Введение / Зачем это нужно
Docker Compose — это инструмент, который позволяет описывать и управлять многоконтейнерными приложениями с помощью одного YAML-файла. Вместо того чтобы вручную запускать десяток контейнеров, настраивать сети и тома, вы описываете всю инфраструктуру как код. Это особенно полезно для разработки, тестирования и локального развёртывания.
После выполнения этого гайда вы:
- Поймёте базовый синтаксис
docker-compose.yml - Научитесь запускать стек из веб-сервиса и базы данных
- Узнаете, как управлять жизненным циклом контейнеров одной командой
Требования / Подготовка
Перед началом убедитесь, что у вас установлено:
- Docker Engine (версия 20.10 или новее)
- Docker Compose v2 (входит в состав Docker Desktop для Linux или как плагин
docker-compose-plugin) - Права sudo (или пользователь в группе
docker)
Проверьте установку:
docker --version
docker compose version
Если Docker Compose не установлен, на Ubuntu/Debian:
sudo apt update
sudo apt install docker-compose-plugin
На CentOS/Rocky/AlmaLinux:
sudo yum install docker-compose-plugin
Шаг 1: Создайте структуру проекта
Создайте каталог для вашего приложения и перейдите в него:
mkdir myapp && cd myapp
В этом каталоге создайте файл docker-compose.yml. Мы будем разворачивать простой стек:
- Сервис
web: Python Flask-приложение - Сервис
db: PostgreSQL
Шаг 2: Напишите файл docker-compose.yml
Создайте файл docker-compose.yml со следующим содержимым:
version: '3.8'
services:
web:
image: python:3.11-slim
command: >
sh -c "pip install flask psycopg2-binary &&
echo 'from flask import Flask\nfrom psycopg2 import connect\napp = Flask(__name__)\n@app.route(\"/\")\ndef hello():\n try:\n conn = connect(dbname=\"testdb\", user=\"user\", password=\"password\", host=\"db\")\n return \"Hello from Docker Compose! DB connection: OK\"\n except Exception as e:\n return f\"DB error: {e}\"\nif __name__ == \"__main__\":\n app.run(host=\"0.0.0.0\", port=5000)' > app.py &&
python app.py"
ports:
- "5000:5000"
depends_on:
- db
environment:
- DATABASE_URL=postgresql://user:password@db/testdb
networks:
- app-network
db:
image: postgres:15-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: testdb
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- app-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 10s
timeout: 5s
retries: 5
volumes:
postgres_data:
networks:
app-network:
driver: bridge
Пояснения к файлу:
- version: указывает версию схемы Compose (используйте 3.8 для совместимости)
- services: список контейнеров (сервисов)
- web:
image: базовый образ Pythoncommand: запускает скрипт, который устанавливает Flask, создаёт простое приложение и запускает егоports: пробрасывает порт 5000 контейнера на порт 5000 хостаdepends_on: гарантирует, чтоdbзапустится доwebenvironment: переменные окружения (используются в приложении)networks: присоединяет сервис к пользовательской сетиapp-network
- db:
image: образ PostgreSQL 15environment: учётные данные БДvolumes: томpostgres_dataсохраняет данные БД на хосте (даже после удаления контейнера)healthcheck: проверка готовности PostgreSQL (важно дляdepends_on)
- web:
- volumes: объявляет именованный том
postgres_data - networks: создаёт сеть
app-network(по умолчанию driverbridge)
Шаг 3: Запустите стек
В каталоге с docker-compose.yml выполните:
docker compose up -d
Что произойдёт:
- Docker Compose прочитает конфигурацию
- Создаст сеть
myapp_app-network(префикс — имя каталога) - Загрузит образы
python:3.11-slimиpostgres:15-alpine(если их нет локально) - Запустит контейнеры в фоновом режиме (
-d)
💡 Совет: Первый запуск может занять минуту — Docker скачивает образы (около 500 МБ).
Шаг 4: Проверьте работу
- Посмотрите статус контейнеров:
docker compose ps
Вывод должен показать оба сервиса в состоянииUp. - Проверьте логи (если что-то не работает):
docker compose logs web docker compose logs db - Тестируйте приложение:
Откройте браузер и перейдите по адресу
http://localhost:5000. Должны увидеть:Hello from Docker Compose! DB connection: OK
Это значит, что веб-контейнер успешно подключился к PostgreSQL. - Проверьте сеть:
docker network ls | grep app-network docker network inspect myapp_app-network
Шаг 5: Управление стеком
Основные команды:
| Команда | Действие |
|---|---|
docker compose down | Останавливает и удаляет контейнеры, сети (тома остаются) |
docker compose down -v | Удаляет также тома (данные БД будут потеряны!) |
docker compose logs -f | Отслеживает логи в реальном времени |
docker compose exec web bash | Заходит в контейнер web |
docker compose stop | Останавливает контейнеры (без удаления) |
docker compose start | Запускает остановленные контейнеры |
docker compose rm | Удаляет остановленные контейнеры |
Пример перезапуска только одного сервиса:
docker compose restart web
Шаг 6: Модификация и пересборка
Если вы изменили docker-compose.yml или нужно пересобрать образ (например, добавили Dockerfile), используйте:
docker compose up -d --build
Для принудительной перезагрузки контейнеров без сборки:
docker compose up -d --force-recreate
Проверка результата
✅ Критерии успеха:
- Контейнеры запущены (
docker compose psпоказываетUp) - Веб-приложение отвечает на
http://localhost:5000и сообщает об успешном подключении к БД - Данные PostgreSQL сохраняются в томе
postgres_data(проверьтеdocker volume ls)
Если что-то не работает:
- Проверьте логи:
docker compose logs - Убедитесь, что порт 5000 не занят другим приложением
- Проверьте, что оба сервиса в одной сети:
docker network inspect myapp_app-network
Возможные проблемы
Ошибка: Error response from daemon: port is already allocated
Причина: Порт 5000 уже используется другим процессом. Решение:
- Остановите конфликтующий процесс (
sudo lsof -i:5000иkill) - Или измените проброс портов в
docker-compose.yml(например,"8080:5000")
Ошибка: postgres: connection to server at "db" (172.20.0.2), port 5432 failed: Connection refused
Причина: Веб-контейнер пытается подключиться к БД до её полной готовности. Решение:
- Убедитесь, что в
dbестьhealthcheck(как в примере) - Добавьте в команду
webожидание (например, черезwait-for-it.shилиdockerize) - Или увеличьте
depends_onс условиемcondition: service_healthy
Ошибка: permission denied while trying to connect to the Docker daemon socket
Причина: Текущий пользователь не в группе docker.
Решение:
sudo usermod -aG docker $USER
newgrp docker
Или используйте sudo для команд Docker.
Том postgres_data не создаётся
Причина: Ошибка в синтаксисе volumes или недостаточно прав.
Решение:
- Проверьте отступы в YAML (пробелы, не табы)
- Убедитесь, что в
dbпуть тома/var/lib/postgresql/dataсуществует в образе PostgreSQL - Посмотрите
docker volume ls— том должен называться[каталог]_postgres_data
Образы не скачиваются (ошибки сети)
Причина: Проблемы с доступом к Docker Hub. Решение:
- Настройте DNS в Docker (
/etc/docker/daemon.json) - Используйте зеркало (например,
registry-mirrorsдля Kubernetes/OpenShift) - Или загрузите образы вручную:
docker pull python:3.11-slim