Files
freetable/docker-compose.coolify.yml

160 lines
4.6 KiB
YAML

# FreeTable Coolify Deployment Configuration
# Production stack: Backend (FastAPI+Gunicorn) + Frontend (Nginx) + PostgreSQL
x-common-env: &common-env
TZ: ${TZ:-UTC}
LOG_LEVEL: ${LOG_LEVEL:-INFO}
x-backend-base: &backend-base
build:
context: .
dockerfile: Dockerfile
restart: unless-stopped
depends_on:
db:
condition: service_healthy
networks:
- freetable-network
x-healthcheck-backend: &healthcheck-backend
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
services:
# ==================== PostgreSQL Database ====================
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
<<: *common-env
POSTGRES_DB: ${POSTGRES_DB:-freetable}
POSTGRES_USER: ${POSTGRES_USER:-freetable}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-changeme}
PGDATA: /var/lib/postgresql/data/pgdata
volumes:
- freetable-db-data:/var/lib/postgresql/data
# Optional: Mount SQL init scripts for schema setup
# - ./initdb:/docker-entrypoint-initdb.d:ro
networks:
- freetable-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-freetable} -d ${POSTGRES_DB:-freetable}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
deploy:
resources:
limits:
memory: 512M
cpus: '0.5'
reservations:
memory: 128M
cpus: '0.1'
# ==================== Backend API ====================
backend:
<<: *backend-base
<<: *healthcheck-backend
environment:
<<: *common-env
# Database
DATABASE_URL: postgresql://${POSTGRES_USER:-freetable}:${POSTGRES_PASSWORD:-changeme}@db:5432/${POSTGRES_DB:-freetable}
# Auth
SECRET_KEY: ${SECRET_KEY:-your-secret-key-change-in-production}
ALGORITHM: ${ALGORITHM:-HS256}
ACCESS_TOKEN_EXPIRE_MINUTES: ${ACCESS_TOKEN_EXPIRE_MINUTES:-30}
REFRESH_TOKEN_EXPIRE_DAYS: ${REFRESH_TOKEN_EXPIRE_DAYS:-7}
# CORS
CORS_ORIGINS: ${CORS_ORIGINS:-http://localhost:3000}
# File Uploads
UPLOAD_DIR: /app/uploads
MAX_UPLOAD_SIZE: ${MAX_UPLOAD_SIZE:-10485760}
volumes:
- freetable-uploads:/app/uploads
expose:
- "8000"
deploy:
resources:
limits:
memory: 768M
cpus: '1.0'
reservations:
memory: 256M
cpus: '0.25'
labels:
# Coolify Discovery
coolify.version: "1.0"
coolify.project.name: FreeTable
coolify.service.name: backend
coolify.service.type: api
# Traefik labels for reverse proxy
traefik.enable: "true"
traefik.http.routers.freetable-backend.rule: "PathPrefix(`/api`)"
traefik.http.routers.freetable-backend.entrypoints: websecure
traefik.http.routers.freetable-backend.tls.certresolver: letsencrypt
traefik.http.services.freetable-backend.loadbalancer.server.port: "8000"
# ==================== Frontend (Nginx) ====================
frontend:
image: nginx:alpine
restart: unless-stopped
environment:
<<: *common-env
BACKEND_HOST: backend
BACKEND_PORT: "8000"
PORT: "80"
volumes:
- ./frontend/dist:/usr/share/nginx/html:ro
- ./nginx.conf:/etc/nginx/nginx.conf:ro
networks:
- freetable-network
depends_on:
backend:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
expose:
- "80"
deploy:
resources:
limits:
memory: 128M
cpus: '0.5'
reservations:
memory: 32M
cpus: '0.1'
labels:
# Coolify Discovery
coolify.version: "1.0"
coolify.project.name: FreeTable
coolify.service.name: frontend
coolify.service.type: web
# Traefik labels for reverse proxy
traefik.enable: "true"
traefik.http.routers.freetable-web.rule: "Host(`${COOLIFY_DOMAIN}`)"
traefik.http.routers.freetable-web.entrypoints: websecure
traefik.http.routers.freetable-web.tls.certresolver: letsencrypt
traefik.http.services.freetable-web.loadbalancer.server.port: "80"
# ==================== Networks ====================
networks:
freetable-network:
driver: bridge
name: freetable-network
# ==================== Volumes ====================
volumes:
freetable-db-data:
name: freetable-db-data
freetable-uploads:
name: freetable-uploads