Docker Compose: практическое руководство по сборке и управлению многоконтейнерными приложениями | AdminWiki
Timeweb Cloud — сервера, Kubernetes, S3, Terraform. Лучшие цены IaaS.
Попробовать

Docker Compose: практическое руководство по сборке и управлению многоконтейнерными приложениями

04 апреля 2026 9 мин. чтения

Docker Compose — это инструмент для определения и запуска многоконтейнерных приложений Docker. Вместо того чтобы вручную запускать каждый контейнер отдельной командой docker run с десятком флагов, вы описываете всю инфраструктуру — сервисы, сети, тома — в одном декларативном YAML-файле. Это превращает сложный процесс оркестровки в простую команду docker compose up, что критически важно для DevOps-инженеров и системных администраторов, которые ценят воспроизводимость, контроль и экономию времени.

В этом руководстве вы получите готовый, проверенный на практике файл docker-compose.yml для типового стека «веб-сервер + база данных», пошаговую инструкцию по его запуску и глубокое объяснение ключевых аспектов: от сборки образов через секцию build до настройки сетевого взаимодействия между контейнерами. Материал основан на реальном опыте и закрывает основные страхи специалистов: «Сработает ли это в моем случае?» и «Не упустил ли я важный шаг?».

Что такое Docker Compose и зачем он нужен для многоконтейнерных приложений

Работа с несколькими контейнерами через отдельные команды docker run быстро становится неуправляемой. Представьте запуск простого веб-приложения с Nginx, PostgreSQL и Redis:

docker run -d --name db \
  -e POSTGRES_PASSWORD=secret \
  -v pgdata:/var/lib/postgresql/data \
  postgres:16

docker run -d --name cache \
  redis:alpine

docker run -d --name web \
  --link db:db --link cache:cache \
  -p 80:80 \
  -v $(pwd)/app:/app \
  my-web-app:latest

Проблемы очевидны: команды длинные и сложные для воспроизведения; легко ошибиться в порядке запуска или параметрах сети; нет единого представления о приложении как о целом. Docker Compose решает эти проблемы, предлагая декларативный подход. Вы описываете что должно работать (сервисы, их конфигурация, связи), а инструмент заботится о как это запустить. Основные выгоды:

  • Единый источник истины: Вся инфраструктура описана в файле docker-compose.yml, который можно добавить в систему контроля версий.
  • Автоматизация сборки и запуска: Одна команда docker compose up собирает образы (при необходимости) и запускает все сервисы в правильном порядке с учетом зависимостей.
  • Упрощенное управление сетями и томами: Compose автоматически создает изолированную сеть для сервисов и позволяет декларативно управлять томами для данных.

Это не просто удобство — это стандарт для разработки, тестирования и развертывания современных приложений, который снижает операционные риски и ускоряет работу. Для более глубокого понимания основ Docker, рекомендуем ознакомиться с практическим гайдом по архитектуре Docker для DevOps и системных администраторов.

От ручного запуска контейнеров к декларативной конфигурации

Эволюция от императивного (команды) к декларативному (YAML-файл) подходу — это переход от хаоса к контролю. Возражение «Я и так могу запустить несколько контейнеров скриптом» теряет силу, когда требуется обеспечить воспроизводимость на разных окружениях (разработка, staging, production), управлять версиями конфигурации и минимизировать человеческий фактор. Файл docker-compose.yml — это документация и исполняемый код в одном лице.

Создаем и разбираем docker-compose.yml: от структуры до рабочего примера

Практическая ценность руководства — в предоставлении готового, работающего инструмента. Ниже приведен полный пример файла docker-compose.yml для стека, состоящего из веб-сервера Nginx и базы данных PostgreSQL. Этот пример можно сразу скопировать, адаптировать под свои нужды и запустить.

version: '3.8'

