Skip to main content

Що таке docker-compose?

Docker Compose це стандартний спосіб описати і запускати multi-container Docker-застосунки. Замість того, щоб писати довгий docker run на кожен сервіс плюс docker network create плюс управління volume, ти описуєш увесь стек у YAML-файлі і піднімаєш його однією командою.

Теорія

TL;DR

  • YAML-файл (дефолтне ім'я: compose.yaml або legacy docker-compose.yml) описує сервіси, мережі і volume твого застосунку.
  • Одна команда піднімає все (docker compose up), одна знімає (docker compose down).
  • Кожен сервіс стає container; Compose створює приватну bridge-мережу, тож сервіси знаходять один одного по імені (db, api).
  • Стандарт для локальної розробки і single-host деплоїв. Для multi-host прода зазвичай береш Swarm або Kubernetes.
  • docker compose (v2, Go-плагін) актуальний. docker-compose (v1, Python) deprecated з 2023.

Швидкий приклад

yaml
# compose.yaml services: web: image: nginx:1.27-alpine ports: - "8080:80" depends_on: - api api: build: ./api environment: DATABASE_URL: postgres://postgres:devpass@db:5432/app depends_on: db: condition: service_healthy db: image: postgres:16 environment: POSTGRES_PASSWORD: devpass POSTGRES_DB: app volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s volumes: pgdata:
bash
$ docker compose up -d [+] Running 4/4 ✔ Network myapp_default Created ✔ Container myapp-db-1 Healthy ✔ Container myapp-api-1 Started ✔ Container myapp-web-1 Started

Одна команда, три сервіси, мережа і volume. Відтворювано на будь-якій машині з Docker.

Основні блоки compose-файлу

yaml
services: # один блок на container <name>: image: ... # АБО build: ./path (зібрати з Dockerfile) container_name: ... # опц., фіксоване ім'я; інакше <project>-<service>-<index> command: ["..."] # override CMD entrypoint: ["..."] # override ENTRYPOINT ports: ["8080:80"] # публікація портів HOST:CONTAINER expose: ["5000"] # тільки внутрішньо, без публікації environment: # env-змінні (map або list) KEY: value env_file: .env # env-змінні з файлу volumes: # mount (named volume або bind mount) - data:/var/lib/... - ./conf:/etc/conf:ro networks: [frontend, backend] depends_on: # порядок старту + health gate <other-service>: condition: service_healthy restart: unless-stopped healthcheck: { test: [...], interval: 30s } deploy: # ліміти ресурсів, replica (працює у Compose з v2) resources: limits: { cpus: "0.5", memory: 512M } networks: # named мережі (дефолт: одна bridge на project) frontend: backend: volumes: # named volume data:

Більшість реальних застосунків використовує підмножину. 80% це services з image/build, ports, environment, volumes, depends_on.

Команди життєвого циклу

bash
docker compose up # старт (foreground, стрімить логи) docker compose up -d # старт detached docker compose down # stop і видалити container + мережу docker compose down -v # ще й видалити volume (ДЕСТРУКТИВНО) docker compose ps # список сервісів цього project docker compose logs -f # tail логи з усіх сервісів docker compose logs api # тільки один сервіс docker compose exec api sh # shell у запущений сервіс docker compose run --rm api npm test # одноразова команда у новому container docker compose build # перезбірка image для сервісів з build: docker compose pull # тягти image для сервісів з image: docker compose restart api # рестарт одного сервісу docker compose stop / start # без видалення docker compose config # валідувати і вивести resolved config

Project-ім'я приходить з імені директорії за замовчуванням. Override через флаг -p або env-змінну COMPOSE_PROJECT_NAME.

Як сервіси знаходять одне одного

Compose створює дефолтну bridge-мережу на project. Всі сервіси приєднуються автоматично. Всередині цієї мережі імена сервісів резолвляться через embedded DNS Docker:

yaml
services: web: image: myapp environment: DB_HOST: db # ← просто "db", не localhost і не IP db: image: postgres:16

З container web ping db працює. Hostname db резолвиться у IP db-container. Без localhost, без host.docker.internal, без ручної мережі.

v1 vs v2 (і чому це важливо у 2026)

  • docker-compose (v1) був Python-інструментом, окремим від Docker daemon. З дефісом. Deprecated з липня 2023.
  • docker compose (v2) Go-плагін, вбудований у сучасний Docker. Пробіл, не дефіс. Поточний стандарт.

Якщо бачиш docker-compose у старих туторіалах, команди майже ідентичні, але сьогодні маєш запускати docker compose. Більшість дистрибутивів за замовчуванням постачають v2; v1 більше не підтримується.

Типові помилки

Плутати down зі stop

bash
docker compose stop # зупиняє container; усе ще існує docker compose down # зупиняє І видаляє container + project-мережу docker compose down -v # ще й стирає volume (data loss!)

Новачки роблять down -v недбало і втрачають свою dev-базу.

Використовувати localhost для зв'язку між сервісами

yaml
# НЕПРАВИЛЬНО: всередині container `api` localhost це сам container api DATABASE_URL: postgres://postgres@localhost:5432/app # ПРАВИЛЬНО: бери ім'я сервісу DATABASE_URL: postgres://postgres@db:5432/app

Кожен container має свій loopback. Трафік між сервісами іде по імені, ніколи не localhost.

Забути condition: service_healthy у depends_on

yaml
# НЕПРАВИЛЬНО: api стартує коли db-container стартує, НЕ коли db готовий приймати запити depends_on: [db] # ПРАВИЛЬНО: api стартує лише після того, як healthcheck db пройшов depends_on: db: condition: service_healthy

Проста list-форма лише впорядковує старти container. Map-форма з condition реально чекає readiness, припускаючи, що залежність має healthcheck.

Bind-mount node_modules на Mac/Windows

yaml
# Повільно на Docker Desktop через cross-VM sync volumes: - .:/app # Швидше: тримай node_modules у named volume, поза bind-sync volumes: - .:/app - api_node_modules:/app/node_modules

Класичний local-dev gotcha, що 2-секундні install-и перетворює на 60-секундні чекання.

Реальне застосування

  • Локальні dev-середовища: домінантний use case. git clone && docker compose up стандартний onboarding.
  • CI/CD тестові фікстури: піднімаємо Postgres + Redis + mock-залежності застосунку одним кроком, проганяємо інтеграційні тести, знімаємо.
  • Single-host production: малі сервіси, side-проекти, внутрішні інструменти. Compose + restart: unless-stopped + reverse proxy це цілком ОК стек для low-traffic застосунків.
  • Demo і tutorial репо: кожен інструмент, що хоче, щоб ти його спробував локально, постачає Compose-файл. Тепер дефолтне очікування.

Питання для поглиблення

Q: Яка різниця між docker compose up і docker compose run?


A: up стартує сервіс як частину running-стеку (довгоживучий, приєднаний до мережі, порти опубліковані). run створює одноразовий новий container на основі того ж service-config, зазвичай для one-shot задач (docker compose run api npm test). run НЕ публікує порти за замовчуванням, поки не додаси --service-ports.

Q: Чи можна мати кілька Compose-файлів для одного project?


A: Так: docker compose -f compose.yaml -f compose.dev.yaml up. Пізніші файли перекривають раніші. Поширений патерн: базовий compose.yaml з прод-shaped config, compose.override.yaml (авто-завантажується) або compose.dev.yaml з dev-доповненнями (bind mount, відкриті dev-порти, hot reload).

Q: Що таке Compose profile?


A: Спосіб позначити сервіси як opt-in. profiles: [debug] у сервісі означає, що він стартує лише при docker compose --profile debug up. Корисно для debug-container, інтеграційних тестів або опційних monitoring-sidecar, які не завжди хочеш мати запущеними.

Q: Коли Compose недостатньо?


A: Multi-host деплой, авто-failover, rolling update, автомасштабування, Compose це single-host і нічого з цього не робить. Коли потрібно, переходь на Docker Swarm (ще простіший за K8s) або Kubernetes (індустрійний дефолт для multi-host).

Q: (Senior) Як організувати Compose-проект для prod, staging і dev з мінімумом дублювання?


A: Базовий compose.yaml з усіма сервісами і shared-config (image, volume, healthcheck). Тоді compose.dev.yaml (bind mount, відкриті dev-інструменти), compose.staging.yaml (інші домени, без debug, менші ресурс-ліміти), compose.prod.yaml (resource caps, restart-політики, без відкритих dev-портів). Використовуй docker compose -f compose.yaml -f compose.<env>.yaml up. Усе secret поза YAML, бери env_file, що вказує на environment-specific dotenv-файли, які не комітяться.

Приклади

Три-сервісний застосунок (web + api + db)

yaml
# compose.yaml services: web: image: nginx:1.27-alpine ports: - "80:80" volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro depends_on: [api] api: build: ./api environment: DATABASE_URL: postgres://postgres:devpass@db:5432/app NODE_ENV: production depends_on: db: condition: service_healthy restart: unless-stopped db: image: postgres:16 environment: POSTGRES_PASSWORD: devpass POSTGRES_DB: app volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 3s retries: 5 volumes: pgdata:
bash
$ docker compose up -d --build # збірка image api, старт усього $ docker compose logs -f api # tail логи api $ docker compose exec api sh # shell у api $ docker compose down # stop, лишити volume

Патерн dev-override

yaml
# compose.override.yaml (авто-завантажується якщо є) services: api: build: target: dev # multi-stage Dockerfile зі стейджем 'dev' volumes: - ./api/src:/app/src # live source mount для hot reload environment: NODE_ENV: development command: npm run dev # override прод CMD ports: - "9229:9229" # node debug-порт
bash
$ docker compose up -d # авто-merge compose.yaml + compose.override.yaml

Prod-shaped база плюс dev-override дає ті самі сервіси з dev-доповненнями зверху.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Коментарі

Ще немає коментарів