Главная/Материалы/Материал

Стек Compose

Пять сервисов, две сети, порядок старта. Схема соответствует проекту 3.

Состав

text
                 хост
                  │  127.0.0.1:8000
                  ▼
        ╔═════════════════════╗
        ║  сеть frontend      ║
        ║                     ║
        ║      ┌───────┐      ║
        ║      │  api  │      ║
        ║      └───┬───┘      ║
        ╚══════════┼══════════╝
                   │
        ╔══════════┼════════════════════════════╗
        ║  сеть backend  (internal: true)       ║
        ║          │                            ║
        ║    ┌─────┴─────┬──────────┐           ║
        ║    ▼           ▼          ▼           ║
        ║ ┌─────┐   ┌───────┐  ┌────────┐       ║
        ║ │ db  │   │ cache │  │ worker │       ║
        ║ └──┬──┘   └───┬───┘  └────────┘       ║
        ║    │          │                       ║
        ║ ┌──┴───┐  ┌───┴─────┐                 ║
        ║ │pgdata│  │cachedata│  тома           ║
        ║ └──────┘  └─────────┘                 ║
        ║                                       ║
        ║        ┌─────────┐                    ║
        ║        │ migrate │  разовая задача    ║
        ║        └─────────┘                    ║
        ╚═══════════════════════════════════════╝

Как читать

Двойная рамка — сеть, не машина: всё это работает на одном хосте. api состоит в двух сетях, потому что он единственный принимает запросы снаружи.

migrate нарисован отдельно: это не сервис, а задача, которая завершается.

Порядок старта

text
   время ──────────────────────────────────────────────►

   db      [запуск][инициализация][healthy ✓]──────────────
                                      │
   cache   [запуск][healthy ✓]────────┤
                                      │
   migrate                            └►[применяет][exit 0]
                                                      │
   api                                                └►[запуск][healthy ✓]
   worker                                             └►[запуск]

Три разных условия, и каждое нужно своё:

СервисЖдётУсловие
migrateГотовности базыservice_healthy
apiСхемы и зависимостейservice_completed_successfully + service_healthy
workerСхемыservice_completed_successfully

Что здесь неочевидно

depends_on в форме списка ждёт запуска, а не готовности.

text
    depends_on: [db]                depends_on:
                                      db:
                                        condition: service_healthy
    ────────────────────            ────────────────────────────
    db: container запущен            db: pg_isready отвечает
    api: стартует                    api: стартует
    api: Connection refused          api: подключается

PostgreSQL после старта container'а несколько секунд инициализирует кластер. Симптом плавающий: на прогретой машине успевает, на холодной нет.

migrate должен завершиться, а не работать.

bash
docker compose ps --format 'table {{.Service}}\t{{.Status}}'
text
api       Up 30 seconds (healthy)
cache     Up 45 seconds (healthy)
db        Up 45 seconds (healthy)
migrate   Exited (0) 35 seconds ago     ← правильно
worker    Up 30 seconds (healthy)

migrate в состоянии Up означает, что в конце команды стоит что-то вроде sleep infinity — container живёт, работа не сделана, никто не узнает.

internal: true у backend запрещает выход наружу изнутри. Это не то же, что «не публиковать порты»: то управляет входом, это — выходом.

Три конфигурации из одного файла

text
compose.yaml                    базовая
    │
    ├── + compose.dev.yaml      разработка:
    │                             монтирование кода,
    │                             порты базы на 127.0.0.1,
    │                             read_only: !override false
    │
    └── + compose.test.yaml     тесты:
                                  tmpfs вместо тома,
                                  fsync=off,
                                  сервис tests
bash
docker compose up -d                                        # базовая
docker compose -f compose.yaml -f compose.dev.yaml up -d    # разработка
docker compose -f compose.yaml -f compose.test.yaml run --rm tests

Отдельные файлы, а не профили: когда отличий много, в одном файле отладочные настройки рано или поздно уезжают в эксплуатацию.

Проверка воспроизводимости

Один успешный запуск ничего не доказывает — гонка проявляется не всегда:

bash
for i in $(seq 10); do
  docker compose down -v >/dev/null 2>&1
  docker compose up -d >/dev/null 2>&1
  sleep 15
  printf '%2d: %s\n' "$i" "$(docker compose ps api --format '{{.Status}}')"
done

Десять запусков из чистого состояния — минимальная проверка.

Подробнее

Урок 9.4. Healthcheck и зависимости
Урок 9.7. Практический стек
Проект 3. Multi-service stack


Навигация

Раздел 09. Docker Compose
Диаграмма сети
Главное оглавление

Markdown на GitHub ↗