services:
  # Сервис базы данных PostgreSQL
  db:
    image: postgres:16-alpine  # Используем конкретный тег для контроля версий
    container_name: app_postgres
    restart: unless-stopped
    environment:
      POSTGRES_DB: myappdb      # Имя базы данных, создаваемой при первом запуске
      POSTGRES_USER: appuser    # Пользователь БД
      POSTGRES_PASSWORD: ${DB_PASSWORD}  # Пароль берется из переменной окружения
    volumes:
      - postgres_data:/var/lib/postgresql/data  # Постоянное хранение данных
    networks:
      - app-network
    # Опционально: проверка здоровья сервиса
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U appuser"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Сервис веб-приложения (пример с кастомным образом)
  web:
    build: ./app  # Собираем образ из Dockerfile в директории ./app
    container_name: app_web
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy  # Ждем, пока БД не станет здоровой
    environment:
      DATABASE_URL: postgresql://appuser:${DB_PASSWORD}@db:5432/myappdb
    volumes:
      - ./app:/app  # Монтируем код для разработки (hot-reload)
    networks:
      - app-network
    ports:
      - "8080:80"  # Пробрасываем порт 80 контейнера на порт 8080 хоста

  # Обратный прокси-сервер Nginx
  proxy:
    image: nginx:alpine
    container_name: app_nginx
    restart: unless-stopped
    depends_on:
      - web
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d:ro  # Монтируем конфигурацию Nginx
    networks:
      - app-network
    ports:
      - "80:80"
      - "443:443"

volumes:
  postgres_data:  # Декларативное объявление именованного тома

networks:
  app-network:    # Декларативное создание пользовательской сети
    driver: bridge

Этот файл описывает три сервиса, которые будут работать в единой изолированной сети app-network. Данные PostgreSQL сохраняются в именованном томе postgres_data, который не удалится при остановке контейнеров.

Готовый пример: веб-приложение с PostgreSQL

Пример выше решает частую задачу — развертывание веб-приложения с базой данных. Ключевые моменты, на которые стоит обратить внимание:

  • Имена сервисов (db, web, proxy): Они же становятся именами хостов (DNS-именами) во внутренней сети Docker, что позволяет контейнерам обращаться друг к другу по имени (например, строке подключения host=db port=5432).
  • Переменные окружения: Секция environment критически важна для конфигурации. Пароль вынесен в переменную ${DB_PASSWORD}, которая должна быть определена в файле .env в той же директории. Никогда не храните секреты прямо в YAML-файле.
  • Volumes: Том postgres_data гарантирует сохранность данных БД между перезапусками контейнеров. Монтирование директории ./app в сервис web полезно на этапе разработки.
  • Проброс портов (ports): Сервис proxy публикует порт 80 на хосте, направляя трафик к внутренним сервисам.

Ключевые директивы services: image, build, ports, environment

Понимание основных директив позволяет гибко модифицировать конфигурацию:

  • image: Указывает готовый образ из реестра (Docker Hub). Всегда используйте конкретные теги (postgres:16-alpine), а не плавающий latest, для обеспечения воспроизводимости.
  • build: Задает контекст для сборки образа из Dockerfile. В примере для сервиса web образ будет собран из Dockerfile в директории ./app. Можно указать конкретный файл: build: context: ./app dockerfile: Dockerfile.prod.
  • ports: Пробрасывает порты с хоста в контейнер в формате "HOST:CONTAINER". Для публикации порта только во внутренней сети Docker используйте только номер порта контейнера: "5432".
  • environment: Задает переменные окружения. Можно использовать список VAR=value или словарь. Для управления секретами лучше использовать специальную секцию secrets или внешний файл .env.

Для перехода от разработки к production-окружению с помощью Docker изучите полное руководство по безопасному деплою, мониторингу и логированию.

Пошаговое руководство по запуску: от файла до работающего приложения

Четкий алгоритм действий убирает неопределенность и дает уверенность. Предположим, вы сохранили приведенный выше YAML-файл как docker-compose.yml в отдельной директории проекта.

Сборка образов и запуск сервисов

  1. Подготовка переменных окружения: Создайте в той же директории файл .env и задайте в нем необходимые переменные, например:
    DB_PASSWORD=StrongPassw0rd!
  2. Проверка конфигурации (опционально, но рекомендуется): Выполните команду для валидации и просмотра итогового конфига:
    docker compose config
    Эта команда выведет обработанный файл конфигурации, что помогает найти синтаксические ошибки и убедиться в правильности подстановки переменных.
  3. Сборка и запуск: Основная команда для старта:
    docker compose up --build -d
    • --build — принудительно пересобирает образы, даже если они уже существуют (для сервисов с директивой build).
    • -d (detached) — запускает контейнеры в фоновом режиме.
    • Без флага -d вы увидите объединенные логи всех сервисов в текущем терминале.

Compose автоматически создаст сеть, тома и запустит сервисы в порядке, определенном зависимостями (depends_on).

Базовый мониторинг и управление состоянием

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

  • Проверка статуса:
    docker compose ps
    Команда покажет список сервисов, их состояние (Up, Exit), порты. Это первое действие при диагностике проблем.
  • Просмотр логов: Для наблюдения за логами конкретного сервиса (например, web):
    docker compose logs -f web
    Флаг -f (follow) позволяет отслеживать логи в реальном времени. Просмотр логов — основной способ понять, почему контейнер завершил работу сразу после старта.
  • Остановка и очистка: Чтобы остановить приложение и удалить контейнеры, сети (но не тома), выполните:
    docker compose down
    Для удаления вместе с анонимными томами, созданными сервисами, добавьте флаг -v. Именованные тома (объявленные в секции volumes) при этом не удаляются, что сохраняет данные БД.
    docker compose down -v

Обеспечение связи между контейнерами: сети Docker Compose

Ключевой принцип сетевого взаимодействия в Docker Compose прост: сервисы, объявленные в одном файле docker-compose.yml, по умолчанию подключаются к одной внутренней сети (bridge) и могут находить друг друга по имени сервиса.

Имена сервисов как DNS-имена

Docker Compose автоматически настраивает встроенный DNS-сервер. В примере выше контейнер сервиса web может подключиться к базе данных, используя в строке подключения хост db и порт 5432. Это работает, потому что оба сервиса находятся в одной пользовательской сети app-network. Имя сервиса (db) резолвится во внутренний IP-адрес контейнера.

Это избавляет от необходимости использовать устаревший флаг --link или вручную прописывать статические IP-адреса. Для более сложных сценариев, таких как настройка статических IP или работа с несколькими сетями, обратитесь к руководству по продвинутым сетевым конфигурациям и безопасности Docker.

Управление версиями образов и оптимизация сборки

Контроль за версиями образов — залог стабильности и воспроизводимости вашего окружения.

  • Используйте конкретные теги: Всегда указывайте полный тег образа (postgres:16-alpine, nginx:1.25-alpine). Использование тега latest может привести к неожиданным обновлениям и поломкам при повторном развертывании.
  • Стратегия тегирования для своих образов: При сборке своих образов через build используйте схему тегирования, например, с хэшем коммита или версией приложения.

Сборка своих образов через секцию build

Директива build интегрирует процесс сборки в workflow Compose. Docker использует кэширование слоев для ускорения повторных сборок. Чтобы принудительно пересобрать образ без кэша, используйте:

docker compose build --no-cache web

Для оптимизации скорости сборки и размера образа обязательно используйте файл .dockerignore в контексте сборки, чтобы исключить из образа ненужные файлы (например, node_modules, .git).

Чтобы увидеть список образов, включая собранные через Compose, выполните:

docker images

Практические советы и частые проблемы

Основано на реальном опыте развертывания.

  • Файл .env: Используйте его для хранения переменных окружения, специфичных для данного развертывания (пароли, ключи API). Не коммитьте его в Git. Добавьте .env в .gitignore.
  • Контейнер падает сразу после старта: Первым делом смотрите логи: docker compose logs [service_name]. Частые причины: ошибка в переменных окружения, отсутствие зависимого сервиса (используйте depends_on с condition: service_healthy), ошибка в точке входа (CMD) Dockerfile.
  • Обновление конфигурации: После изменения docker-compose.yml выполните docker compose up -d. Compose остановит и пересоздаст только те сервисы, конфигурация которых изменилась.
  • Миграция с версии 2 на версию 3: Современные версии Docker Engine и Compose используют схему версии 3.x. Основное отличие — версия 3.x оптимизирована для работы с Docker Swarm и имеет несколько измененных или удаленных параметров (например, volume_driver). Для standalone-использования достаточно указать version: '3.8'.
  • Управление в кластере: Если ваш следующий шаг — оркестрация контейнеров на нескольких хостах, изучите практическое руководство по Docker Swarm для системных администраторов как более простую альтернативу Kubernetes.

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

Поделиться:
Сохранить гайд? В закладки браузера