version: '3.8' # Production Docker Compose Configuration # Usage: docker compose -f docker-compose.prod.yml up -d services: # ========================================== # Gitea - Production Configuration # ========================================== gitea: image: gitea/gitea:latest-rootless container_name: xflow-gitea restart: unless-stopped networks: - xflow-network volumes: - gitea-data:/data - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro environment: - USER_UID=1000 - USER_GID=1000 - GITEA__database__DB_TYPE=postgres - GITEA__database__HOST=postgres:5432 - GITEA__database__NAME=gitea - GITEA__database__USER=gitea - GITEA__database__PASSWD=${POSTGRES_PASSWORD} - GITEA__server__DOMAIN=${GITEA_DOMAIN} - GITEA__server__ROOT_URL=https://${GITEA_DOMAIN} - GITEA__server__SSH_DOMAIN=${GITEA_DOMAIN} - GITEA__server__SSH_PORT=222 - GITEA__server__SSH_LISTEN_PORT=22 - GITEA__security__INSTALL_LOCK=true - GITEA__security__SECRET_KEY=${GITEA_SECRET_KEY} - GITEA__service__DISABLE_REGISTRATION=false - GITEA__service__REQUIRE_SIGNIN_VIEW=false - GITEA__log__MODE=console - GITEA__log__LEVEL=Info healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/api/healthz"] interval: 30s timeout: 10s retries: 3 start_period: 40s deploy: resources: limits: cpus: '1.0' memory: 512M reservations: cpus: '0.25' memory: 128M # ========================================== # PostgreSQL - Production # ========================================== postgres: image: postgres:16-alpine container_name: xflow-postgres restart: unless-stopped networks: - xflow-network volumes: - postgres-data:/var/lib/postgresql/data - ./backups:/backups environment: - POSTGRES_USER=gitea - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - POSTGRES_DB=gitea - PGDATA=/var/lib/postgresql/data/pgdata healthcheck: test: ["CMD-SHELL", "pg_isready -U gitea"] interval: 10s timeout: 5s retries: 5 deploy: resources: limits: cpus: '0.5' memory: 256M reservations: cpus: '0.1' memory: 64M # ========================================== # Nginx - Production with SSL # ========================================== nginx: image: nginx:alpine container_name: xflow-nginx restart: unless-stopped networks: - xflow-network ports: - "80:80" - "443:443" volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx/html:/usr/share/nginx/html:ro - ./nginx/ssl:/etc/nginx/ssl:ro - certbot-data:/etc/letsencrypt:ro - certbot-www:/var/www/certbot:ro healthcheck: test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/health"] interval: 30s timeout: 10s retries: 3 deploy: resources: limits: cpus: '0.25' memory: 128M depends_on: - gitea # ========================================== # Certbot - SSL Certificates # ========================================== certbot: image: certbot/certbot container_name: xflow-certbot restart: "no" networks: - xflow-network volumes: - certbot-data:/etc/letsencrypt - certbot-www:/var/www/certbot entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'" profiles: - ssl # ========================================== # Watchtower - Auto-update containers # ========================================== watchtower: image: containrrr/watchtower container_name: xflow-watchtower restart: unless-stopped networks: - xflow-network volumes: - /var/run/docker.sock:/var/run/docker.sock environment: - WATCHTOWER_CLEANUP=true - WATCHTOWER_POLL_INTERVAL=3600 - WATCHTOWER_INCLUDE_STOPPED=true - WATCHTOWER_REVIVE_STOPPED=false - WATCHTOWER_ROLLING_RESTART=true - WATCHTOWER_LABEL_ENABLE=true command: --interval 3600 --cleanup profiles: - auto-update # ========================================== # Redis - Caching (optional) # ========================================== redis: image: redis:7-alpine container_name: xflow-redis restart: unless-stopped networks: - xflow-network volumes: - redis-data:/data command: redis-server --appendonly yes --maxmemory 64mb --maxmemory-policy allkeys-lru healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 3s retries: 3 deploy: resources: limits: cpus: '0.25' memory: 128M profiles: - cache networks: xflow-network: driver: bridge ipam: config: - subnet: 172.20.0.0/16 volumes: gitea-data: driver: local postgres-data: driver: local api-logs: driver: local certbot-data: driver: local certbot-www: driver: local redis-data: driver: local