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

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

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

Начать курс

Зачем нужна контейнеризация 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

Лучшие практики и советы

Чтобы ваша контейнеризация была эффективной и безопасной, следуйте этим рекомендациям: