Учебное руководство
Главы руководства
На этой странице

Docker, Compose, сеть и хранение

Оглавление · Далее: настройки

Почему несколько контейнеров

Next.js и Strapi имеют собственные образы. PostgreSQL, Garage и Caddy используют готовые образы; каждый сервис хранит данные в своих томах.

СервисОбраз/targetВнутренний портНазначение
postgrespostgres:17-alpine5432База CMS
webtarget web3000Next.js
strapiinfra/strapi/Dockerfile1337CMS и её API
caddycaddy:2-alpine80 / 443Входной proxy

Теги node:24-bookworm-slim, postgres:17-alpine, caddy:2-alpine закрепляют ветку, но не полный digest. Web/Strapi в production получают digest из текущей сборки Actions. Все зависимости инфраструктуры пока не воспроизводятся побитово между произвольными датами pull.

Этапы Dockerfile

Корневой Dockerfile:

  1. build: Node 24, pnpm, установка по lockfile и сборка contracts.
  2. web-build: чтение CMS с BuildKit secret и статическая сборка Next.js.
  3. web: копирование Next standalone, .next/static и public; запуск под node.

Standalone — минимальная серверная сборка Next.js со traced dependencies. outputFileTracingRoot расширен до корня монорепо, чтобы попасть могли локальные workspace-пакеты. Без копирования static/public HTML мог бы открываться без картинок, стилей или robots.txt.

Strapi Dockerfile сначала устанавливает build tools и npm ci, собирает CMS, затем выполняет npm prune --omit=dev. Build tools не устанавливаются в финальном stage отдельно; runtime содержит файлы собранного приложения и production-пакеты.

.dockerignore исключает node_modules, сборки и .env. .gitignore и .dockerignore — разные механизмы: добавление файла в один не меняет другой.

Profile и production override

Локально web, strapi и caddy используют profile app. infra:up запускает PostgreSQL и Garage.

compose.production.yaml накладывается после базового Compose:

  • build заменяется на !reset null, используются готовые образы;
  • profiles сбрасываются, чтобы все приложения запускались обычным up;
  • CMS получает реальные домены и защиту панели;
  • PostgreSQL init-файл монтируется со стабильного пути /opt/gheilt/postgres-init.sh;
  • Caddy использует production Caddyfile.

Compose объединяет volume entries по пути назначения. Поэтому override заменяет init script/Caddyfile, но сохраняет том с данными PostgreSQL и тома Caddy.

Адрес внутри сети и адрес на хосте

СоединениеПравильный адрес
Web → Strapistrapi:1337, read-only token
Web → Garage websites3:3902, фиксированный Host
Strapi → Garage S3s3:3900, S3 credentials
Strapi → PostgreSQLpostgres:5432
Strapi → webhookhttp://web:3000/api/webhooks/strapi
Браузер → локальный сайт Dockerlocalhost:8080

Порты Caddy локально привязаны не только к loopback: учитывайте настройки firewall и доверие к сети компьютера. Локальный CMS-домен и панели не стоит считать защищёнными потому, что это dev-сборка.

Тома и базы

Init script создаёт пользователя и базу strapi.

Имя ComposeФактическое имя для project gheiltЧто хранится
postgres_dataatmanki_postgres_dataВсе базы PostgreSQL
strapi_uploadsatmanki_strapi_uploadsСтарые local uploads (сохраняются)
caddy_dataatmanki_caddy_dataTLS-данные Caddy
caddy_configatmanki_caddy_configСохранённая конфигурация Caddy

Init scripts образа PostgreSQL выполняются на новом пустом data volume. Изменение файла или .env при уже созданном томе не создаст пользователей заново и не поменяет существующие пароли. Нужна явная миграция/ротация.

down сохраняет named volumes. down -v удаляет их. Не удаляйте тома для решения проблемы несовпадения паролей без понимания, какие данные исчезнут.

Порядок запуска и перезапуска

restart: unless-stopped — отдельная политика Docker для контейнера после выхода процесса или перезапуска daemon. Она не означает, что приложение с зависшей бизнес- логикой обязательно будет признано неисправным.

Различие и порядок запуска в документации Compose.

HealthcheckЧто реально проверяет
PostgreSQLpg_isready
Web/api/health
Strapi/_health
CaddyСобственного healthcheck нет

up --wait проверяет healthcheck, а чтение контента проверяется отдельно через /api/content-health.

Где смотреть код

Compose, override, Dockerfile, Strapi image, init script, Caddy.

Отдельный S3-сервис

Garage 2.3.0 запускается одним узлом, с двумя persistent volumes: s3_data и s3_metadata. S3 API 3900 и website 3902 опубликованы только на loopback; RPC 3901 не опубликован. Caddy отдаёт публичный bucket media по отдельному media-домену, с фиксированным upstream Host. Strapi сохраняет новые uploads через официальный AWS S3 provider, прежние local uploads остаются в старом томе.

pnpm infra:up теперь также запускает Garage; pnpm infra:s3 запускает только хранилище и включает website для bucket. stack:up делает эту подготовку до запуска приложений. Подробности.

Отдельный стек наблюдаемости

infra/observability/compose.yaml использует project atmanki-observability, готовые закреплённые образы и собственные тома. Umami и GlitchTip подключаются к существующей PostgreSQL с разными ролями. Grafana имеет частную сеть для Prometheus и общую сеть atmanki_default для Caddy. Prometheus и exporters не имеют портов на хосте. Docker socket этому стеку не передаётся.

Для сервисов заданы hard limits памяти: Umami 384 MiB, GlitchTip 512 MiB, Grafana 512 MiB, Prometheus 192 MiB, exporters по 48 MiB. Сумма — 1696 MiB; она не включает существующие приложения и PostgreSQL. Лимит предотвращает неограниченный рост контейнера, но при превышении может завершить процесс OOM. Проверка startup в CI и измерение на VPS — разные проверки.

Учебный разбор объясняет сети, сбор метрик и ограничения одного VPS. Наличие конфигурации в Git не подтверждает публикацию стека.