1. Введение

Docker Compose стал де-факто стандартом для оркестрации многоконтейнерных приложений в среде разработки и тестирования. При работе с веб-приложениями стек LEMP (Linux, Nginx, MySQL, PHP) представляет собой классическую архитектуру, которая идеально подходит для контейнеризации.

В данном руководстве мы детально рассмотрим процесс создания производственно-готовой инфраструктуры LEMP-стека с использованием Docker Compose. Мы охватим все аспекты: от базовой настройки до продвинутых техник оптимизации и мониторинга.

Важно понимать, что правильная настройка Docker Compose не только упрощает разработку, но и обеспечивает консистентность между различными средами развертывания.

2. Предварительные требования

Прежде чем начать работу с Docker Compose, убедитесь, что ваша система соответствует минимальным требованиям и установлены необходимые компоненты.

2.1. Системные требования

  • Операционная система: Linux, macOS или Windows 10/11 с WSL2
  • ОЗУ: минимум 4 ГБ (рекомендуется 8 ГБ или более)
  • Свободное место на диске: минимум 10 ГБ
  • Процессор: поддержка виртуализации (Intel VT-x или AMD-V)

2.2. Установка Docker и Docker Compose

Для Ubuntu/Debian установка выполняется следующими командами:

# Обновление списка пакетов
sudo apt update

# Установка необходимых пакетов
sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release

# Добавление официального GPG ключа Docker
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# Добавление репозитория Docker
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Установка Docker Engine
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin

# Добавление пользователя в группу docker
sudo usermod -aG docker $USER

# Проверка установки
docker --version
docker compose version

2.3. Базовые знания

Для эффективной работы с данным руководством рекомендуется иметь базовые знания:

  • Понимание основ работы с Docker
  • Знание синтаксиса YAML
  • Опыт работы с Linux командной строкой
  • Базовое понимание веб-технологий (HTTP, SQL, PHP)

3. Структура проекта

Правильная организация файлов проекта является ключевым фактором для поддерживаемости и масштабируемости вашей инфраструктуры. Рассмотрим рекомендуемую структуру каталогов.

3.1. Базовая структура

lemp-docker/
├── docker-compose.yml
├── docker-compose.override.yml
├── docker-compose.prod.yml
├── .env
├── .env.example
├── .dockerignore
├── .gitignore
├── README.md
├── Makefile
├── config/
│   ├── nginx/
│   │   ├── default.conf
│   │   ├── nginx.conf
│   │   ├── ssl/
│   │   └── sites-available/
│   ├── php/
│   │   ├── php.ini
│   │   ├── php-fpm.conf
│   │   └── www.conf
│   └── mysql/
│       ├── my.cnf
│       └── init/
│           └── 01-database.sql
├── data/
│   ├── mysql/
│   ├── nginx/
│   │   └── logs/
│   └── uploads/
├── logs/
│   ├── nginx/
│   ├── php/
│   └── mysql/
├── www/
│   ├── html/
│   │   ├── index.php
│   │   └── phpinfo.php
│   ├── site1/
│   └── site2/
└── scripts/
    ├── backup.sh
    ├── restore.sh
    └── deploy.sh

3.2. Описание каталогов

  • config/ — файлы конфигурации для всех сервисов
  • data/ — persistent данные (базы данных, загруженные файлы)
  • logs/ — файлы логов всех сервисов
  • www/ — веб-файлы и приложения
  • scripts/ — вспомогательные скрипты для развертывания и обслуживания

3.3. Создание структуры проекта

# Создание базовой структуры проекта
mkdir -p lemp-docker/{config/{nginx/{ssl,sites-available},php,mysql/init},data/{mysql,nginx/logs,uploads},logs/{nginx,php,mysql},www/{html,site1,site2},scripts}

cd lemp-docker

# Создание основных файлов
touch docker-compose.yml .env .env.example .dockerignore .gitignore README.md Makefile

# Создание конфигурационных файлов
touch config/nginx/{default.conf,nginx.conf}
touch config/php/{php.ini,php-fpm.conf,www.conf}
touch config/mysql/{my.cnf,init/01-database.sql}

# Создание базового веб-контента
echo "" > www/html/phpinfo.php
echo "" > www/html/index.php

4. Базовый docker-compose.yml

Файл docker-compose.yml является сердцем нашей инфраструктуры. Он определяет все сервисы, сети и тома, необходимые для работы LEMP-стека.

4.1. Основная структура файла

version: '3.8'

services:
  nginx:
    image: nginx:alpine
    container_name: ${PROJECT_NAME:-lemp}_nginx
    restart: unless-stopped
    ports:
      - "${NGINX_HTTP_PORT:-80}:80"
      - "${NGINX_HTTPS_PORT:-443}:443"
    volumes:
      - ./www:/var/www/html:cached
      - ./config/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./config/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
      - ./logs/nginx:/var/log/nginx
    depends_on:
      - php
    networks:
      - lemp-network

  php:
    build:
      context: ./config/php
      dockerfile: Dockerfile
    container_name: ${PROJECT_NAME:-lemp}_php
    restart: unless-stopped
    volumes:
      - ./www:/var/www/html:cached
      - ./config/php/php.ini:/usr/local/etc/php/php.ini:ro
      - ./config/php/php-fpm.conf:/usr/local/etc/php-fpm.conf:ro
      - ./logs/php:/var/log/php
    depends_on:
      - mysql
    networks:
      - lemp-network

  mysql:
    image: mysql:8.0
    container_name: ${PROJECT_NAME:-lemp}_mysql
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    volumes:
      - ./data/mysql:/var/lib/mysql
      - ./config/mysql/my.cnf:/etc/mysql/my.cnf:ro
      - ./config/mysql/init:/docker-entrypoint-initdb.d:ro
      - ./logs/mysql:/var/log/mysql
    ports:
      - "${MYSQL_PORT:-3306}:3306"
    networks:
      - lemp-network

volumes:
  mysql-data:
    driver: local

networks:
  lemp-network:
    driver: bridge

4.2. Ключевые особенности конфигурации

  • version: '3.8' — спецификация Docker Compose, поддерживающая все необходимые функции
  • restart: unless-stopped — автоматический перезапуск контейнеров
  • depends_on — определяет порядок запуска сервисов
  • cached в volumes — оптимизация производительности для макОС и Windows

4.3. Конфигурация переменных окружения (.env)

# Общие настройки проекта
PROJECT_NAME=lemp-stack
ENVIRONMENT=development

# Настройки Nginx
NGINX_HTTP_PORT=80
NGINX_HTTPS_PORT=443

# Настройки MySQL
MYSQL_ROOT_PASSWORD=your_secure_root_password
MYSQL_DATABASE=app_database
MYSQL_USER=app_user
MYSQL_PASSWORD=your_secure_password
MYSQL_PORT=3306

# Настройки PHP
PHP_VERSION=8.2
PHP_MAX_EXECUTION_TIME=300
PHP_MEMORY_LIMIT=512M
PHP_UPLOAD_MAX_FILESIZE=100M

5. Настройка сервиса Nginx

Nginx выступает в роли веб-сервера и обратного прокси, обрабатывая статические файлы и перенаправляя динамические запросы к PHP-FPM.

5.1. Основной конфигурационный файл nginx.conf

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;

