Модуль 10 / 18
Docker Compose: модель приложения и окружения
Содержание
1. Цели и модель Compose
После модуля вы сможете описать multi-container приложение декларативно, вычислить итоговую конфигурацию, управлять project lifecycle и диагностировать расхождение между YAML и объектами Engine.
- Compose Specification описывает желаемую модель
- service — шаблон контейнеров
- project изолирует имена и lifecycle
- config показывает вычисленную модель
- up согласует объекты, down удаляет проектные ресурсы
2. Теория: project, service и resource
Compose CLI преобразует compose.yaml в модель project и вызывает Docker API. Это не отдельный orchestrator: контейнеры выполняет тот же Engine. Service задаёт image, command, environment, mounts, networks и другие параметры одного типа workload.
Project name входит в labels и типовые имена ресурсов. Его задают top-level name, -p, COMPOSE_PROJECT_NAME или каталог с определённым приоритетом. Стабильное имя предотвращает случайное управление соседним проектом.
3. Теория: вычисление конфигурации
YAML на диске ещё не является effective configuration. Compose объединяет файлы, обрабатывает anchors, profiles и interpolation, нормализует short syntax. docker compose config показывает результат до создания объектов.
Переменные для подстановки берутся из shell и env-файлов по правилам precedence. environment внутри service относится к контейнеру и не тождественен источникам interpolation. Secrets нельзя хранить в committed .env.
4. Теория: up, run, exec и down
up создаёт или пересоздаёт изменившиеся services, networks и volumes, затем запускает их. Повторный up должен быть идемпотентным. stop сохраняет контейнеры, start запускает их снова, down удаляет project containers и networks.
exec запускает процесс в существующем service container. run создаёт отдельный one-off container и по умолчанию не публикует service ports. Флаг --rm управляет только этим one-off container.
5. Теория: DNS, ports и volumes
Default network создаётся на project, а service names становятся DNS-именами. Между services используют container port; ports нужны лишь для доступа с host или извне.
Named volumes должны быть объявлены. down не удаляет их без -v, потому что данные имеют независимый lifecycle. External resources Compose не создаёт и не должен удалять.
6. Теория: profiles, scale и границы Compose
Profiles включают необязательные services: debug tools, migration или maintenance. Service без profile запускается всегда. Явный запуск профилированного service активирует его зависимости, но не превращает profile в production policy.
Scale создаёт несколько контейнеров service, однако fixed container_name и host port мешают масштабированию. Compose одного Engine не обеспечивает multi-host scheduling, rolling update или cluster failover; для этого нужен orchestrator.
7. Методические указания
- Всегда выполняйте config --quiet и просматривайте config
- Фиксируйте image version или digest
- Не задавайте container_name без необходимости
- Разделяйте build-time и runtime variables
- Привязывайте локальные ports к 127.0.0.1
- Используйте labels для ownership
- Не применяйте down -v без проверки данных
- Запускайте команды из известного project directory
8. Лабораторная работа: Compose project
Создайте web и опциональный debug client, исследуйте interpolation и project name.
mkdir -p /tmp/docker-module-10/html
printf '%s\n' '<!doctype html><html><meta charset="utf-8"><title>Compose lab</title><h1>compose works</h1></html>' > /tmp/docker-module-10/html/index.html
printf '%s\n' 'WEB_PORT=18090' 'APP_ENV=lab' > /tmp/docker-module-10/.env
printf '%s\n' 'name: docker-m10' 'services:' ' web:' ' image: nginx:1.29-alpine' ' ports:' ' - "127.0.0.1:${WEB_PORT:-18090}:80"' ' volumes:' ' - type: bind' ' source: ./html' ' target: /usr/share/nginx/html' ' read_only: true' ' environment:' ' APP_ENV: ${APP_ENV:-development}' ' networks: [frontend]' ' labels:' ' course.module: "10"' ' client:' ' image: alpine:3.21' ' command: ["sh", "-c", "sleep 300"]' ' profiles: [debug]' ' networks: [frontend]' 'networks:' ' frontend:' ' name: docker-m10-frontend' > /tmp/docker-module-10/compose.yaml
cd /tmp/docker-module-10
docker compose version
docker compose config --quiet
docker compose config
docker compose config --services
docker compose config --imagescd /tmp/docker-module-10
docker compose config --environment
docker compose config --format json | jq '{name,services:(.services | keys),networks:(.networks | keys)}'
WEB_PORT=18091 APP_ENV=override docker compose config --format json | jq '.services.web | {environment,ports}'
docker compose -p docker-m10-alt config --format json | jq '.name'Запустите profile, проверьте DNS и host publishing, затем наблюдайте reconciliation и scale.
cd /tmp/docker-module-10
docker compose --profile debug up --detach
docker compose ps
docker compose images
docker compose exec --interactive=false client wget -qO- http://web/
curl --fail --silent --show-error --retry 10 --retry-connrefused --retry-delay 1 http://127.0.0.1:18090/
docker compose logs --no-color --tail 20 web
docker compose topcd /tmp/docker-module-10
docker compose --profile debug up --detach --scale client=2
docker compose ps --format json | jq -s 'map({Name,Service,State})'
docker compose --profile debug up --detach
docker compose psКритерий: config валиден; client получает страницу по имени web; loopback port отвечает; повторный up сохраняет желаемое состояние.
9. Диагностика Compose
Идите от effective model к project labels и фактическим объектам. Не начинайте с удаления проекта.
cd /tmp/docker-module-10
docker compose config --quiet
docker compose ps --all
docker compose logs --no-color --timestamps --tail 50
docker compose events --json --since 10m --until 0s 2>/dev/null | tail -20 || true
docker network inspect docker-m10-frontend
docker inspect docker-m10-web-1 --format '{{json .Config.Labels}}' | jq- config: interpolation, merge и profiles
- ps --all: exited и restarting containers
- logs: stderr/stdout каждого service
- inspect labels: project, service и config hash
- network/volume inspect: membership и ownership
- events: последовательность create/start/die
10. Контроль и cleanup
- Чем service отличается от container?
- Как определяется project name?
- Почему config важнее чтения одного YAML?
- Чем run отличается от exec?
- Что удаляет down?
- Почему container_name мешает scale?
- Зачем profiles?
- Где заканчиваются возможности Compose?
cd /tmp/docker-module-10
docker compose --profile debug down --remove-orphans
cd /
rm -f /tmp/docker-module-10/compose.yaml /tmp/docker-module-10/.env /tmp/docker-module-10/html/index.html
rmdir /tmp/docker-module-10/html /tmp/docker-module-10
docker ps -a --filter label=com.docker.compose.project=docker-m10
docker network ls --filter name=docker-m10Модуль освоен, если вы предсказываете effective configuration, безопасно управляете project lifecycle и находите объект по Compose labels.