Files
at-container-registry/deploy/docker-compose.prod.yml
2026-02-10 22:11:21 -06:00

164 lines
4.6 KiB
YAML

# ATCR Production Deployment with Caddy
# For UpCloud Rocky Linux deployment
#
# Usage:
# 1. Copy .env.prod.template to .env and fill in your values
# 2. docker compose -f deploy/docker-compose.prod.yml up -d
#
# Domains:
# - atcr.io → AppView (registry API + web UI)
# - hold01.atcr.io → Hold service (presigned URL generator)
# - blobs.atcr.io → S3 object storage (CNAME to UpCloud S3)
services:
caddy:
image: caddy:2-alpine
container_name: atcr-caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp" # HTTP/3
environment:
APPVIEW_DOMAIN: ${APPVIEW_DOMAIN:-atcr.io}
HOLD_DOMAIN: ${HOLD_DOMAIN:-hold01.atcr.io}
volumes:
- caddy_data:/data
- caddy_config:/config
configs:
- source: caddyfile
target: /etc/caddy/Caddyfile
networks:
- atcr-network
healthcheck:
test: ["CMD", "caddy", "validate", "--config", "/etc/caddy/Caddyfile"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
atcr-appview:
build:
context: ..
dockerfile: Dockerfile.appview
image: atcr-appview:latest
container_name: atcr-appview
restart: unless-stopped
command: ["serve", "--config", "/config.yaml"]
# Base config: config-appview.example.yaml
# Env vars below override config file values for this deployment
environment:
ATCR_BASE_URL: https://${APPVIEW_DOMAIN:-atcr.io}
ATCR_DEFAULT_HOLD_DID: ${ATCR_DEFAULT_HOLD_DID:-did:web:${HOLD_DOMAIN:-hold01.atcr.io}}
ATCR_LOG_LEVEL: ${ATCR_LOG_LEVEL:-info}
ATCR_LOG_FORMATTER: ${ATCR_LOG_FORMATTER:-text}
volumes:
- ./config-appview.yaml:/config.yaml:ro
# Persistent data: auth keys, UI database, OAuth tokens, Jetstream cache
- atcr-appview-data:/var/lib/atcr
networks:
- atcr-network
healthcheck:
test: ["CMD", "/healthcheck", "http://localhost:5000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
atcr-hold:
build:
context: ..
dockerfile: Dockerfile.hold
image: atcr-hold:latest
container_name: atcr-hold
restart: unless-stopped
command: ["serve", "--config", "/config.yaml"]
# Base config: config-hold.example.yaml
# Env vars below override config file values for this deployment
environment:
HOLD_PUBLIC_URL: ${HOLD_PUBLIC_URL:-https://${HOLD_DOMAIN:-hold01.atcr.io}}
HOLD_OWNER: ${HOLD_OWNER:-}
HOLD_BLUESKY_POSTS_ENABLED: ${HOLD_BLUESKY_POSTS_ENABLED:-true}
# S3/UpCloud Object Storage (REQUIRED)
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID:-}
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY:-}
AWS_REGION: ${AWS_REGION:-us-east-1}
S3_BUCKET: ${S3_BUCKET:-atcr-blobs}
S3_ENDPOINT: ${S3_ENDPOINT:-}
HOLD_LOG_LEVEL: ${ATCR_LOG_LEVEL:-info}
volumes:
- ./config-hold.yaml:/config.yaml:ro
# PDS data (carstore SQLite + signing keys)
- atcr-hold-data:/var/lib/atcr-hold
- ./quotas.yaml:/quotas.yaml:ro
networks:
- atcr-network
healthcheck:
test: ["CMD", "/healthcheck", "http://localhost:8080/xrpc/_health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
networks:
atcr-network:
driver: bridge
ipam:
config:
- subnet: 172.29.0.0/24
volumes:
caddy_data:
driver: local
caddy_config:
driver: local
atcr-appview-data:
driver: local
atcr-hold-data:
driver: local
configs:
caddyfile:
content: |
# ATCR AppView - Main registry + web UI
${APPVIEW_DOMAIN:-atcr.io} {
# Reverse proxy to AppView container
reverse_proxy atcr-appview:5000 {
# Preserve original host header
header_up Host {host}
header_up X-Real-IP {remote_host}
}
# Enable compression
encode gzip
# Logging
log {
output file /data/logs/appview.log {
roll_size 100mb
roll_keep 10
}
}
}
# ATCR Hold Service - Storage presigned URL generator
${HOLD_DOMAIN:-hold01.atcr.io} {
# Reverse proxy to Hold service container
reverse_proxy atcr-hold:8080 {
# Preserve original host header
header_up Host {host}
header_up X-Real-IP {remote_host}
}
# Enable compression
encode gzip
# Logging
log {
output file /data/logs/hold.log {
roll_size 100mb
roll_keep 10
}
}
}