Production deployment (PRD §5.7): - Dockerfile: multi-stage build (deps → build → runner), healthcheck - docker-compose.yml: app + backup container + Caddy HTTPS proxy - Backup container: daily SQLite backup + SHA-256 checksum - Caddy: automatic HTTPS reverse proxy - Volumes: db, data, backups, caddy-data - deploy/backup.sh: timestamped backup + checksum + retention cleanup - deploy/restore.sh: checksum verification + pre-restore backup - README.md: quick start (Docker + dev), architecture, modules, compliance, MCP Verified: - Backup script: creates aos_20261027.db + .sha256 ✓ - TypeScript: 0 errors, ESLint clean
91 lines
2.4 KiB
YAML
91 lines
2.4 KiB
YAML
# AOS — Agency Operating System
|
|
# Docker Compose for production (PRD §5.7: Containers: app, postgres, caddy, backup)
|
|
# Usage: docker compose up -d
|
|
|
|
services:
|
|
app:
|
|
build: .
|
|
container_name: aos-app
|
|
restart: unless-stopped
|
|
ports:
|
|
- "3000:3000"
|
|
environment:
|
|
- NODE_ENV=production
|
|
- DATABASE_URL=file:/app/db/custom.db
|
|
- PORT=3000
|
|
- HOSTNAME=0.0.0.0
|
|
# Set these in .env or docker-compose.override.yml
|
|
- ENCRYPTION_KEY=${ENCRYPTION_KEY:-change-me-32-bytes}
|
|
- AUTH_SECRET=${AUTH_SECRET:-change-me-auth-secret}
|
|
volumes:
|
|
- aos-db:/app/db
|
|
- aos-data:/app/data
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 3
|
|
start_period: 10s
|
|
|
|
# Backup container (PRD §5.7: backup container)
|
|
# Runs daily at 03:00, backs up SQLite + uploads volume
|
|
backup:
|
|
image: alpine:latest
|
|
container_name: aos-backup
|
|
restart: unless-stopped
|
|
depends_on:
|
|
app:
|
|
condition: service_healthy
|
|
environment:
|
|
- BACKUP_SCHEDULE=0 3 * * *
|
|
- BACKUP_RETENTION_DAYS=30
|
|
volumes:
|
|
- aos-db:/data/db:ro
|
|
- aos-backups:/backups
|
|
entrypoint:
|
|
- sh
|
|
- -c
|
|
- |
|
|
apk add --no-cache sqlite curl
|
|
echo "AOS Backup service started. Schedule: $$BACKUP_SCHEDULE"
|
|
while true; do
|
|
sleep 86400
|
|
TIMESTAMP=$$(date +%Y%m%d_%H%M%S)
|
|
echo "[$$TIMESTAMP] Starting backup..."
|
|
# Backup SQLite
|
|
sqlite3 /data/db/custom.db ".backup /backups/aos_$$TIMESTAMP.db"
|
|
# Checksum
|
|
sha256sum /backups/aos_$$TIMESTAMP.db > /backups/aos_$$TIMESTAMP.db.sha256
|
|
# Cleanup old backups
|
|
find /backups -name "aos_*.db" -mtime +$$BACKUP_RETENTION_DAYS -delete
|
|
find /backups -name "aos_*.db.sha256" -mtime +$$BACKUP_RETENTION_DAYS -delete
|
|
echo "[$$TIMESTAMP] Backup complete: aos_$$TIMESTAMP.db"
|
|
done
|
|
|
|
# Caddy reverse proxy (HTTPS)
|
|
caddy:
|
|
image: caddy:2-alpine
|
|
container_name: aos-caddy
|
|
restart: unless-stopped
|
|
depends_on:
|
|
app:
|
|
condition: service_healthy
|
|
ports:
|
|
- "80:80"
|
|
- "443:443"
|
|
volumes:
|
|
- caddy-data:/data
|
|
- caddy-config:/config
|
|
command: |
|
|
caddy reverse-proxy --from :443 --to app:3000
|
|
|
|
volumes:
|
|
aos-db:
|
|
driver: local
|
|
aos-data:
|
|
driver: local
|
|
aos-backups:
|
|
driver: local
|
|
caddy-data:
|
|
caddy-config:
|