PHP Deployment with Docker and CI/CD: A Production Guide
Learn to deploy PHP applications using Docker and CI/CD pipelines.
20+ years shipping production PHP systems at scale. Drawn from code that ran under real load.
- ✓Basic knowledge of PHP and Git
- ✓Docker and Docker Compose installed
- ✓A GitHub account for CI/CD
- ✓A server (or cloud instance) for deployment
- Use multi-stage Docker builds to keep images small.
- Leverage Docker Compose for local development and testing.
- Implement CI/CD pipelines (e.g., GitHub Actions) for automated testing and deployment.
- Use environment variables for configuration and secrets.
- Monitor and log your containers in production.
Think of Docker as a shipping container for your app. It packages everything your app needs (code, dependencies, settings) into a standardized box that runs the same way anywhere. CI/CD is like an automated assembly line: you push code changes, and the pipeline automatically tests, builds, and ships the container to your servers.
Deploying PHP applications can be a headache. Different environments, missing extensions, configuration drift – these issues plague developers. Docker solves this by packaging your application with all its dependencies into a portable container. Combined with a CI/CD pipeline, you can automate testing, building, and deployment, ensuring every release is consistent and reliable.
In this tutorial, you'll learn how to containerize a PHP application with Docker, optimize your Dockerfile for production, set up a CI/CD pipeline using GitHub Actions, and deploy to a server. We'll cover real-world scenarios like handling environment variables, secrets, and zero-downtime deployments. By the end, you'll have a robust deployment workflow that scales from a single server to a cluster.
This guide assumes you're familiar with PHP basics, Git, and have a basic understanding of Docker. We'll use a simple Laravel application as an example, but the principles apply to any PHP framework or plain PHP app.
1. Dockerizing a PHP Application
The first step is to create a Dockerfile that builds a production-ready image. We'll use a multi-stage build to keep the image small. The first stage installs Composer dependencies and compiles assets; the second stage copies only the necessary files.
Here's an example Dockerfile for a Laravel application:
2. Docker Compose for Local Development
Docker Compose allows you to define and run multi-container Docker applications. For a PHP app, you typically need PHP-FPM, Nginx, and a database. Here's a docker-compose.yml for local development:
3. Setting Up a CI/CD Pipeline with GitHub Actions
A CI/CD pipeline automates testing, building, and deploying your application. We'll use GitHub Actions. Create a workflow file in .github/workflows/deploy.yml:
- Run tests on every push
- Build a Docker image
- Push the image to Docker Hub (or a registry)
- Deploy to a server via SSH
4. Environment Variables and Secrets Management
Managing configuration and secrets is critical. Use environment variables for non-sensitive config (e.g., DB_HOST) and secrets for sensitive data (e.g., API keys). In Docker, pass them via -e or an env_file.
For production, use Docker secrets (Swarm) or a secrets manager like HashiCorp Vault. Here's how to use an .env file with Docker Compose:
5. Optimizing PHP-FPM and Nginx for Production
Performance tuning is essential. Configure PHP-FPM to use the right number of workers based on your server's memory. Use the 'ondemand' process manager for low-traffic sites, or 'dynamic' for consistent load.
Nginx should serve static files directly and proxy PHP requests to FPM. Enable gzip compression and caching headers.
6. Zero-Downtime Deployments with Docker
Zero-downtime deployments ensure your application remains available during updates. With Docker, you can use rolling updates or blue-green deployments. Docker Compose supports rolling updates with the 'deploy' configuration.
For a simple approach, use a reverse proxy like Traefik or Nginx to switch between two versions of your app. Here's a basic blue-green deployment script:
7. Monitoring and Logging in Production
Monitoring is crucial for production. Use Docker's logging drivers to collect logs (e.g., json-file, syslog, or third-party like Logstash). For metrics, use Prometheus and Grafana.
Here's how to configure centralized logging with the ELK stack (Elasticsearch, Logstash, Kibana) using Docker Compose:
8. Security Best Practices
- Run containers as a non-root user.
- Use read-only root filesystem where possible.
- Regularly update base images.
- Scan images for vulnerabilities with tools like Trivy.
- Use secrets management for sensitive data.
- Limit network exposure; only expose necessary ports.
Here's how to run PHP-FPM as a non-root user:
The Case of the Bloated Docker Image
- Always use multi-stage builds to separate build and runtime environments.
- Keep production images minimal – only include what's necessary to run the app.
- Use .dockerignore to exclude unnecessary files (e.g., node_modules, .git).
- Regularly audit image sizes and prune unused images.
docker logs <container>docker inspect <container>| File | Command / Code | Purpose |
|---|---|---|
| Dockerfile | FROM composer:2 AS build | 1. Dockerizing a PHP Application |
| docker-compose.yml | version: '3.8' | 2. Docker Compose for Local Development |
| .github | name: Deploy to Production | 3. Setting Up a CI/CD Pipeline with GitHub Actions |
| .env | DB_HOST=db | 4. Environment Variables and Secrets Management |
| nginx.conf | server { | 5. Optimizing PHP-FPM and Nginx for Production |
| deploy.sh | CURRENT=$(docker ps --filter "name=app-green" -q) | 6. Zero-Downtime Deployments with Docker |
| docker-compose.monitoring.yml | version: '3.8' | 7. Monitoring and Logging in Production |
| Dockerfile (excerpt) | FROM php:8.2-fpm-alpine | 8. Security Best Practices |
Key takeaways
Common mistakes to avoid
5 patternsIncluding development dependencies in the production image.
Hardcoding environment variables in Dockerfile or docker-compose.yml.
Running containers as root.
Not using .dockerignore.
Ignoring health checks.
Interview Questions on This Topic
Explain multi-stage Docker builds and why they are important for PHP applications.
Frequently Asked Questions
20+ years shipping production PHP systems at scale. Drawn from code that ran under real load.
That's Advanced PHP. Mark it forged?
3 min read · try the examples if you haven't