Files
ForbiddenStarsApp/docker-compose.yml
T
NotBigGhostandClaude Opus 5 ec1e94119c Чистка: устаревшие комментарии и подсказки, export-скрипт, мусорный файл
Комментарии про методы входа приведены к факту (логин/пароль и Telegram везде,
stub только в development): config.py, .env.example, telegram.py, dev_stub.py,
dev_auth.py, login.py. admin_login.py больше не обещает «строже игроцкого» —
описаны реальные лимиты; client_ip — адрес за прокси уже даёт uvicorn.

Подсказки деплоя: run.ps1/run.sh (build-push на ПК, `up -d` на Pi), compose,
.env.example (build-push.ps1), Caddyfile (туннель-контейнер вместо autossh);
ratelimit.py ссылается на core/events.py вместо CLAUDE.md.

Удалены неиспользуемые scripts/export-prod.sh (с блоком export-ignore в
.gitattributes и упоминаниями в README), db/init_db.py и случайно закоммиченный
файл «h -u origin dev…». #70

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LqSoRj99iwVEH5U5fnZgsd
2026-09-19 03:12:16 +03:00

120 lines
7.0 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ─────────────────────────────────────────────────────────────────────────────
# ПРОД на Raspberry Pi (forbiddenstars.ru) — единый compose: приложение + туннель.
# На Pi нужны только ДВА файла: этот docker-compose.yml и .env. Репозиторий, сборка и
# файл ключа не нужны: образы тянутся из реестра (pull_policy: always), а приватный ключ
# туннеля лежит в .env (TUNNEL_KEY_B64, base64). build: оставлен для сборки/пуша на ПК
# (scripts/build-push.*) — на Pi он не используется.
#
# Запуск/обновление: docker compose up -d (сам тянет свежие образы)
# Логи: docker compose logs -f app (или: ... tunnel / backup)
# Остановка: docker compose down (данные в томах сохраняются)
# Бэкапы: docker compose exec backup fs-backup status (help — все команды)
# инструкция: deploy/backup/README.md
#
# НИКОГДА не выполняйте на проде `docker compose down -v`: флаг -v удаляет тома — и данные
# приложения, и локальный репозиторий бэкапов (останется только копия на VPS).
#
# Контейнер ВСЕГДА production: APP_ENV форсится здесь и игнорирует значение из .env.
# Порты на хост НЕ публикуются — наружу приложение выставляет только сервис tunnel
# (SSH reverse-туннель к VPS). Из LAN/localhost оно недоступно.
# ─────────────────────────────────────────────────────────────────────────────
services:
app:
build: .
# Образ из реестра (Gitea): собирается под arm64 на ПК (scripts/build-push.ps1, в Linux —
# .sh) и тянется на Pi. build: нужен только этой сборке на ПК — на Pi не используется.
image: ${IMAGE_REGISTRY:-gitea.arseniev.info/notbigghost}/forbidden-stars:${IMAGE_TAG:-latest}
pull_policy: always # на Pi всегда тянем образ из реестра (без сборки)
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).
# Приватный ключ — в .env как TUNNEL_KEY_B64 (base64); pubkey — в authorized_keys у tunnel@VPS.
tunnel:
build: ./deploy/tunnel
image: ${IMAGE_REGISTRY:-gitea.arseniev.info/notbigghost}/forbidden-stars-tunnel:${IMAGE_TAG:-latest}
pull_policy: always
restart: unless-stopped
init: true
depends_on:
app:
condition: service_healthy
environment:
VPS_TUNNEL_HOST: ${VPS_TUNNEL_HOST} # обязателен; tunnel.sh упадёт с ошибкой, если пуст
VPS_TUNNEL_USER: ${VPS_TUNNEL_USER:-tunnel}
VPS_TUNNEL_PORT: ${VPS_TUNNEL_PORT:-9000} # прод-слот (forbiddenstars.ru)
UPSTREAM: app:8000
TUNNEL_KEY_B64: ${TUNNEL_KEY_B64:-} # приватный ключ туннеля (base64), из .env
mem_limit: 64m
security_opt:
- no-new-privileges:true
# Бэкапы (restic): снимки по расписанию в локальный репозиторий (том backup-data) и на VPS
# (SFTP, если задан BACKUP_VPS_HOST). От app не зависит и app не мешает. Переменные —
# только BACKUP_* (секреты приложения сюда не передаются). Всё про настройку и
# восстановление — deploy/backup/README.md.
backup:
build: ./deploy/backup
image: ${IMAGE_REGISTRY:-gitea.arseniev.info/notbigghost}/forbidden-stars-backup:${IMAGE_TAG:-latest}
pull_policy: always
restart: unless-stopped
environment:
BACKUP_PASSWORD: ${BACKUP_PASSWORD:-} # пароль шифрования; пусто = бэкапы отключены
BACKUP_HOSTNAME: fs-prod # имя хоста в снимках
BACKUP_SCHEDULE: ${BACKUP_SCHEDULE:-0 4 * * *}
BACKUP_VERIFY_SCHEDULE: ${BACKUP_VERIFY_SCHEDULE:-30 5 * * 0}
BACKUP_KEEP_DAILY: ${BACKUP_KEEP_DAILY:-14}
BACKUP_KEEP_WEEKLY: ${BACKUP_KEEP_WEEKLY:-8}
BACKUP_KEEP_MONTHLY: ${BACKUP_KEEP_MONTHLY:-12}
BACKUP_COMPRESSION: ${BACKUP_COMPRESSION:-max}
BACKUP_MAX_AGE_HOURS: ${BACKUP_MAX_AGE_HOURS:-30}
BACKUP_VPS_HOST: ${BACKUP_VPS_HOST:-}
BACKUP_VPS_USER: ${BACKUP_VPS_USER:-fsbackup}
BACKUP_VPS_PORT: ${BACKUP_VPS_PORT:-22}
BACKUP_VPS_DIR: ${BACKUP_VPS_DIR:-/srv/fs-backups/restic}
BACKUP_SSH_KEY_B64: ${BACKUP_SSH_KEY_B64:-}
TZ: ${BACKUP_TZ:-Europe/Moscow}
volumes:
- db-data:/fs-db # живая БД (снимается консистентно)
- uploads-data:/fs/uploads
- achievements-data:/fs/achievements
- backup-data:/backup # локальный репозиторий restic + состояние
mem_limit: ${BACKUP_MEM_LIMIT:-384m}
security_opt:
- no-new-privileges:true
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
volumes:
db-data:
uploads-data:
achievements-data:
backup-data: