Контейнеризация PHP приложений с Docker: полный гайд для разработчика

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

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

Начать курс

Почему каждый PHP-разработчик должен освоить Docker?

Вы когда-нибудь сталкивались с ситуацией, когда локально всё работает идеально, а на сервере — «белый экран смерти»? Или, что ещё хуже, когда коллега говорит: «У меня всё работает, обнови composer» — и ваш проект превращается в тыкву? Знакомо? Тогда добро пожаловать в мир контейнеризации PHP приложений с Docker.

Docker — это не просто модный buzzword. Это инструмент, который навсегда изменит ваш подход к разработке. Представьте: вы больше не тратите часы на настройку окружения. Не нужно ставить XAMPP, OpenServer или мучиться с версиями PHP. Один docker-compose up — и ваше приложение живёт в изолированном, предсказуемом мире. И этот мир можно передать коллеге, залить на сервер или даже продать заказчику. В этой статье мы разберём контейнеризацию PHP приложений от А до Я: от базового Dockerfile до продакшен-оптимизации.

Что такое контейнеризация и зачем она PHP?

Контейнеризация — это способ упаковки приложения вместе со всеми его зависимостями (PHP, расширениями, веб-сервером, базой данных) в изолированную среду — контейнер. В отличие от виртуальных машин, контейнеры легковесны, запускаются за секунды и потребляют минимум ресурсов.

Для PHP это особенно актуально. Почему? Потому что типичное PHP-приложение — это связка: PHP-FPM, Nginx или Apache, MySQL/PostgreSQL, Redis, очередь задач. Ручная настройка этой экосистемы на каждой машине — ад. А с Docker вы описываете всю инфраструктуру в коде (Infrastructure as Code) и воспроизводите её одной командой.

Основные преимущества контейнеризации для PHP-разработчика:

  • Единообразие окружений: локальная среда = стейджинг = продакшен. Забудьте про «у меня работает».
  • Изоляция зависимостей: проект на PHP 7.4 спокойно соседствует с проектом на PHP 8.3 на одном хост-компьютере.
  • Быстрое развёртывание: достаточно запушить образ в registry и обновить контейнер на сервере.
  • Масштабируемость: легко добавить ещё один контейнер с PHP-FPM под нагрузкой.

Создаём первый Dockerfile для PHP-приложения

Начнём с самого главного — Dockerfile. Это инструкция по сборке образа вашего приложения. Предположим, у нас есть простое PHP-приложение на Laravel или Symfony (принцип одинаков для любого фреймворка).

# Используем официальный образ PHP 8.2 с FPM
FROM php:8.2-fpm-alpine

# Устанавливаем системные зависимости
RUN apk add --no-cache \
    nginx \
    supervisor \
    libpng-dev \
    libjpeg-turbo-dev \
    freetype-dev \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install -j$(nproc) pdo_mysql gd opcache

# Копируем конфиги
COPY ./docker/nginx.conf /etc/nginx/http.d/default.conf
COPY ./docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY ./docker/php.ini /usr/local/etc/php/conf.d/custom.ini

# Устанавливаем Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Копируем исходный код приложения
COPY . /var/www/html
WORKDIR /var/www/html

# Устанавливаем зависимости PHP
RUN composer install --no-dev --optimize-autoloader

# Права доступа
RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache

EXPOSE 80

CMD ["supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]

Разбираем по полочкам:

  • FROM php:8.2-fpm-alpine — берём лёгкий образ на базе Alpine Linux. Он весит ~50 МБ вместо 200+ МБ у десктопных образов.
  • docker-php-ext-install — магическая команда для установки расширений PHP прямо внутри контейнера.
  • COPY --from=composer:latest — мультистейдж-сборка. Мы берём готовый бинарник Composer из официального образа, не устанавливая PHP отдельно.
  • supervisord — менеджер процессов, который будет держать Nginx и PHP-FPM живыми внутри одного контейнера (для простоты). В продакшене лучше разделять сервисы.

Docker Compose: оркестровка нескольких контейнеров

Один контейнер — это круто, но в реальном приложении нужны база данных, кэш и, возможно, очередь. docker-compose.yml позволяет описать всю экосистему в одном файле.

version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "80:80"
    volumes:
      - ./storage:/var/www/html/storage
    depends_on:
      - db
      - redis
    environment:
      - DB_HOST=db
      - REDIS_HOST=redis

  db:
    image: mysql:8.0
    volumes:
      - db_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: app
      MYSQL_USER: app
      MYSQL_PASSWORD: secret
    ports:
      - "3306:3306"

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"

volumes:
  db_data:

Запускаем одной командой: docker-compose up -d. Всё — у вас работает PHP, Nginx, MySQL и Redis. И это воспроизводимо на любой машине, где есть Docker.

Полезные трюки для PHP-разработчика:

  • Xdebug в контейнере: добавьте в Dockerfile pecl install xdebug и настройте remote_host. Никаких больше костылей.
  • Hot-reload для разработки: используйте volume для монтирования исходников: .:/var/www/html. Меняете код — изменения сразу видны.
  • Переменные окружения: выносите настройки БД, API-ключи в .env и передавайте через environment в compose-файле.

Оптимизация для продакшена: делаем образ лёгким и безопасным

Контейнеризация PHP приложений для продакшена требует особого подхода. Нельзя просто взять образ для разработки и залить на сервер. Вот несколько обязательных шагов.

1. Мультистейдж-сборка

Собирайте зависимости в одном образе, а копируйте результат в чистый, минимальный образ. Это уменьшает размер в 2-3 раза.

# Этап сборки
FROM composer:2 AS composer
COPY . /app
RUN composer install --no-dev --optimize-autoloader

# Финальный образ
FROM php:8.2-fpm-al                

Блоги

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