When writing Dockerfiles for PHP and MySQL, it's important to focus on security, efficiency, and maintainability. Here are some best practices specific to Dockerfiles for PHP and MySQL environments:
1. Use Official Base Images
- Why: Official Docker images for PHP and MySQL are regularly updated and optimized for performance and security. Always use these as your base.
- 
Example: 
 FROM php:7.4-fpm FROM mysql:8.0
2. Minimize PHP Extensions and Packages
- Why: Install only the necessary PHP extensions and Linux packages to keep your image lightweight and reduce potential security vulnerabilities.
- 
Example: 
 RUN apt-get update && apt-get install -y \ libpng-dev \ libjpeg-dev \ libfreetype6-dev \ && docker-php-ext-configure gd --with-freetype --with-jpeg \ && docker-php-ext-install gd
3. Optimize PHP Configuration
- 
Why: Customize your PHP configuration to suit your application’s needs. Use environment variables or copy custom php.inifiles to configure settings like memory limits, error reporting, and upload sizes.
- 
Example: 
 COPY php.ini /usr/local/etc/php/
4. Leverage Multi-Stage Builds for PHP
- Why: Use multi-stage builds to separate the build environment (e.g., compiling PHP extensions) from the final runtime environment. This keeps the final image lean and secure.
- 
Example: 
 FROM php:7.4-fpm AS builder WORKDIR /usr/src/php/ext RUN docker-php-ext-install pdo_mysql FROM php:7.4-fpm COPY --from=builder /usr/local/lib/php/extensions/no-debug-non-zts-20190902/pdo_mysql.so /usr/local/lib/php/extensions/no-debug-non-zts-20190902/ RUN docker-php-ext-enable pdo_mysql
5. Configure MySQL for Production
- Why: Use environment variables to configure MySQL in a way that’s optimized for production. Avoid hardcoding credentials and use Docker secrets or environment variables instead.
- 
Example: 
 ENV MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} ENV MYSQL_DATABASE=mydatabase ENV MYSQL_USER=myuser ENV MYSQL_PASSWORD=${MYSQL_PASSWORD}
6. Persist MySQL Data Using Volumes
- Why: To avoid data loss, persist MySQL data outside the container using Docker volumes. This ensures your data is safe even if the container is removed.
- 
Example: 
 version: '3.8' services: db: image: mysql:8.0 volumes: - db_data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: example MYSQL_DATABASE: exampledb volumes: db_data:
  
  
  7. Use .dockerignore for PHP Projects
- 
Why: Exclude unnecessary files and directories (e.g., node_modules,.git,tests, etc.) from being copied into the Docker image, reducing the build context and resulting image size.
- 
Example: 
 .git node_modules tests .env
8. Keep the Image Lean
- Why: Remove unnecessary dependencies and temporary files after installation to minimize the image size.
- 
Example: 
 RUN apt-get update && apt-get install -y \ libzip-dev \ && docker-php-ext-install zip \ && apt-get clean \ && rm -rf /var/lib/apt/lists/*
9. Use Supervisord for Managing Multiple Processes
- 
Why: If your PHP container needs to run multiple services (e.g., PHP-FPM and a cron job), use supervisordto manage them efficiently.
- 
Example: 
 RUN apt-get update && apt-get install -y supervisor COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf CMD ["supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
10. Enable OPCache for PHP
- Why: Enabling OPCache improves PHP performance by caching the compiled bytecode of PHP scripts, reducing the need for PHP to recompile the scripts on each request.
- 
Example: 
 RUN docker-php-ext-install opcache COPY opcache.ini /usr/local/etc/php/conf.d/opcache.ini
11. Separate Application Code and Configuration
- 
Why: Keep your application code and configuration files (like php.iniormy.cnf) separate to allow easy updates and better management.
- 
Example: 
 COPY src/ /var/www/html/ COPY php.ini /usr/local/etc/php/
12. Health Checks
- Why: Use Docker's health check functionality to monitor the health of your PHP and MySQL containers, ensuring they are running correctly.
- 
Example: 
 HEALTHCHECK --interval=30s --timeout=10s --retries=3 \ CMD curl -f http://localhost/health || exit 1
Conclusion
By following these best practices, you can create Dockerfiles that produce efficient, secure, and maintainable containers for your PHP and MySQL projects. This will result in a smoother development process and more stable production environments.
Contact Links
If you found this series helpful, please consider giving the repository a star on GitHub or sharing the post on your favorite social networks 😍. Your support would mean a lot to me!

If you want more helpful content like this, feel free to follow me:
 
 
              
 
    
Top comments (1)
There are some bad practices in your list :-/ Allow me to lean in:
apt-getto run.versionkey, it's been deprecated for years. As for using DB inside a container, this is contencious. Many Ops will scream in horror due to the inefficiency and how unsafe it is to manage it. In a dev environement it's ok; in production, shouldn't happen. And the volume doesn't guarantee persistency. Anyone who fought with a problematic compose deployment knows how quick it is todocker compose down -v:o)Dockerfilein this.cronstuff, let an other container take that responsibility.exit 1?(If you're interested in sources of my claims, I'll provide)