Docker, Compose, сеть и хранение
Оглавление · Далее: настройки
Почему несколько контейнеров
Next.js и Strapi имеют собственные образы. PostgreSQL, Garage и Caddy используют готовые образы; каждый сервис хранит данные в своих томах.
| Сервис | Образ/target | Внутренний порт | Назначение |
|---|---|---|---|
postgres | postgres:17-alpine | 5432 | База CMS |
web | target web | 3000 | Next.js |
strapi | infra/strapi/Dockerfile | 1337 | CMS и её API |
caddy | caddy:2-alpine | 80 / 443 | Входной proxy |
Теги node:24-bookworm-slim, postgres:17-alpine, caddy:2-alpine закрепляют
ветку, но не полный digest. Web/Strapi в production получают digest
из текущей сборки Actions. Все зависимости инфраструктуры пока не воспроизводятся
побитово между произвольными датами pull.
Этапы Dockerfile
Корневой Dockerfile:
build: Node 24, pnpm, установка по lockfile и сборка contracts.web-build: чтение CMS с BuildKit secret и статическая сборка Next.js.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 → Strapi | strapi:1337, read-only token |
| Web → Garage website | s3:3902, фиксированный Host |
| Strapi → Garage S3 | s3:3900, S3 credentials |
| Strapi → PostgreSQL | postgres:5432 |
| Strapi → webhook | http://web:3000/api/webhooks/strapi |
| Браузер → локальный сайт Docker | localhost:8080 |
Порты Caddy локально привязаны не только к loopback: учитывайте настройки firewall и доверие к сети компьютера. Локальный CMS-домен и панели не стоит считать защищёнными потому, что это dev-сборка.
Тома и базы
Init script создаёт пользователя и базу strapi.
| Имя Compose | Фактическое имя для project gheilt | Что хранится |
|---|---|---|
postgres_data | atmanki_postgres_data | Все базы PostgreSQL |
strapi_uploads | atmanki_strapi_uploads | Старые local uploads (сохраняются) |
caddy_data | atmanki_caddy_data | TLS-данные Caddy |
caddy_config | atmanki_caddy_config | Сохранённая конфигурация Caddy |
Init scripts образа PostgreSQL выполняются на новом пустом data volume.
Изменение файла или .env при уже созданном томе не создаст пользователей заново
и не поменяет существующие пароли. Нужна явная миграция/ротация.
down сохраняет named volumes. down -v удаляет их. Не удаляйте тома для решения
проблемы несовпадения паролей без понимания, какие данные исчезнут.
Порядок запуска и перезапуска
restart: unless-stopped — отдельная политика Docker для контейнера после выхода
процесса или перезапуска daemon. Она не означает, что приложение с зависшей бизнес-
логикой обязательно будет признано неисправным.
Различие и порядок запуска в документации Compose.
| Healthcheck | Что реально проверяет |
|---|---|
| PostgreSQL | pg_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 не подтверждает публикацию стека.