Post

Containerizing PHP Applications with Docker

Containerizing PHP Applications with Docker

Containerizing PHP Applications with Docker

Docker has revolutionized how we deploy and manage applications. In this guide, I’ll show you how to containerize a PHP application, making it easy to develop, test, and deploy consistently across any environment.

Why Containerize PHP Apps?

  • Consistency: Eliminates “works on my machine” problems
  • Isolation: Sandboxes your application dependencies
  • Scalability: Makes horizontal scaling straightforward
  • DevOps Integration: Simplifies CI/CD pipelines

Basic Dockerfile for PHP

Let’s start with a simple Dockerfile for a PHP application:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
FROM php:8.2-apache

# Install dependencies
RUN apt-get update && apt-get install -y \
    libzip-dev \
    zip \
    unzip \
    && docker-php-ext-install zip pdo pdo_mysql

# Enable Apache mod_rewrite
RUN a2enmod rewrite

# Set working directory
WORKDIR /var/www/html

# Copy application files
COPY . .

# Set permissions
RUN chown -R www-data:www-data /var/www/html

Adding Composer

For PHP applications using Composer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
FROM php:8.2-apache

# Install dependencies and extensions
RUN apt-get update && apt-get install -y \
    libzip-dev \
    zip \
    unzip \
    git \
    curl \
    && docker-php-ext-install zip pdo pdo_mysql

# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Enable Apache mod_rewrite
RUN a2enmod rewrite

# Set working directory
WORKDIR /var/www/html

# Copy composer files first to leverage Docker cache
COPY composer.json composer.lock ./
RUN composer install --no-scripts --no-autoloader

# Copy the rest of the application
COPY . .

# Generate optimized autoloader
RUN composer dump-autoload --optimize

# Set permissions
RUN chown -R www-data:www-data /var/www/html

Docker Compose for PHP + MySQL

For applications that need a database, use Docker Compose:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8000:80"
    volumes:
      - ./:/var/www/html
    depends_on:
      - db
    environment:
      DB_HOST: db
      DB_DATABASE: app_db
      DB_USERNAME: app_user
      DB_PASSWORD: app_password

  db:
    image: mysql:8.0
    ports:
      - "3306:3306"
    environment:
      MYSQL_DATABASE: app_db
      MYSQL_USER: app_user
      MYSQL_PASSWORD: app_password
      MYSQL_ROOT_PASSWORD: root_password
    volumes:
      - mysql_data:/var/lib/mysql

volumes:
  mysql_data:

Optimizing for Production

For production environments, you’ll want to optimize your Docker setup:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
FROM php:8.2-fpm as builder

# Install dependencies for building
RUN apt-get update && apt-get install -y \
    libzip-dev \
    zip \
    unzip \
    git \
    curl \
    && docker-php-ext-install zip pdo pdo_mysql opcache

# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Set working directory
WORKDIR /app

# Copy composer files
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --no-autoloader

# Copy application files
COPY . .

# Generate optimized autoloader
RUN composer dump-autoload --optimize --no-dev

# Production image
FROM php:8.2-fpm

# Copy built application
COPY --from=builder /app /var/www/html

# Install production dependencies only
RUN apt-get update && apt-get install -y \
    libzip-dev \
    && docker-php-ext-install zip pdo pdo_mysql opcache

# PHP Configuration
COPY docker/php/production.ini /usr/local/etc/php/conf.d/app.ini

# Set permissions
RUN chown -R www-data:www-data /var/www/html

Security Considerations

  1. Run as non-root user: Add USER www-data at the end of your Dockerfile
  2. Use specific version tags: Avoid latest tags for reproducible builds
  3. Scan images for vulnerabilities: Use tools like Docker Scout or Trivy
  4. Minimize image size: Use multi-stage builds and Alpine-based images
  5. Securely handle environment variables: Never hardcode sensitive data

Debugging with Docker

To debug PHP applications in Docker containers:

  1. Install Xdebug:
1
2
RUN pecl install xdebug \
    && docker-php-ext-enable xdebug
  1. Configure Xdebug:
1
2
3
xdebug.mode=develop,debug
xdebug.client_host=host.docker.internal
xdebug.start_with_request=yes

Conclusion

Containerizing PHP applications with Docker provides consistency, simplifies deployment, and improves development workflows. By following these patterns, you can create efficient and secure containers for your PHP applications, whether they’re simple websites or complex Laravel applications.

This post is licensed under CC BY 4.0 by the author.