Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке docker-compose?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Docker Compose** це інструмент для декларативного опису і запуску multi-container застосунків у одному YAML-файлі. Одна команда (`docker compose up`) піднімає весь стек: сервіси, мережі, volume. ```yaml # compose.yaml services: web: image: nginx:1.27-alpine ports: ["8080:80"] depends_on: [api] api: image: myapp:1.0 environment: DATABASE_URL: postgres://postgres:dev@db:5432/app db: image: postgres:16 environment: POSTGRES_PASSWORD: dev ``` ```bash docker compose up -d # підняти все docker compose down # зупинити все ``` **Головне:** Compose перетворює довгий ланцюг `docker run` на версійований декларативний файл. Той самий файл працює на лептопі тіммейта і на CI runner.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**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-доповненнями зверху.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.