- docker-compose.yml: слот туннеля параметризован (${VPS_TUNNEL_PORT:-9000}), VPS_TUNNEL_HOST
стал обязательным (${...:?}), лимиты ресурсов из .env (APP_MEM_LIMIT/APP_CPUS),
stop_grace_period 30s (чек-пойнт WAL SQLite), security_opt no-new-privileges на обоих сервисах;
healthcheck/логирование/тома сохранены (имена томов не менялись — данные не осиротеют).
- .env.example: VPS_TUNNEL_PORT по умолчанию НЕ задаётся (каждый контур берёт свой слот:
dev→9001, prod→9000, test→9001); добавлены ADMIN_NICKNAME, DEV/PROD_ACHIEVEMENTS_DIR,
APP_MEM_LIMIT/APP_CPUS.
- deploy/pi/README: чек-лист .env для Pi; запуск одним `docker compose up -d --build`.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
71 lines
3.6 KiB
YAML
71 lines
3.6 KiB
YAML
# ─────────────────────────────────────────────────────────────────────────────
|
||
# ПРОД на Raspberry Pi (forbiddenstars.ru) — единый compose: приложение + туннель.
|
||
# Все настройки и секреты — в корневом .env (см. .env.example). Этот файл их только
|
||
# пробрасывает; ничего секретного тут нет.
|
||
#
|
||
# Запуск/обновление: docker compose up -d --build
|
||
# Логи: docker compose logs -f app (или: ... tunnel)
|
||
# Остановка: docker compose down (данные в томах сохраняются)
|
||
# Бэкап/restore: scripts/backup.sh / scripts/restore.sh
|
||
#
|
||
# Контейнер ВСЕГДА production: APP_ENV форсится здесь и игнорирует значение из .env.
|
||
# Порты на хост НЕ публикуются — наружу приложение выставляет только сервис tunnel
|
||
# (SSH reverse-туннель к VPS). Из LAN/localhost оно недоступно.
|
||
# ─────────────────────────────────────────────────────────────────────────────
|
||
services:
|
||
app:
|
||
build: .
|
||
image: forbidden-stars:latest
|
||
restart: unless-stopped
|
||
init: true # PID 1 пробрасывает сигналы → корректный SIGTERM
|
||
stop_grace_period: 30s # время на чек-пойнт WAL SQLite перед остановкой
|
||
env_file:
|
||
- .env # единый источник настроек/секретов всего приложения
|
||
environment:
|
||
APP_ENV: production # прод обособлен: игнорируем APP_ENV из .env
|
||
volumes:
|
||
- db-data:/data # БД SQLite + WAL-сайдкары
|
||
- uploads-data:/data/uploads # медиа партий
|
||
- achievements-data:/data/achievements # определения титулов (файлы)
|
||
healthcheck:
|
||
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/api/health')"]
|
||
interval: 30s
|
||
timeout: 5s
|
||
retries: 3
|
||
start_period: 40s
|
||
mem_limit: ${APP_MEM_LIMIT:-512m} # лимиты под Pi; переопределяются в .env
|
||
cpus: ${APP_CPUS:-1.5}
|
||
security_opt:
|
||
- no-new-privileges:true
|
||
logging:
|
||
driver: json-file
|
||
options:
|
||
max-size: "10m"
|
||
max-file: "5"
|
||
|
||
# SSH reverse-туннель: VPS:${VPS_TUNNEL_PORT:-9000} → app:8000 (домен forbiddenstars.ru).
|
||
# Ключ — ./deploy/tunnel/id_tunnel (в git не идёт); его pubkey в authorized_keys у tunnel@VPS.
|
||
tunnel:
|
||
build: ./deploy/tunnel
|
||
image: forbidden-stars-tunnel:latest
|
||
restart: unless-stopped
|
||
init: true
|
||
depends_on:
|
||
app:
|
||
condition: service_healthy
|
||
environment:
|
||
VPS_TUNNEL_HOST: ${VPS_TUNNEL_HOST:?VPS_TUNNEL_HOST is required in .env}
|
||
VPS_TUNNEL_USER: ${VPS_TUNNEL_USER:-tunnel}
|
||
VPS_TUNNEL_PORT: ${VPS_TUNNEL_PORT:-9000} # прод-слот (forbiddenstars.ru)
|
||
UPSTREAM: app:8000
|
||
volumes:
|
||
- ./deploy/tunnel/id_tunnel:/key/id_tunnel:ro
|
||
mem_limit: 64m
|
||
security_opt:
|
||
- no-new-privileges:true
|
||
|
||
volumes:
|
||
db-data:
|
||
uploads-data:
|
||
achievements-data:
|