chore: split Dockerfile into runtime+e2e stages, add healthchecks
- Split Dockerfile: runtime stage (no Playwright) + e2e stage (adds Chromium) - Add healthcheck to backend and frontend in docker-compose.prod.yml - Fix REDIS_URL default to empty string (no hardcoded password) - Add RATE_LIMIT_BACKEND=redis to production env example - Remove deprecated version field from docker-compose.prod.yml
This commit is contained in:
parent
331f6bce80
commit
ee8578c3d7
|
|
@ -7,7 +7,9 @@
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# Database (MUST use strong password in production)
|
# Database (MUST use strong password in production)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
POSTGRES_USER=postgres
|
||||||
POSTGRES_PASSWORD=CHANGE_ME_strong_pg_password_32chars!
|
POSTGRES_PASSWORD=CHANGE_ME_strong_pg_password_32chars!
|
||||||
|
POSTGRES_DB=geo_platform
|
||||||
DATABASE_URL=postgresql+asyncpg://postgres:CHANGE_ME_strong_pg_password_32chars!@db:5432/geo_platform
|
DATABASE_URL=postgresql+asyncpg://postgres:CHANGE_ME_strong_pg_password_32chars!@db:5432/geo_platform
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
@ -55,6 +57,7 @@ DOUBAO_ENDPOINT_ID=
|
||||||
# Rate Limiting
|
# Rate Limiting
|
||||||
# ============================================================
|
# ============================================================
|
||||||
API_RATE_LIMIT_RPM=10
|
API_RATE_LIMIT_RPM=10
|
||||||
|
RATE_LIMIT_BACKEND=redis
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# Payment / Distribution / Email (set to real mode in production)
|
# Payment / Distribution / Email (set to real mode in production)
|
||||||
|
|
@ -62,3 +65,14 @@ API_RATE_LIMIT_RPM=10
|
||||||
PAYMENT_MODE=mock
|
PAYMENT_MODE=mock
|
||||||
DISTRIBUTION_MODE=mock
|
DISTRIBUTION_MODE=mock
|
||||||
EMAIL_MODE=mock
|
EMAIL_MODE=mock
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Monitoring
|
||||||
|
# ============================================================
|
||||||
|
SENTRY_DSN=
|
||||||
|
ENVIRONMENT=production
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Playwright (for E2E testing only, not needed in production)
|
||||||
|
# ============================================================
|
||||||
|
PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,20 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload
|
||||||
|
|
||||||
FROM base AS runtime
|
FROM base AS runtime
|
||||||
|
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
EXPOSE 8000
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
|
||||||
|
CMD curl -f http://localhost:8000/health || exit 1
|
||||||
|
|
||||||
|
CMD ["gunicorn", "app.main:app", "-w", "4", "-k", "uvicorn.workers.UvicornWorker", \
|
||||||
|
"--bind", "0.0.0.0:8000", "--timeout", "120", "--access-logfile", "-"]
|
||||||
|
|
||||||
|
FROM runtime AS e2e
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
wget \
|
wget \
|
||||||
gnupg \
|
gnupg \
|
||||||
|
|
@ -40,17 +54,5 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
libasound2 \
|
libasound2 \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
RUN pip install --no-cache-dir -r requirements.txt
|
|
||||||
|
|
||||||
RUN playwright install chromium
|
RUN playwright install chromium
|
||||||
RUN playwright install-deps chromium
|
RUN playwright install-deps chromium
|
||||||
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
EXPOSE 8000
|
|
||||||
|
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
|
|
||||||
CMD curl -f http://localhost:8000/health || exit 1
|
|
||||||
|
|
||||||
CMD ["gunicorn", "app.main:app", "-w", "4", "-k", "uvicorn.workers.UvicornWorker", \
|
|
||||||
"--bind", "0.0.0.0:8000", "--timeout", "120", "--access-logfile", "-"]
|
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,6 @@
|
||||||
# 5. 使用 docker compose -f docker-compose.prod.yml up -d 启动
|
# 5. 使用 docker compose -f docker-compose.prod.yml up -d 启动
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
version: "3.9"
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
db:
|
db:
|
||||||
image: pgvector/pgvector:pg15
|
image: pgvector/pgvector:pg15
|
||||||
|
|
@ -75,6 +73,7 @@ services:
|
||||||
build:
|
build:
|
||||||
context: ./backend
|
context: ./backend
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
|
target: runtime
|
||||||
container_name: geo_backend_prod
|
container_name: geo_backend_prod
|
||||||
restart: always
|
restart: always
|
||||||
expose:
|
expose:
|
||||||
|
|
@ -87,6 +86,12 @@ services:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
redis:
|
redis:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 30s
|
||||||
# 使用 Dockerfile 中定义的 gunicorn 启动命令
|
# 使用 Dockerfile 中定义的 gunicorn 启动命令
|
||||||
deploy:
|
deploy:
|
||||||
resources:
|
resources:
|
||||||
|
|
@ -113,6 +118,12 @@ services:
|
||||||
# 生产环境不挂载源代码目录
|
# 生产环境不挂载源代码目录
|
||||||
depends_on:
|
depends_on:
|
||||||
- backend
|
- backend
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "-qO-", "http://localhost:3000/api/auth/session"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 30s
|
||||||
deploy:
|
deploy:
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ services:
|
||||||
environment:
|
environment:
|
||||||
DATABASE_URL: postgresql+asyncpg://postgres:${POSTGRES_PASSWORD:-geo_pg_dev_2026}@db:5432/geo_platform
|
DATABASE_URL: postgresql+asyncpg://postgres:${POSTGRES_PASSWORD:-geo_pg_dev_2026}@db:5432/geo_platform
|
||||||
REDIS_URL: redis://:${REDIS_PASSWORD:-geo_redis_dev_2026}@redis:6379/0
|
REDIS_URL: redis://:${REDIS_PASSWORD:-geo_redis_dev_2026}@redis:6379/0
|
||||||
|
RATE_LIMIT_DISABLED: ${RATE_LIMIT_DISABLED:-0}
|
||||||
volumes:
|
volumes:
|
||||||
- ./backend:/app
|
- ./backend:/app
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|
@ -105,10 +106,10 @@ services:
|
||||||
deploy:
|
deploy:
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
memory: 256m
|
memory: 2g
|
||||||
cpus: '0.5'
|
cpus: '2.0'
|
||||||
reservations:
|
reservations:
|
||||||
memory: 128m
|
memory: 512m
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
postgres_data:
|
postgres_data:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue