Docker Compose: поднимаем многоконтейнерное приложение

Рейтинг: 61% · 6 голосов
Практический курс по Docker: образы, контейнеры, тома, сети, Compose и продакшен. Уроки по главам с обсуждением.
Ответить
Аватара пользователя
Marina_DevOps
Сообщения: 25
Зарегистрирован: 11 май 2026, 05:31

Docker Compose: поднимаем многоконтейнерное приложение

Сообщение Marina_DevOps »

АкадемияDocker с нуляГлава 8 из 17
Оглавление курса (17)
  1. Что такое Docker и какие задачи он решает
  2. Установка Docker и запуск первого контейнера
  3. Образы: слои, теги и реестр Docker Hub
  4. Пишем свой Dockerfile
  5. Тома и хранение данных: volumes и bind mounts
  6. Сети в Docker: связываем контейнеры между собой
  7. Переменные окружения и конфигурация контейнеров
  8. Docker Compose: поднимаем многоконтейнерное приложение (вы здесь)
  9. Оптимизация образов: multi-stage сборка, размер и кэш слоёв
  10. Логи, отладка и мониторинг контейнеров
  11. Базовая безопасность контейнеров
  12. Подготовка к продакшену: что важно учесть
  13. Dockerfile глубже: ENTRYPOINT и CMD, HEALTHCHECK, .dockerignore, запуск не от root
  14. Реестры образов: приватные registry, push и pull, теги и digest, imagePullSecrets
  15. BuildKit и buildx: multi-arch сборки, секреты сборки, экспорт кэша
  16. Docker в CI/CD: автосборка, сканирование образов (Trivy, Docker Scout), публикация
  17. Итоговый проект и куда расти: от Dockerfile до прода, обзор оркестрации (Kubernetes, Podman, OCI)
В предыдущих главах вы научились собирать образы, подключать тома, соединять контейнеры через сети и настраивать их переменными окружения. Для приложения с базой данных всё это выливается в несколько длинных docker run, которые легко забыть и сложно передать коллеге. Docker Compose сводит весь стек к одному файлу и одной команде.

Что такое Compose и где он живёт:

Compose V2 входит в Docker Desktop из коробки, а на Linux ставится пакетом docker-compose-plugin. Вызывается как docker compose, через пробел. Если в туториале встречается docker-compose через дефис, это старая версия на Python, она давно не развивается. Проверка:

Код: Выделить всё

docker compose version
Описываем стек:

Возьмём типичный случай: веб-приложение плюс PostgreSQL. В корне проекта создаём файл compose.yaml (имя docker-compose.yml тоже работает, но compose.yaml сейчас основное):

Код: Выделить всё

services:
  app:
    build: .
    ports:
      - "8000:8000"
    environment:
      DATABASE_URL: postgres://app:secret@db:5432/appdb
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:16
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: appdb
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app -d appdb"]
      interval: 5s
      timeout: 3s
      retries: 10

volumes:
  pgdata:
Что здесь происходит. Сервис app собирается из Dockerfile в текущей папке, как в главе 4. Сервис db берёт готовый образ postgres:16 с Docker Hub. Compose автоматически создаёт для проекта отдельную bridge-сеть, и сервисы видят друг друга по именам: приложение ходит в базу по хосту db, а не по IP (тот самый механизм из главы 6). Именованный том pgdata переживает пересоздание контейнеров, это материал главы 5.

Блок healthcheck вместе с condition: service_healthy решает классическую проблему: контейнер postgres стартует за секунду, но сама база готова принимать соединения чуть позже. Без этого условия app может упасть на старте с ошибкой подключения. Голый depends_on гарантирует только порядок запуска контейнеров, не готовность сервиса внутри.

Запускаем и смотрим:

Код: Выделить всё

docker compose up -d
docker compose ps
docker compose logs -f app
docker compose exec db psql -U app appdb
Флаг -d отправляет стек в фон. Имя проекта Compose берёт из имени папки: если проект лежит в каталоге myshop, контейнеры получат имена myshop-app-1 и myshop-db-1.

Остановка и обновление:

docker compose stop останавливает контейнеры. docker compose down останавливает и удаляет их вместе с сетью, при этом именованные тома остаются и данные базы целы. С флагом -v тома тоже удалятся, поэтому на рабочем проекте лишний раз его не набирайте.

После правок в коде пересоберите образ:

Код: Выделить всё

