Docker and PHP: Advanced Application Containerization Techniques

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Docker and PHP: Advanced-Level Application Containerization



Containerization of PHP applications using Docker has long ceased to be just a convenient development tool. At an advanced level, it is the key to creating scalable, secure, and reproducible environments. In this article, we will explore techniques that will help you move from basic PHP container startup to professional orchestration: multi-stage builds, image optimization, working with Docker Compose for microservice architecture, and advanced caching.



1. Multi-Stage Build: Minimal Final Image



One of the main problems with standard Docker images is their size. The base php:8.2-apache image weighs over 400 MB, and with extensions installed, it reaches 600+. This is unacceptable for production: a large image loads slower, takes up registry space, and increases the attack surface.



Multi-stage build allows you to split the process into stages: one for compiling and installing dependencies (with a full set of tools), and a second for a minimal runtime. The final image contains only compiled artifacts and necessary libraries.



Example Dockerfile for a Laravel application:



# Stage 1: Compilation and dependency installationFROM composer:latest AS vendorWORKDIR /appCOPY composer.json composer.lock ./RUN composer install --no-dev --optimize-autoloader --no-interaction

# Stage 2: Building Node resources (if there is a frontend)FROM node:18-alpine AS frontendWORKDIR /appCOPY package.json package-lock.json ./RUN npm ci --productionCOPY resources/ ./resources/RUN npm run production

# Stage 3: Final PHP imageFROM php:8.2-fpm-alpine AS productionRUN docker-php-ext-install pdo_mysql opcacheCOPY --from=vendor /app/vendor /var/www/html/vendorCOPY --from=frontend /app/public/build /var/www/html/public/buildCOPY . /var/www/html

RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cacheEXPOSE 9000CMD ["php-fpm"]


This approach reduces the image size from 500+ MB to ~120 MB. composer:latest and node:18-alpine are used only during the build stages and do not end up in the final layer.



2. Optimizing Docker Layer Caching



Each instruction in a Dockerfile creates a layer. To speed up rebuilds, you should place rarely changing layers as early as possible. For a PHP project, this means:



  • Copy composer.json and composer.lock before copying the code.
  • Run composer install before copying the source files.
  • Copy the code last.


Example of an optimized instruction order:



FROM php:8.2-fpm-alpine AS baseWORKDIR /var/www/html

# Install system dependencies onceRUN apk add --no-cache $PHPIZE_DEPS \ && docker-php-ext-install pdo_mysql opcache bcmath

# Copy only dependency filesCOPY composer.json composer.lock ./RUN composer install --no-dev --no-interaction --no-scripts --prefer-dist

# Copy the rest of the codeCOPY . .

# Generate autoloader and optimizeRUN composer dump-autoload --optimize


Tip: use .dockerignore to exclude vendor, .git, node_modules, and other temporary files from the build context. This will speed up context transfer to the Docker daemon.



3. Docker Compose for Microservice Architecture



Modern PHP applications rarely consist of a single service. A typical architecture includes PHP-FPM, Nginx, Redis, a task queue (RabbitMQ/Beanstalkd), and a database. Docker Compose allows you to describe the entire infrastructure in a single docker-compose.yml.



Example configuration for a PHP microservice:



version: '3.8'services:  app:    build:      context: .      target: production                

Blogs

Book Recommendations