Docker и PHP: контейнеризация приложений от А до Я
Контейнеризация PHP-приложений с помощью Docker стала стандартом современной веб-разработки. Независимо от того, создаете ли вы простой лендинг или сложное корпоративное приложение, Docker обеспечивает единообразие окружения на всех этапах: от локальной разработки до продакшена. В этой статье мы разберем все этапы создания Docker-инфраструктуры для PHP-приложения — от базового Dockerfile до полноценного стека с Nginx и MySQL.
Почему Docker важен для PHP-разработчика
Традиционная PHP-разработка часто сталкивается с проблемой "на моей машине работает". Разные версии PHP, расширения, настройки сервера — все это приводит к конфликтам. Docker решает эту проблему раз и навсегда:
- Изоляция окружения — каждое приложение имеет свой набор зависимостей
- Воспроизводимость — одинаковое окружение на всех машинах
- Масштабируемость — легко добавлять новые сервисы (Redis, Elasticsearch)
- CI/CD интеграция — контейнеры идеально подходят для пайплайнов
Давайте перейдем от теории к практике и создадим полноценное Docker-окружение для PHP-приложения.
Создание базового Dockerfile для PHP
Начнем с самого главного — Dockerfile. Это инструкция по сборке образа вашего PHP-приложения. Вот оптимальная конфигурация для production-ready приложения:
# Используем официальный PHP образ с FPM
FROM php:8.2-fpm-alpine
# Установка системных зависимостей
RUN apk add --no-cache \
git \
unzip \
libpq-dev \
libzip-dev \
&& docker-php-ext-install \
pdo_mysql \
zip \
opcache
# Установка Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Настройка OPcache для продакшена
RUN { \
echo 'opcache.memory_consumption=128'; \
echo 'opcache.interned_strings_buffer=8'; \
echo 'opcache.max_accelerated_files=4000'; \
echo 'opcache.revalidate_freq=2'; \
echo 'opcache.fast_shutdown=1'; \
echo 'opcache.enable_cli=1'; \
} > /usr/local/etc/php/conf.d/opcache.ini
# Копируем файлы приложения
WORKDIR /var/www/html
COPY . .
# Устанавливаем права
RUN chown -R www-data:www-data /var/www/html \
&& chmod -R 755 storage bootstrap/cache
# Запускаем PHP-FPM
CMD ["php-fpm"]
EXPOSE 9000
Этот Dockerfile использует Alpine Linux — минимальный образ, который значительно уменьшает размер конечного контейнера. Мы устанавливаем только необходимые расширения: pdo_mysql для работы с базой данных и zip для Composer.
Сборка и запуск контейнера
# Сборка образа
docker build -t my-php-app .
# Запуск контейнера
docker run -d -p 9000:9000 --name php-app my-php-app
Полный стек с Nginx и MySQL через docker-compose
Реальное приложение редко состоит из одного PHP-контейнера. Нам нужен веб-сервер и база данных. Здесь на помощь приходит docker-compose — инструмент для оркестрации нескольких контейнеров.
Создадим файл docker-compose.yml:
version: '3.8'
services:
# PHP-FPM сервис
app:
build:
context: .
dockerfile: Dockerfile
container_name: php-app
volumes:
- ./:/var/www/html
networks:
- app-network
# Nginx веб-сервер
nginx:
image: nginx:alpine
container_name: php-nginx
ports:
- "8080:80"
volumes:
- ./:/var/www/html
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- app
networks:
- app-network
# MySQL база данных
db:
image: mysql:8.0
container_name: php-mysql
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root_password
MYSQL_DATABASE: app_database
MYSQL_USER: app_user
MYSQL_PASSWORD: app_password
volumes:
- mysql_data:/var/lib/mysql
networks:
- app-network
volumes:
mysql_data:
networks:
app-network:
driver: bridge
Конфигурация Nginx
Создадим файл docker/nginx/default.conf для связки Nginx с PHP-FPM:
server {
listen 80;
index index.php index.html;
server_name localhost;
root /var/www/html/public;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass app:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}
Запуск полного стека
# Запуск всех сервисов
docker-compose up -d
# Просмотр логов
docker-compose logs -f
# Остановка сервисов
docker-compose down
Работа с Composer в контейнере
Управление зависимостями через Composer — неотъемлемая часть PHP-разработки. Docker упрощает этот процесс:
# Установка зависимостей через контейнер
docker run --rm \
-v $(pwd):/app \
composer:latest \
composer install --no-dev --optimize-autoloader
# Запуск artisan команд (для Laravel)
docker exec php-app php artisan migrate
docker exec php-app php artisan cache:clear
docker exec php-app php artisan config:cache
Пример PHP-приложения для теста
Создадим простой скрипт public/index.php для проверки работы стека:
<?php
// Проверка соединения с MySQL
try {
$pdo = new PDO(
'mysql:host=db;dbname=app_database',
'app_user',
'app_password'
);
$connectionStatus = '✅ Подключение к MySQL успешно!';
} catch (PDOException $e) {
$connectionStatus = '❌ Ошибка подключения: ' . $e->getMessage();
}
// Информация о PHP
$phpVersion = phpversion();
$extensions = get_loaded_extensions();
$requiredExtensions = ['pdo_mysql', 'zip', 'opcache'];
$extensionStatus = [];
foreach ($requiredExtensions as $ext) {
$extensionStatus[$ext] = in_array($