Если ваш PHP-проект до сих пор разворачивается вручную на сервере с помощью FTP и магии, а слово «Docker» вызывает смешанные чувства, эта статья для вас. Мы разберём, как перевести типичное PHP-приложение в контейнеры, не сломав продакшен и не поседев за ночь.
Зачем вообще нужен Docker в PHP?
PHP-разработка исторически славилась «зоопарком» версий: на одном сервере PHP 5.6, на другом — 7.4, а у коллеги на локалке — 8.2. Docker решает эту проблему раз и навсегда. Вы описываете окружение в файле, и оно одинаково запускается везде: на ноутбуке, в CI/CD и на продакшене.
Кроме того, контейнеры изолируют зависимости. Больше не нужно переживать, что обновление библиотеки для одного проекта сломает другой. Каждый сервис живёт в своём «пузыре».
Создаём Dockerfile для PHP-приложения
Начнём с базового образа. Для типичного Laravel или Symfony-проекта понадобится PHP с расширениями и Composer. Вот пример Dockerfile:
FROM php:8.2-fpm
RUN apt-get update && apt-get install -y \
git \
unzip \
libpng-dev \
libonig-dev \
libxml2-dev \
&& docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html
COPY . .
RUN composer install --no-interaction --optimize-autoloader --no-dev
RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache
EXPOSE 9000
CMD ["php-fpm"]
Этот Dockerfile делает несколько вещей: устанавливает системные зависимости, расширения PHP, Composer, копирует код и ставит зависимости. Обратите внимание на --no-dev — для продакшена dev-зависимости не нужны.
Настраиваем docker-compose для локальной разработки
Один контейнер — это скучно. Настоящий PHP-проект обычно требует базу данных, Redis, возможно, Nginx. Docker Compose позволяет описать всё в одном YAML-файле. Пример для Laravel:
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
volumes:
- .:/var/www/html
depends_on:
- db
- redis
environment:
- DB_HOST=db
- REDIS_HOST=redis
web:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- .:/var/www/html
- ./nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- app
db:
image: mysql:8.0
environment:
MYSQL_DATABASE: laravel
MYSQL_ROOT_PASSWORD: secret
volumes:
- dbdata:/var/lib/mysql
redis:
image: redis:alpine
volumes:
dbdata:
Здесь мы определили четыре сервиса: PHP-FPM, Nginx, MySQL и Redis. Том dbdata сохраняет данные базы между перезапусками. Для локальной разработки удобно монтировать код внутрь контейнера — изменения сразу видны без пересборки.
Оптимизация и подготовка к продакшену
Для продакшена подход немного меняется. Во-первых, не монтируйте код — копируйте его в образ при сборке. Во-вторых, используйте многоступенчатую сборку, чтобы уменьшить размер образа. Вот пример оптимизированного Dockerfile:
# Стадия сборки
FROM composer:2 AS vendor
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --no-autoloader --prefer-dist
# Финальный образ
FROM php:8.2-fpm-alpine
RUN apk add --no-cache \
libpng-dev \
libzip-dev \
&& docker-php-ext-install pdo_mysql mbstring zip gd
WORKDIR /var/www/html
COPY --from=vendor /app/vendor ./vendor
COPY . .
RUN composer dump-autoload --optimize --no-dev
RUN chown -R www-data:www-data storage bootstrap/cache
USER www-data
EXPOSE 9000
CMD ["php-fpm"]
Обратите внимание на USER www-data — контейнер не должен работать от root. Это базовое правило безопасности.
Сравнение подходов: что выбрать?
При миграции часто встаёт вопрос: использовать готовые образы (например, bitnami/php-fpm) или писать свой Dockerfile? Вот краткая таблица для сравнения:
| Критерий | Свой Dockerfile | Готовый образ |
|---|---|---|
| Гибкость | Высокая | Ограниченная |
| Время настройки | Больше | Меньше |
| Размер образа | Контролируемый | Может быть большим |
| Безопасность | Зависит от вас | Обновляется сообществом |
Для большинства проектов оптимален свой Dockerfile на основе официального образа PHP. Это даёт баланс между контролем и удобством.
Что в итоге?
Миграция PHP-проекта на Docker — это не страшно, если действовать поэтапно. Начните с локальной разработки, напишите простой Dockerfile, добавьте docker-compose с базой данных. Затем оптимизируйте образ для продакшена: многоступенчатая сборка, непривилегированный пользователь, .dockerignore.
В результате вы получите воспроизводимое окружение, лёгкое масштабирование и меньше головной боли при деплое. Docker не решит все проблемы, но точно сделает вашу жизнь проще.


