Docker Compose в продакшене: практическое руководство для небольших команд в 2026 году
Введение: Docker Compose в 2026 году — жив и актуален
Разговоры о том, что Docker Compose «устарел» и годится только для локальной разработки, ведутся уже несколько лет. Тем не менее в 2026 году тысячи стартапов и небольших команд успешно используют его для продакшен-развёртываний. И это не от незнания альтернатив — это осознанный выбор.
Docker Compose остаётся актуальным инструментом там, где важна простота, скорость итерации и минимальные операционные издержки. Kubernetes мощнее, но за мощью стоит сложность: обучение команды, поддержка кластера, настройка RBAC, Helm-чарты. Для команды из двух-пяти человек это зачастую избыточно.
В этой статье мы разберём, как выстроить production-ready инфраструктуру на Docker Compose: от архитектуры файлов до CI/CD и мониторинга, и честно обсудим, когда всё-таки пора смотреть в сторону Kubernetes.
Docker Compose v2 vs v3: ключевые отличия и что использовать сейчас
Долгое время существовала путаница между версиями схемы Compose-файла (v2, v3) и версиями самого инструмента. В 2026 году ситуация прояснилась: Docker официально перешёл на единую спецификацию Compose Specification, которая объединила лучшее из обоих миров.
Что изменилось на практике
- Поле
versionбольше не обязательно и фактически игнорируется новыми версиями Docker Compose v2+. Его можно убрать из файлов. - Директива
depends_onтеперь поддерживает условия (condition: service_healthy), что делает её полноценным инструментом управления порядком запуска. - Секреты и конфиги получили нативную поддержку — не только для Swarm, но и для обычного Compose.
- Команда
docker-compose(с дефисом, Python-версия) устарела. Используйтеdocker compose(плагин, написанный на Go) — он быстрее и активно поддерживается.
Вывод прост: в 2026 году пишите файлы по Compose Specification без поля version, используйте docker compose вместо docker-compose.
Архитектура production-ready Compose-файла
Хороший продакшен-файл — это не просто список сервисов. Это декларация того, как ваше приложение должно вести себя под нагрузкой, при падении и при обновлении.
Пример базовой структуры
services:
app:
image: registry.example.com/myapp:${APP_VERSION:-latest}
restart: unless-stopped
networks:
- internal
- proxy
environment:
- DATABASE_URL=${DATABASE_URL}
secrets:
- db_password
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
depends_on:
db:
condition: service_healthy
deploy:
resources:
limits:
cpus: "1.0"
memory: 512M
db:
image: postgres:16-alpine
restart: unless-stopped
networks:
- internal
volumes:
- pg_data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
restart: unless-stopped
networks:
- internal
volumes:
- redis_data:/data
command: redis-server --appendonly yes
nginx:
image: nginx:alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
networks:
- proxy
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- certbot_data:/etc/letsencrypt
networks:
internal:
driver: bridge
internal: true
proxy:
driver: bridge
volumes:
pg_data:
redis_data:
certbot_data:
secrets:
db_password:
file: ./secrets/db_password.txt
Ключевые элементы архитектуры
- Сети: разделяйте внутреннюю сеть (сервисы между собой) и внешнюю (проксирование). Флаг
internal: trueзапрещает контейнерам в этой сети выходить в интернет — хорошая практика для баз данных. - Volumes: всегда используйте именованные тома для данных, требующих персистентности. Никогда не храните продакшен-данные в bind mounts.
- Health checks: обязательны для любого сервиса, от которого зависят другие. Без них
depends_onпроверяет только факт запуска контейнера, а не готовность приложения. - Restart policies:
unless-stopped— разумный дефолт для продакшена. Он перезапускает контейнер при падении, но не трогает его при ручной остановке. - Resource limits: ограничивайте CPU и память. Без лимитов один сервис может съесть все ресурсы хоста.
Секреты и конфигурации: безопасное управление переменными окружения
Передача секретов через переменные окружения в .env-файле — самая распространённая ошибка. Такие файлы попадают в репозиторий, в логи CI, в историю команд. В продакшене нужен другой подход.
Уровни управления секретами
- Docker Secrets (нативно): файлы монтируются в
/run/secrets/контейнера. Поддерживаются в обычном Compose (не только в Swarm). Показаны в примере выше. - Внешние хранилища: HashiCorp Vault, AWS Secrets Manager, Doppler. Секреты получаются в момент деплоя и передаются как файлы или через environment.
- Переменные окружения CI/CD: GitLab CI, GitHub Actions и другие системы позволяют хранить секреты на уровне проекта. В момент деплоя они подставляются в нужные места.
Практическая схема для небольшой команды
Минимальная безопасная схема: секреты хранятся в переменных GitLab/GitHub, при деплое записываются в файлы на сервере, Compose читает их через механизм secrets. Файл .env содержит только несекретные настройки (имена образов, порты, имена баз данных) и может быть в репозитории.
# .env (безопасно коммитить)
APP_VERSION=1.4.2
DB_NAME=myapp_prod
REDIS_MAX_MEMORY=256mb
# secrets/db_password.txt (НЕ коммитить, в .gitignore)
# Создаётся скриптом деплоя из CI/CD переменных
Обновление сервисов без даунтайма
Docker Compose не имеет встроенного rolling update, как Kubernetes. Но нулевой даунтайм достижим при правильной архитектуре.
Стратегия blue-green через nginx
Самый простой подход: держать reverse proxy (nginx или Traefik) снаружи, а приложение обновлять с кратким переключением:
# Обновление без даунтайма
docker compose pull app
docker compose up -d --no-deps --build app
Флаг --no-deps обновляет только указанный сервис без перезапуска зависимостей. Docker сначала запускает новый контейнер, убеждается в прохождении healthcheck, затем останавливает старый. При наличии health check даунтайм сводится к секундам.
Traefik как умный прокси
Для более гладких обновлений многие команды используют Traefik вместо Nginx. Traefik читает лейблы Docker-контейнеров и автоматически перенаправляет трафик на здоровые инстанции:
app:
image: registry.example.com/myapp:${APP_VERSION}
labels:
- "traefik.enable=true"
- "traefik.http.routers.app.rule=Host(`example.com`)"
- "traefik.http.services.app.loadbalancer.healthcheck.path=/health"
Интеграция с CI/CD пайплайном
Автоматический деплой через Docker Compose в CI/CD — это не rocket science. Типовая схема: сборка образа → пуш в registry → SSH на сервер → docker compose up.
Пример GitLab CI/CD pipeline
stages:
- build
- deploy
build:
stage: build
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
only:
- main
deploy:
stage: deploy
script:
- echo "$DB_PASSWORD" > secrets/db_password.txt
- export APP_VERSION=$CI_COMMIT_SHORT_SHA
- docker compose pull
- docker compose up -d --no-deps app
- docker compose exec app php artisan migrate --force
environment:
name: production
only:
- main
Обратите внимание: миграции базы данных запускаются после старта контейнера, но до переключения трафика — это важный порядок. Если используете Laravel или другой фреймворк с системой миграций, убедитесь в их идемпотентности.
Rollback
Откат в Compose-мире тривиален: достаточно поменять тег образа на предыдущий и повторить docker compose up. Фиксируйте теги образов в переменных, не используйте latest в продакшене.
Мониторинг и логирование контейнеров
«Мониторинг — это не опционально в продакшене» — банальная, но справедливая истина. Docker Compose не даёт мониторинг из коробки, но интегрируется с популярными решениями без лишних сложностей.
Логирование
Настройте драйвер логирования на уровне сервиса или глобально в /etc/docker/daemon.json:
app:
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "5"
Для централизованного логирования: Loki + Grafana — отличный выбор для небольших команд. Promtail собирает логи Docker-контейнеров и отправляет в Loki. Вся связка поднимается тем же Compose.
Метрики
Стек Prometheus + Grafana стал стандартом де-факто. Добавьте в Compose-файл:
- cAdvisor — метрики контейнеров (CPU, RAM, сеть)
- Node Exporter — метрики хоста
- Prometheus — сбор и хранение метрик
- Grafana — визуализация
Весь стек мониторинга можно вынести в отдельный docker-compose.monitoring.yml и запускать через docker compose -f docker-compose.yml -f docker-compose.monitoring.yml up -d.
Алерты
Alertmanager (часть экосистемы Prometheus) или простой uptimerobot.com для базовых проверок доступности — достаточно для большинства небольших проектов. Настройте уведомления в Slack или Telegram.
Когда пора переходить на Kubernetes: честные критерии
Docker Compose — отличный инструмент, но у него есть реальные ограничения. Вот честный список сигналов, что пора смотреть в сторону Kubernetes:
Технические триггеры
- Нужен горизонтальный масштаб: вы хотите запускать 5, 10, 50 реплик одного сервиса на разных машинах. Compose работает на одном хосте. Docker Swarm — промежуточный вариант, но в 2026 году его развитие замедлилось.
- Требуется автомасштабирование: HPA (Horizontal Pod Autoscaler) в Kubernetes реагирует на нагрузку автоматически. В Compose нужно менять реплики вручную.
- Сложная оркестрация: десятки сервисов с разными версиями, сложными зависимостями и независимыми циклами деплоя — Kubernetes с Helm значительно удобнее.
- Multi-region или multi-node: как только появляется потребность в нескольких серверах для одного приложения, Compose перестаёт быть достаточным.
- Жёсткие SLA: если у вас SLA 99.99%, нужны механизмы автоматического восстановления, rolling updates без даунтайма и circuit breakers — всё это в Kubernetes нативно.
Организационные триггеры
- Команда выросла до 10+ человек и нескольких независимых команд
- Появился выделенный DevOps/Platform инженер
- Количество микросервисов перевалило за 15-20
- Нужна изоляция окружений (dev/staging/prod) с разными ресурсами на уровне кластера
Когда НЕ нужен Kubernetes
Если ваш монолит или набор из 3-5 сервисов обслуживает 10 000 пользователей в день на одном сервере — Docker Compose справляется отлично. Переход на Kubernetes добавит минимум 2-4 недели на настройку и постоянные операционные издержки. Это время лучше потратить на продукт.
Заключение
Docker Compose в 2026 году — это зрелый, надёжный инструмент для продакшен-развёртываний небольших команд. При правильной архитектуре: разделённые сети, именованные тома, health checks, управление секретами и интеграция с CI/CD — он обеспечивает стабильную работу приложений без операционной сложности Kubernetes.
Ключевые принципы, которые стоит запомнить:
- Используйте
docker compose(плагин v2) без поляversionв файле - Разделяйте сети на внутренние и внешние
- Никогда не передавайте секреты через
.env-файлы в репозитории - Health checks — обязательны, не опциональны
- Фиксируйте версии образов, не используйте
latest - Автоматизируйте деплой через CI/CD с первого дня
- Добавьте мониторинг до первого инцидента, а не после
Kubernetes — мощный инструмент, но его время приходит с масштабом. Не усложняйте раньше времени. Compose даёт 80% возможностей при 20% сложности — и для большинства небольших команд это идеальное соотношение.
Технологии
Теги
Руслан Исмаилов
Senior Web / Backend разработчик. Senior web/backend разработчик с 9-летним опытом. Стек: PHP, Laravel, PostgreSQL, Redis, Docker, Kubernetes, REST, микросервисы, CI/CD. Подробнее обо мне →