events {
    worker_connections 1024;
    use epoll;
    multi_accept on;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # Логирование
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    access_log /var/log/nginx/access.log main;

    # Оптимизация производительности
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    server_tokens off;

    # Сжатие gzip
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_comp_level 6;
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/javascript
        application/xml+rss
        application/json
        image/svg+xml;

    # Буферы и тайм-ауты
    client_body_buffer_size 128k;
    client_max_body_size 100m;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 4k;
    output_buffers 1 32k;
    postpone_output 1460;

    # Инклюд конфигураций сайтов
    include /etc/nginx/conf.d/*.conf;
}

5.2. Конфигурация виртуального хоста default.conf

server {
    listen 80;
    listen [::]:80;
    server_name localhost;
    
    root /var/www/html;
    index index.php index.html index.htm;

    # Обработка статических файлов
    location ~ \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    # Основное местоположение
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # Обработка PHP файлов
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        
        # Оптимизация FastCGI
        fastcgi_buffer_size 128k;
        fastcgi_buffers 4 256k;
        fastcgi_busy_buffers_size 256k;
        fastcgi_temp_file_write_size 256k;
        fastcgi_connect_timeout 60;
        fastcgi_send_timeout 60;
        fastcgi_read_timeout 60;
    }

    # Запрет на доступ к скрытым файлам
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }
}

6. Настройка сервиса PHP-FPM

PHP-FPM (ФастПроцессМенеджер) обеспечивает выполнение PHP-скриптов в отдельном контейнере.

6.1. Dockerfile для PHP-FPM

FROM php:8.2-fpm-alpine

# Установка системных зависимостей
RUN apk add --no-cache \
    linux-headers \
    libpng-dev \
    libjpeg-turbo-dev \
    freetype-dev \
    zip \
    libzip-dev \
    curl-dev \
    oniguruma-dev \
    icu-dev \
    postgresql-dev \
    mysql-client

# Установка PHP расширений
RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install \
        pdo \
        pdo_mysql \
        mysqli \
        gd \
        zip \
        curl \
        mbstring \
        intl \
        opcache \
        bcmath

# Установка Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Установка Xdebug для разработки
RUN apk add --no-cache $PHPIZE_DEPS \
    && pecl install xdebug \
    && docker-php-ext-enable xdebug

# Копирование конфигураций
COPY php.ini /usr/local/etc/php/php.ini
COPY php-fpm.conf /usr/local/etc/php-fpm.conf
COPY www.conf /usr/local/etc/php-fpm.d/www.conf

# Создание пользователя
RUN addgroup -g 1000 -S www && \
    adduser -u 1000 -S www -G www

USER www

WORKDIR /var/www/html

EXPOSE 9000

CMD ["php-fpm"]

6.2. Конфигурация php.ini

[PHP]
engine = On
short_open_tag = Off
precision = 14
output_buffering = 4096
zlib.output_compression = Off
implicit_flush = Off
unserialize_callback_func =
serialize_precision = -1
disable_functions =
disable_classes =
zend.enable_gc = On

# Ограничения ресурсов
max_execution_time = 300
max_input_time = 60
memory_limit = 512M

# Обработка ошибок
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
display_errors = On
display_startup_errors = On
log_errors = On
log_errors_max_len = 1024
ignore_repeated_errors = Off
ignore_repeated_source = Off
report_memleaks = On

# Загрузка файлов
file_uploads = On
upload_max_filesize = 100M
max_file_uploads = 20
post_max_size = 100M

# Оптимизация OPcache
[opcache]
opcache.enable = 1
opcache.enable_cli = 1
opcache.interned_strings_buffer = 8
opcache.max_accelerated_files = 10000
opcache.memory_consumption = 128
opcache.save_comments = 1
opcache.revalidate_freq = 1

# Xdebug конфигурация
[xdebug]
xdebug.mode = debug
xdebug.start_with_request = yes
xdebug.client_host = host.docker.internal
xdebug.client_port = 9003
xdebug.log = /var/log/php/xdebug.log

7. Настройка сервиса MySQL

MySQL 8.0 обеспечивает надежное хранение данных для наших веб-приложений.

7.1. Конфигурация my.cnf

[mysqld]
port = 3306
datadir = /var/lib/mysql
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
max_connections = 500
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
general_log = 1
general_log_file = /var/log/mysql/general.log
log_error = /var/log/mysql/error.log
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2

7.2. Инициализация базы данных

-- 01-database.sql
CREATE DATABASE IF NOT EXISTS app_database CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS 'app_user'@'%' IDENTIFIED BY 'your_secure_password';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON app_database.* TO 'app_user'@'%';
FLUSH PRIVILEGES;

10. Запуск и развертывание

После подготовки всех конфигурационных файлов можно приступать к запуску среды.

# Первый запуск
docker compose config
docker compose build
docker compose up -d

# Проверка статуса
docker compose ps
docker compose logs -f

# Основные команды
docker compose stop
docker compose start
docker compose restart nginx

# Проверка работоспособности
curl -I http://localhost
curl http://localhost/phpinfo.php

12. Лучшие практики и безопасность

Соблюдение лучших практик обеспечивает безопасность и надежность вашей инфраструктуры.

12.1. Безопасность

  • Используйте сильные пароли для всех сервисов
  • Не выносите порты баз данных наружу в production
  • Ограничивайте права пользователей в контейнерах
  • Используйте SSL/TLS сертификаты для HTTPS
  • Регулярно обновляйте образы Docker
Помните: безопасность — это не однократная настройка, а непрерывный процесс. Регулярно обновляйте свои конфигурации и следите за обновлениями безопасности.

15. Заключение

Docker Compose предоставляет мощные возможности для организации современной инфраструктуры LEMP-стека. Правильная настройка позволяет достичь высокой производительности, масштабируемости и надежности.

Основные преимущества данного подхода: изоляция сервисов, легкость развертывания, портативность между окружениями и стандартизация процессов разработки.

Продолжайте изучать возможности контейнеризации и адаптируйте предложенные решения под специфику ваших проектов.

Владислав Павлович

Владислав Павлович

Системный администратор Linux с опытом работы более 5 лет. Специализируюсь на высоконагруженных системах, автоматизации инфраструктуры и оптимизации производительности серверов.