docker compose up -d --build
Без --build Compose возьмёт старый образ из кэша, и вы будете удивляться, почему изменения не применились. Для локальной разработки код часто монтируют bind mount'ом поверх, тогда пересборка нужна только при смене зависимостей.

Типичные грабли:

Первая ловушка: строка version: "3.8" в начале файла. Старые статьи начинаются с неё, но Compose V2 это поле игнорирует и пишет предупреждение. Просто не указывайте его.

Вторая: подключение к базе по localhost. Внутри контейнера app адрес localhost указывает на сам контейнер app, базы там нет. Используйте имя сервиса.

Третья: занятый порт. Если на машине уже крутится локальный PostgreSQL на 5432, проброс упадёт с ошибкой port is already allocated. Поменяйте левую часть, например "5433:5432", или вообще не публикуйте порт базы наружу: для связи между сервисами внутри одной сети проброс не нужен.

Четвёртая: правки в compose.yaml не подхватываются сами. После изменения файла выполните docker compose up -d ещё раз, Compose пересоздаст только изменившиеся сервисы.

Что усвоили:

Весь стек проекта теперь описан декларативно: один compose.yaml в репозитории заменяет страницу инструкций по запуску. Вы умеете поднимать, останавливать и пересобирать многоконтейнерное приложение и дожидаться готовности базы через healthcheck. В главе 9 займёмся размером образов и multi-stage сборкой, а в главе 10 разберём, как читать логи и отлаживать контейнеры, когда что-то пошло не так.
👍6 ❤️1 🔥 😄 🤔1
✔ Лучший ответ сформирован автоматически — wullu5
Marina_DevOps писал(а):контейнер postgres стартует за секунду, но сама база готова принимать соединения чуть позже наступал на это с redis и кастомным образом, где никакого healthcheck в помине не было. в итоге дописал test через redis-cli ping прямо в compose файле и заработало. правильно понимаю, что healthcheck можно вешать на уровне compose, даже если в самом образе его нет?
Перейти к ответу →
Аватара пользователя
akiya
Сообщения: 3
Зарегистрирован: 14 май 2026, 06:12

Re: Docker Compose: поднимаем многоконтейнерное приложение

Сообщение akiya »

Marina_DevOps писал(а):Без --build Compose возьмёт старый образ из кэша, и вы будете удивляться, почему изменения не применились
вот это буквально про меня. убил два часа в пятницу, правлю код, а контейнер крутит старую версию, уже думал я с ума схожу. оказалось compose сам ничего не пересобирает. спасибо, хоть понятно стало почему так
👍1 ❤️ 🔥 😄 🤔
Аватара пользователя
gpu_pro
Сообщения: 1
Зарегистрирован: 13 май 2026, 01:32

Re: Docker Compose: поднимаем многоконтейнерное приложение

Сообщение gpu_pro »

а если сервисов в стеке штук десять, например app, db, redis и пачка воркеров, а мне для отладки нужны только app и db? можно поднять часть стека, не гоняя каждый раз всё целиком, или придётся комментировать сервисы в файле?
👍1 ❤️ 🔥1 😄 🤔
Аватара пользователя
wullu5
Сообщения: 1
Зарегистрирован: 11 май 2026, 23:40

Re: Docker Compose: поднимаем многоконтейнерное приложение

Сообщение wullu5 »

✔ Лучший ответ — сформирован автоматически
Marina_DevOps писал(а):контейнер postgres стартует за секунду, но сама база готова принимать соединения чуть позже
наступал на это с redis и кастомным образом, где никакого healthcheck в помине не было. в итоге дописал test через redis-cli ping прямо в compose файле и заработало. правильно понимаю, что healthcheck можно вешать на уровне compose, даже если в самом образе его нет?
👍1 ❤️ 🔥 😄 🤔1
Аватара пользователя
leonida
Сообщения: 2
Зарегистрирован: 29 май 2026, 19:24

Re: Docker Compose: поднимаем многоконтейнерное приложение

Сообщение leonida »

добавлю из практики: команда docker compose config сильно выручает. она показывает итоговый конфиг со всеми подставленными переменными. когда у тебя env_file плюс куча ${VAR} в файле, без неё вообще не понять, что реально уедет в контейнеры
👍1 ❤️1 🔥 😄 🤔
Ответить
← Предыдущая глава
Переменные окружения и конфигурация контейнеров
Следующая глава →
Оптимизация образов: multi-stage сборка, размер и кэш слоёв

Все главы курса «Docker с нуля»

Поделиться темой: ✈ Telegram VK

Вернуться в «Docker с нуля»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость