services: app: build: . image: forbidden-stars:latest restart: unless-stopped init: true env_file: - .env # секреты/настройки (один общий формат для dev и prod) environment: # Прод обособлен: контейнер ВСЕГДА production и ИГНОРИРУЕТ APP_ENV из .env # (хоть development, хоть test). БД=/data, STATIC_DIR=/app/static — из Dockerfile. APP_ENV: production # Портов на хост НЕТ: приложение доступно только изнутри сети compose. # Наружу его выставляет сервис tunnel (ниже) через VPS. Из LAN/localhost — недоступно. volumes: - db-data:/data # БД SQLite + WAL-сайдкары - uploads-data:/data/uploads # задел под фото/видео 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: 512m cpus: 1.5 logging: driver: json-file options: max-size: "10m" max-file: "5" # SSH reverse-туннель к VPS: forbiddenstars.ru (VPS:9000) -> app:8000 (по сети compose). # Ключ — в ./deploy/tunnel/id_tunnel (gitignore), его pubkey в authorized_keys у tunnel@VPS. # VPS_TUNNEL_HOST/USER берутся из .env (на Pi заполни их там же). 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_USER: ${VPS_TUNNEL_USER:-tunnel} VPS_TUNNEL_PORT: "9000" # forbiddenstars.ru (прод); у test — 9001 UPSTREAM: app:8000 volumes: - ./deploy/tunnel/id_tunnel:/key/id_tunnel:ro mem_limit: 64m volumes: db-data: uploads-data: