Зачем нужна контейнеризация PHP-приложений с Docker?
Современная веб-разработка на PHP редко обходится без использования контейнеризации. Docker позволяет упаковать ваше приложение со всеми зависимостями (веб-сервер, расширения PHP, база данных) в изолированный контейнер. Это гарантирует, что приложение будет работать одинаково на локальной машине разработчика, на сервере тестирования и в production-среде. В этой статье мы разберем, как правильно настроить Docker для PHP, создадим готовый проект и рассмотрим лучшие практики.
Преимущества использования Docker с PHP
- Воспроизводимость окружения: забудьте о проблеме "на моей машине работает".
- Изоляция: каждое приложение живет в своем контейнере с нужными версиями PHP и библиотек.
- Масштабирование: легко запустить несколько экземпляров приложения с помощью docker-compose.
- Упрощение CI/CD: контейнеры идеально подходят для пайплайнов автоматической сборки и деплоя.
Создание Dockerfile для PHP-приложения
Начнем с самого главного — файла Dockerfile. Он описывает, как будет собран образ вашего PHP-приложения. Рассмотрим базовый пример для приложения на PHP 8.2 с веб-сервером Apache.
# Dockerfile
FROM php:8.2-apache
# Установка расширений PHP
RUN docker-php-ext-install pdo pdo_mysql mysqli
# Включение mod_rewrite для Apache (полезно для фреймворков)
RUN a2enmod rewrite
# Копирование исходного кода приложения
COPY . /var/www/html/
# Смена владельца для правильных прав доступа
RUN chown -R www-data:www-data /var/www/html
# Открываем порт 80
EXPOSE 80
Этот Dockerfile берет официальный образ PHP 8.2 с Apache, устанавливает драйверы для MySQL и копирует ваш код. Для более сложных проектов, например, на Laravel или Symfony, потребуется дополнительная настройка.
Пример для Laravel с Nginx и PHP-FPM
Для современных фреймворков часто используют связку Nginx + PHP-FPM. Вот пример Dockerfile для PHP-FPM:
# Dockerfile.php-fpm
FROM php:8.2-fpm
# Установка системных зависимостей и расширений
RUN apt-get update && apt-get install -y \
libpq-dev \
libzip-dev \
unzip \
git \
&& docker-php-ext-install pdo pdo_mysql zip
# Установка Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Копирование проекта
WORKDIR /var/www
COPY . .
# Установка зависимостей PHP
RUN composer install --no-interaction --optimize-autoloader
# Права доступа для Laravel
RUN chown -R www-data:www-data /var/www/storage /var/www/bootstrap/cache
CMD ["php-fpm"]
А вот конфигурация Nginx, которую нужно будет поместить в отдельный контейнер через docker-compose:
# default.conf (для Nginx)
server {
listen 80;
server_name localhost;
root /var/www/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
index index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
Оркестрация с помощью docker-compose
Для управления несколькими контейнерами (PHP, Nginx, MySQL) используйте docker-compose.yml. Это стандартный инструмент для локальной разработки и тестирования.
# docker-compose.yml
version: '3.8'
services:
php:
build:
context: .
dockerfile: Dockerfile.php-fpm
container_name: php-app
volumes:
- .:/var/www
networks:
- app-network
nginx:
image: nginx:alpine
container_name: nginx-server
ports:
- "8080:80"
volumes:
- .:/var/www
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- php
networks:
- app-network
mysql:
image: mysql:8.0
container_name: mysql-db
restart: unless-stopped
environment:
MYSQL_DATABASE: app_db
MYSQL_ROOT_PASSWORD: root_password
MYSQL_USER: app_user
MYSQL_PASSWORD: app_password
ports:
- "3306:3306"
volumes:
- db_data:/var/lib/mysql
networks:
- app-network
volumes:
db_data:
networks:
app-network:
driver: bridge
Теперь, чтобы запустить весь стек, достаточно выполнить команду:
docker-compose up -d
После этого ваше PHP-приложение будет доступно по адресу http://localhost:8080.
Оптимизация для разработки
Для удобства разработки добавьте в docker-compose.yml сервис с Xdebug. Это позволит отлаживать код прямо из контейнера:
# Дополнение к сервису php в docker-compose.yml
php:
build:
context: .
dockerfile: Dockerfile.php-fpm
args:
- WITH_XDEBUG=true
environment:
PHP_IDE_CONFIG: "serverName=Docker"
XDEBUG_CONFIG: "client_host=host.docker.internal client_port=9003"
extra_hosts:
- "host.docker.internal:host-gateway"
А в Dockerfile добавьте условную установку Xdebug:
ARG WITH_XDEBUG=false
RUN if [ "$WITH_XDEBUG" = "true" ]; then \
pecl install xdebug && \
docker-php-ext-enable xdebug; \
fi
Лучшие практики и советы
Чтобы ваша контейнеризация была эффективной и безопасной, следуйте этим рекомендациям:
- Используйте .dockerignore: исключите из образа папки
vendor,.git,node_modulesи другие временные файлы. Это уменьшит размер образа и ускорит сборку. - Минимизируйте количество слоев: объединяйте команды
RUN