5.9 KiB
Зачем Docker Compose
Когда сервисов несколько (БД, бэкенд, фронт, прокси), писать длинные docker run неудобно. Compose описывает весь стек в одном файле (compose.yaml или docker-compose.yml), поднимает общую сеть и тома, учитывает порядок старта через depends_on и проверки healthcheck.
Команды:
docker compose up -d --build - запустить докер компос в фоне и полностью пересобрать
docker compose ps - список контейнеров в докер компос
docker compose logs -f api - смотреть в реальном времени логи контейнера api из докер компос
docker compose down - остановить контейнере и удалить
Где лежит учебный проект
В репозитории подготовлен полный стек, четыре сервиса:
| Путь | Содержимое |
|---|---|
docker/examples/multi-service/compose.yaml |
Описание всех сервисов, сетей, томов |
docker/examples/multi-service/.env.example |
Пример переменных окружения для Compose |
docker/examples/multi-service/web/ |
Nginx + статика через COPY |
docker/examples/multi-service/api/ |
Flask + Postgres + загрузка файлов в том |
docker/examples/multi-service/proxy/ |
Входной nginx: / → web, /api/ → api |
Скопируйте переменные окружения:
cd docker/examples/multi-service
cp .env.example .env
Запуск:
docker compose up -d --build
Все сервисы подняты
Откроем в браузере страницу на порту 8080 и увидим рабочий сервис, отлично. Нам сейчас не интересна логика работы стека, так как не по теме.
Разбор ключевых фрагментов docker-compose.yaml
Имена и сеть
Поле name: multi-service-demo задаёт префикс для имён контейнеров/ресурсов по умолчанию (удобно не конфликтовать с другими проектами).
Сеть backend с драйвером bridge - все перечисленные сервисы в одной L2-сети, видят друг друга по DNS-имени сервиса (db, api, web, proxy).
Зависимости и здоровье
depends_on:
db:
condition: service_healthy
Без condition Compose лишь упорядочивает старт, но не ждёт готовности БД. С healthcheck у db сервис api не начнёт считаться поднятым для зависимых, пока Postgres не пройдёт проверку.
expose vs ports
ports- публикация на хост (нужно для proxy).expose- документация + открытие порта между контейнерами сети; на сетевой интерфейс хоста не выводится.
Так мы не публикуем Postgres наружу - к БД можно попасть только из контейнеров в той же сети (или если вы явно добавите ports для отладки).
Тома
volumes:
pgdata:
api_uploads:
Именованные тома хранятся в области Docker на диске. Пример «скопировать/сохранить файл в Docker» в runtime:
echo hello > /tmp/up.txt
docker cp /tmp/up.txt "$(docker compose ps -q api)":/data/uploads/host-demo.txt
docker compose exec api ls -la /data/uploads
Альтернатива для разработки - bind-mount каталога с хоста в сервис (в учебном файле не включено, чтобы не привязывать пути к вашему $HOME):
services:
api:
volumes:
- ./local_uploads:/data/uploads
Копирование файлов в контейнер в контексте Compose
| Способ | Когда использовать |
|---|---|
COPY в Dockerfile |
Статика, код, конфиги, которые должны быть в образе на момент деплоя |
| Именованный / bind том | Данные, логи, загрузки пользователей, меняющиеся без пересборки |
docker cp |
Разовая отладка, экстренная подмена файла |
Обновление одного сервиса после правки кода
# изменили только api/app.py
docker compose build api
docker compose up -d api
Остановка и очистка
Мягко (тома сохраняются):
docker compose down
Полный сброс демо:
docker compose down -v --rmi local