2026-04-11 23:28:23 +08:00
|
|
|
services:
|
2026-04-12 00:03:30 +08:00
|
|
|
db:
|
2026-04-12 21:46:31 +08:00
|
|
|
image: ${POSTGRES_IMAGE:-docker.m.daocloud.io/pgvector/pgvector:pg16}
|
2026-04-12 00:03:30 +08:00
|
|
|
container_name: fquiz-db
|
|
|
|
|
environment:
|
|
|
|
|
POSTGRES_DB: ${POSTGRES_DB:-fquiz}
|
|
|
|
|
POSTGRES_USER: ${POSTGRES_USER:-fquiz}
|
|
|
|
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-fquiz}
|
|
|
|
|
ports:
|
2026-04-12 21:46:31 +08:00
|
|
|
- "${POSTGRES_PORT:-5433}:5432"
|
2026-04-12 00:03:30 +08:00
|
|
|
volumes:
|
|
|
|
|
- fquiz_db_data:/var/lib/postgresql/data
|
|
|
|
|
healthcheck:
|
|
|
|
|
test:
|
|
|
|
|
[
|
|
|
|
|
"CMD-SHELL",
|
|
|
|
|
"pg_isready -U ${POSTGRES_USER:-fquiz} -d ${POSTGRES_DB:-fquiz}",
|
|
|
|
|
]
|
|
|
|
|
interval: 10s
|
|
|
|
|
timeout: 5s
|
|
|
|
|
retries: 8
|
|
|
|
|
start_period: 10s
|
|
|
|
|
restart: unless-stopped
|
|
|
|
|
|
2026-04-11 23:28:23 +08:00
|
|
|
api:
|
|
|
|
|
build:
|
|
|
|
|
context: ./api
|
|
|
|
|
dockerfile: Dockerfile
|
2026-04-12 00:03:30 +08:00
|
|
|
args:
|
|
|
|
|
PYTHON_BASE_IMAGE: ${PYTHON_BASE_IMAGE:-docker.m.daocloud.io/library/python:3.11-slim}
|
2026-04-12 16:00:20 +08:00
|
|
|
PIP_INDEX_URL: ${PIP_INDEX_URL:-https://pypi.org/simple}
|
|
|
|
|
PIP_DEFAULT_TIMEOUT: ${PIP_DEFAULT_TIMEOUT:-300}
|
|
|
|
|
PIP_RETRIES: ${PIP_RETRIES:-20}
|
2026-04-11 23:28:23 +08:00
|
|
|
container_name: fquiz-api
|
2026-04-12 00:03:30 +08:00
|
|
|
depends_on:
|
|
|
|
|
db:
|
|
|
|
|
condition: service_healthy
|
2026-04-11 23:28:23 +08:00
|
|
|
environment:
|
|
|
|
|
API_HOST: ${API_HOST:-0.0.0.0}
|
|
|
|
|
API_PORT: ${API_PORT:-8000}
|
|
|
|
|
API_CORS_ORIGINS: ${API_CORS_ORIGINS:-http://localhost:3000,http://127.0.0.1:3000}
|
2026-04-12 00:03:30 +08:00
|
|
|
DATABASE_URL: ${DATABASE_URL:-postgresql+psycopg://fquiz:fquiz@db:5432/fquiz}
|
|
|
|
|
JWT_SECRET_KEY: ${JWT_SECRET_KEY:-change-this-in-production}
|
|
|
|
|
ACCESS_TOKEN_EXPIRE_MINUTES: ${ACCESS_TOKEN_EXPIRE_MINUTES:-15}
|
|
|
|
|
REFRESH_TOKEN_EXPIRE_DAYS: ${REFRESH_TOKEN_EXPIRE_DAYS:-30}
|
|
|
|
|
REFRESH_COOKIE_SECURE: ${REFRESH_COOKIE_SECURE:-false}
|
|
|
|
|
REFRESH_COOKIE_SAMESITE: ${REFRESH_COOKIE_SAMESITE:-lax}
|
|
|
|
|
INITIAL_ADMIN_EMAIL: ${INITIAL_ADMIN_EMAIL:-admin@example.com}
|
|
|
|
|
INITIAL_ADMIN_USERNAME: ${INITIAL_ADMIN_USERNAME:-admin}
|
|
|
|
|
INITIAL_ADMIN_PASSWORD: ${INITIAL_ADMIN_PASSWORD:-change-me-strong-password}
|
2026-04-11 23:28:23 +08:00
|
|
|
ports:
|
|
|
|
|
- "${API_PORT:-8000}:8000"
|
|
|
|
|
healthcheck:
|
|
|
|
|
test:
|
|
|
|
|
[
|
|
|
|
|
"CMD",
|
|
|
|
|
"python",
|
|
|
|
|
"-c",
|
|
|
|
|
"import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=2).read()",
|
|
|
|
|
]
|
|
|
|
|
interval: 10s
|
|
|
|
|
timeout: 3s
|
|
|
|
|
retries: 5
|
|
|
|
|
start_period: 10s
|
|
|
|
|
restart: unless-stopped
|
|
|
|
|
|
|
|
|
|
web:
|
|
|
|
|
build:
|
|
|
|
|
context: ./web
|
|
|
|
|
dockerfile: Dockerfile
|
|
|
|
|
args:
|
2026-04-12 00:03:30 +08:00
|
|
|
NODE_BASE_IMAGE: ${NODE_BASE_IMAGE:-docker.m.daocloud.io/library/node:22-alpine}
|
2026-04-11 23:28:23 +08:00
|
|
|
NEXT_PUBLIC_API_BASE_URL: ${NEXT_PUBLIC_API_BASE_URL:-http://localhost:8000}
|
|
|
|
|
container_name: fquiz-web
|
|
|
|
|
depends_on:
|
|
|
|
|
api:
|
|
|
|
|
condition: service_healthy
|
|
|
|
|
environment:
|
|
|
|
|
NEXT_PUBLIC_API_BASE_URL: ${NEXT_PUBLIC_API_BASE_URL:-http://localhost:8000}
|
|
|
|
|
NODE_ENV: production
|
|
|
|
|
ports:
|
|
|
|
|
- "3000:3000"
|
|
|
|
|
restart: unless-stopped
|
2026-04-12 00:03:30 +08:00
|
|
|
|
|
|
|
|
volumes:
|
|
|
|
|
fquiz_db_data:
|