Docker и PHP: контейнеризация приложений продвинутого уровня

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Docker и PHP: контейнеризация приложений продвинутого уровня

Контейнеризация с помощью Docker давно стала стандартом для разработки и развертывания PHP-приложений. Базовые знания — запустить контейнер с PHP и Nginx — это лишь первый шаг. На продвинутом уровне требуется настройка многоэтапной сборки, оптимизация размера образов, работа с несколькими сервисами, управление переменными окружения, интеграция с CI/CD и построение микросервисной архитектуры. В этой статье мы разберем ключевые техники, которые помогут вам вывести контейнеризацию PHP на новый уровень.

1. Многоэтапная сборка (Multi-stage builds) для PHP

Многоэтапная сборка позволяет использовать несколько FROM инструкций в одном Dockerfile. Это идеально подходит для PHP-приложений, где на этапе сборки нужны Composer, Node.js и другие инструменты, а в финальный образ должны попасть только скомпилированные файлы и минимальный набор зависимостей.

Пример Dockerfile для Laravel-приложения с многоэтапной сборкой:

# Этап 1: Установка зависимостей и сборка
FROM composer:2.5 AS vendor
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader --no-interaction

FROM node:18 AS frontend
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production
COPY resources/ ./resources/
RUN npm run production

# Этап 2: Финальный образ
FROM php:8.2-fpm-alpine3.18 AS final
WORKDIR /var/www/html

# Установка необходимых PHP-расширений
RUN apk add --no-cache \
        libpng-dev \
        libjpeg-turbo-dev \
        freetype-dev \
        libzip-dev \
        oniguruma-dev \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install -j$(nproc) \
        pdo_mysql \
        mbstring \
        gd \
        zip \
        opcache

# Копирование только необходимых файлов из предыдущих этапов
COPY --from=vendor /app/vendor/ ./vendor/
COPY --from=frontend /app/public/build/ ./public/build/
COPY . .

# Оптимизация для продакшена
RUN php artisan optimize

EXPOSE 9000
CMD ["php-fpm"]

Ключевые преимущества:

  • Финальный образ содержит только runtime-зависимости (PHP-FPM, расширения, код).
  • Инструменты сборки (Composer, Node.js) не попадают в продакшен.
  • Значительное уменьшение размера образа (с 800-900 MB до 150-200 MB).

2. Оптимизация размера Docker-образов для PHP

Маленькие образы быстрее загружаются, требуют меньше места на диске и снижают поверхность атаки. Основные стратегии:

  • Используйте alpine-версии базовых образов. php:8.2-fpm-alpine весит ~50 MB против ~400 MB для стандартного php:8.2-fpm.
  • Минимизируйте количество слоев. Объединяйте команды RUN с помощью &&.
  • Удаляйте временные файлы. После установки расширений чистите кеш: docker-php-source delete и apk del .build-deps.
  • Используйте .dockerignore. Исключите .git, node_modules, tests, .env и другие ненужные файлы.

Пример продвинутого .dockerignore:

.git
.gitignore
.env
.env.example
node_modules
tests
storage/logs/*
!storage/logs/.gitkeep
docker-compose.yml
Makefile
README.md

3. Docker Compose для сложных PHP-проектов

Для приложений на PHP, использующих базы данных, очереди, кеш и веб-сервер, docker-compose.yml становится центральным файлом конфигурации. Продвинутые настройки включают:

  • Сети (networks): изолируйте сервисы (например, база данных не должна быть доступна извне).
  • Тома (volumes): используйте именованные тома для данных БД и анонимные тома для кода в разработке.
  • Healthchecks: проверяйте, что сервисы готовы к работе.
  • Переменные окружения: используйте .env файл и env_file.

Пример расширенного docker-compose.yml для Symfony-проекта:

version: '3.8'

services:
  php:
    build:
      context: .
      target: final
    container_name: app_php
    volumes:
      - ./:/var/www/html:delegated
    networks:
      - app-network
    environment:
      - APP_ENV=prod
      - DATABASE_URL=postgresql://user:pass@db:5432/app?serverVersion=15
    depends_on:
      db:
        condition: service_healthy

  nginx:
    image: nginx:1.25-alpine
    container_name: app_nginx
    ports:
      - "8080:80"
    volumes:
      - ./:/var/www/html:ro
      - ./docker/nginx/conf.d:/etc/nginx/conf.d:ro
    networks:
      - app-network
    depends_on:
      - php

  db:
    image: postgres:15-alpine
    container_name: app_db
    volumes:
      - pgdata:/var/lib/postgresql/data
    networks:
      - app-network
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
      POSTGRES_DB: app
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user -d app"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    container_name: app_redis
    networks:
      - app-network
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 3s
      retries: 3

networks:
  app-network:
    driver: bridge

volumes:
  pgdata:

4. Интеграция с CI/CD и микросервисами на PHP

В продакшене Docker-образы должны собираться автоматически. Для PHP-проектов популярны GitHub Actions, GitLab CI и Jenkins. Пример пайплайна для сборки и публикации образа на PHP:

# .github/workflows                

Блоги

Рекомендаций по книгам