Php Docker Deployment
title: PHP Docker Deployment — Complete Guide to Containerizing PHP Apps description: 'Learn PHP Docker deployment: Dockerfile for PHP apps, docker-compose with Nginx/MySQL, environment configuration, multi-stage builds, CI/CD, and production best practices.' date: 2026-06-28 lastmod: 2026-06-28 weight: 44 tags: [backend, php]
PHP Docker deployment packages applications into portable containers with Nginx, PHP-FPM, MySQL, and Redis, ensuring consistent environments across development, staging, and production.
## What You'll Learn
By the end of this tutorial, you'll create Dockerfiles for PHP apps, configure docker-compose with Nginx and MySQL, use environment variables, implement multi-stage builds, and deploy to production.
## Real-World Use
A SaaS platform runs Docker containers on AWS ECS. Each microservice (API, admin, workers) runs in separate containers. Deployments are zero-downtime rolling updates.
## Docker Deployment Learning Path
```mermaid
flowchart LR
A[Performance] --> B[Docker/Deploy]
B --> C[Project]
C --> D[Next Steps]
B --> E{You Are Here}
style E fill:#f90,color:#fff
Dockerfile
FROM php:8.3-fpm-alpine AS base
RUN docker-php-ext-install pdo_mysql opcache
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader
COPY . .
RUN chown -R www-data:www-data storage/ bootstrap/cache/
FROM base AS development
RUN pecl install xdebug && docker-php-ext-enable xdebug
RUN composer install
CMD ["php-fpm"]
FROM base AS production
RUN rm -rf tests/ docker/
CMD ["php-fpm"]
docker-compose.yml
services:
app:
build:
context: .
target: development
volumes:
- .:/var/www/html
depends_on:
- mysql
- redis
environment:
- APP_ENV=local
- DB_HOST=mysql
- DB_DATABASE=myapp
- DB_USERNAME=myapp
- DB_PASSWORD=secret
nginx:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- .:/var/www/html
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- app
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: myapp
MYSQL_USER: myapp
MYSQL_PASSWORD: secret
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:alpine
volumes:
mysql_data:
Nginx Configuration
server {
listen 80;
root /var/www/html/public;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass app:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Environment Configuration
<?php
// .env
APP_ENV=production
APP_DEBUG=false
DB_HOST=mysql
DB_DATABASE=myapp
DB_USERNAME=myapp
DB_PASSWORD=secret
REDIS_HOST=redis
<?php
// config.php
$env = parse_ini_file(__DIR__ . "/.env");
$dbHost = $env["DB_HOST"] ?? "localhost";
$dbName = $env["DB_DATABASE"] ?? "myapp";
$dsn = "mysql:host=$dbHost;dbname=$dbName;charset=utf8mb4";
$pdo = new PDO($dsn, $env["DB_USERNAME"], $env["DB_PASSWORD"]);
Production Deployment
# Build production image
docker build --target production -t myapp:latest .
# Push to registry
docker tag myapp:latest registry.example.com/myapp:v1.0
docker push registry.example.com/myapp:v1.0
# Deploy
docker-compose -f docker-compose.prod.yml up -d
# Zero-downtime deployment
docker service update --image registry.example.com/myapp:v1.0 myapp_service
Common Mistakes
1. Hardcoding Configuration
Never hardcode database credentials, API keys, or secrets in Dockerfiles. Use environment variables.
2. Running as Root
Containers running as root are security risks. Use USER www-data or a non-root user in the Dockerfile.
3. Ignoring .dockerignore
Without .dockerignore, the build context includes vendor/, tests/, and .git, making builds slow.
4. Not Using Multi-Stage Builds
Development dependencies (Xdebug, dev tools) shouldn't be in production images. Use multi-stage builds.
5. Volumes for Production
Don't mount source code as volumes in production. The image should contain all application code.
Practice Questions
1. Why use multi-stage Docker builds?
Separate build dependencies (Composer, NPM) from runtime. Production images are smaller and more secure.
2. How do you handle database migrations in Docker?
Run migrations as part of the entrypoint or in a separate run-once job before starting the app.
3. What is the difference between CMD and ENTRYPOINT?
CMD provides default arguments. ENTRYPOINT is the main command. Combined: ENTRYPOINT ["php-fpm"] with CMD ["-d", "memory_limit=256M"].
4. How do you debug a running container?
docker exec -it container_name bash, check logs with docker logs, or use Xdebug with remote_host.
5. Challenge: Create a production docker-compose.yml with health checks.
services:
app:
build:
context: .
target: production
healthcheck:
test: ["CMD", "php-fpm", "-t"]
interval: 30s
timeout: 10s
retries: 3
nginx:
image: nginx:alpine
ports: ["80:80"]
depends_on:
app:
condition: service_healthy
FAQ
Mini Project: Dockerized PHP App
Create a complete docker-compose setup for a PHP application with Nginx, MySQL, and Redis.
mkdir my-docker-app && cd my-docker-app
echo '<?php echo "Hello from Docker!"; ?>' > public/index.php
# Create Dockerfile, docker-compose.yml, and nginx config as shown above
docker compose up -d
curl http://localhost:8080
# Output: Hello from Docker!
What's Next
PHP Project
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro