171b71b7e0
A workflow_dispatch-only rollout from master (confirm=deploy): - .gitea/workflows/prod-deploy.yaml builds + pushes the images to the registry, ships the compose/config/certs/env over SSH, deploys the main host via prod-deploy.sh, then the bot host, then verifies the public site. - deploy/prod-deploy.sh rolls the main stack one service at a time in dependency order (postgres->backend->gateway->landing->validator->caddy), health-checking after each; any failure rolls the whole stack back to the previous tag. A schema migration adds a maintenance window: the backend (sole writer) is stopped for a consistent pg_dump before migrating; image rollback stays DB-safe (expand-contract), the dump is kept for a manual restore. - prod overlay: pull the four main images from the registry by tag. - Runtime secrets reach the host via a sourced env.sh (single-quoted values keep the bcrypt hash's literal $ intact, unlike a --env-file).
99 lines
2.5 KiB
YAML
99 lines
2.5 KiB
YAML
# Production main-host overlay, applied on top of docker-compose.yml on the main host:
|
|
# docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
|
|
#
|
|
# It (1) publishes caddy 80/443 — there is no host caddy in prod, so the contour caddy
|
|
# owns the edge and does its own ACME on CADDY_SITE_ADDRESS — and the gateway bot-link
|
|
# :9443 the remote bot dials in over mTLS; and (2) retunes the R7 limits down for the
|
|
# 2 vCPU / 1.9 GiB host (GOMAXPROCS=2, smaller memory caps, shorter Prometheus
|
|
# retention). The contour launches deliberately undersized at zero players; the added
|
|
# node_exporter + Grafana watch host memory so it can be resized at Selectel when
|
|
# traffic arrives.
|
|
#
|
|
# The bot + its VPN sidecar are absent here (the telegram-local profile is not
|
|
# activated); the prod bot runs on its own host from docker-compose.bot.yml.
|
|
|
|
services:
|
|
caddy:
|
|
ports:
|
|
- "80:80"
|
|
- "443:443"
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 96M
|
|
|
|
gateway:
|
|
# Prod pulls the pushed image by tag instead of building locally; the base
|
|
# build: section stays dormant because the deploy always pulls first.
|
|
image: ${REGISTRY:?set REGISTRY}/scrabble-gateway:${TAG:?set TAG}
|
|
ports:
|
|
- "9443:9443"
|
|
environment:
|
|
# 2 vCPU host: align the Go scheduler with the cgroup quota (R7's 3 needs 3 cores).
|
|
GOMAXPROCS: "2"
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: "2.0"
|
|
memory: 384M
|
|
|
|
backend:
|
|
image: ${REGISTRY:?set REGISTRY}/scrabble-backend:${TAG:?set TAG}
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 384M
|
|
|
|
postgres:
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 384M
|
|
|
|
validator:
|
|
image: ${REGISTRY:?set REGISTRY}/scrabble-telegram-validator:${TAG:?set TAG}
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 96M
|
|
|
|
landing:
|
|
image: ${REGISTRY:?set REGISTRY}/scrabble-landing:${TAG:?set TAG}
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 64M
|
|
|
|
otelcol:
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 256M
|
|
|
|
prometheus:
|
|
command:
|
|
- --config.file=/etc/prometheus/prometheus.yml
|
|
- --storage.tsdb.retention.time=7d
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 256M
|
|
|
|
tempo:
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 384M
|
|
|
|
grafana:
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 256M
|
|
|
|
postgres_exporter:
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 64M
|