Skip to content

Php Docker Deployment

DodaTech 4 min read

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

Do I need Docker for PHP development?

Not required, but Docker ensures consistent environments across team members and eliminates 'works on my machine' problems.

What base image should I use?

php:8.3-fpm-alpine is recommended. It's small (30MB), secure, and has the PHP extensions you need.

How do I handle file permissions in Docker?

Use a non-root user (www-data). Match the user ID with the host user to avoid permission issues with mounted volumes.

What is the best way to serve static files?

Use Nginx to serve static files directly. Don't route static assets through PHP-FPM.

How do I set up HTTPS in Docker?

Use a reverse proxy like Traefik or Nginx with Let's Encrypt. Or terminate TLS at the load balancer (AWS ALB).

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