Files
writer-work-flow/docker-compose.prod.yml
Yaojia Wang 5464539a91 fix(devops): 修复容器化部署面缺口,docker compose 可干净构建
消除 DEPLOYMENT.md §1.5 列出的 6 个「照抄即部署」缺口(仅动部署面文件,不改应用源码):

1. apps/api/Dockerfile 补 `COPY alembic.ini ./`,容器内可直接 alembic upgrade head。
2. base compose api 注入 CREDENTIAL_ENC_KEY(${VAR:-dev 占位},自动读根 .env 覆盖)+
   APP_ENV/LOG_JSON/CORS_ORIGINS,无 .env 也能起,不再因缺 Fernet key 启动失败。
3. base compose web 设 API_BASE_INTERNAL=http://api:8000,RSC 直连 api 容器。
4. web Dockerfile 加 ARG/ENV NEXT_PUBLIC_API_BASE(默认 localhost:8000),compose
   web.build.args 传入,构建期可注入公网 API 基址。
5. api/web Dockerfile 内置 HEALTHCHECK(api 用 urllib 打 /health、web 用 node 打 /)。
6. 新增 docker-compose.prod.yml 覆盖层做生产加固:pg 强口令 ${POSTGRES_PASSWORD}、
   pg 仅绑 127.0.0.1、APP_ENV=prod、LOG_JSON=true、密钥/连接串/CORS/公网 API 全从
   env 且必填(:? 缺失拒起)、restart: unless-stopped。base 保持 dev 便利不破坏。

附带修复:web Dockerfile 在 install 前补 COPY pnpm-workspace.yaml,使容器内 install
看到 minimumReleaseAgeExclude/onlyBuiltDependencies,避免误拒 @xyflow 等近期发布依赖;
新增 .dockerignore(根 + apps/web)排除宿主 node_modules/.next/.venv 等,避免平台原生
二进制经 COPY . . 覆盖容器版导致 next build 失败,并加速构建上下文、保证可复现。

验证:docker compose config(base)与 prod 合并 config 均通过;docker compose build
两镜像均成功(api 378MB / web 296MB);自定义 NEXT_PUBLIC_API_BASE 已确认内联进前端
bundle。DEPLOYMENT.md §1.5 回写为「已修复」并补 §2.6 生产 env 清单与正确部署命令。
2026-07-07 05:01:44 +02:00

41 lines
2.1 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 生产加固覆盖层 —— 与 base 叠加使用base 保持 dev 便利,本文件收紧安全):
# docker compose -f docker-compose.yml -f docker-compose.prod.yml build
# docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
#
# 需在宿主机 .envchmod 600勿入库或环境变量提供以下必填项缺失即拒绝 up / config 报错):
# POSTGRES_PASSWORD —— pg 强随机口令(替换 base 的弱口令 writer/writer
# CREDENTIAL_ENC_KEY —— Fernet key生产新生成勿用 .env.example 占位值)
# CORS_ORIGINS —— 前端真实来源,逗号分隔,禁通配 *
# NEXT_PUBLIC_API_BASE—— 浏览器可达的公网 API 基址(构建期内联进 web bundle
services:
pg:
environment:
POSTGRES_USER: writer
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD 必填(生产强口令,勿用 base 弱口令)}
POSTGRES_DB: writer
# 不对公网暴露:仅绑本机回环(供宿主机跑迁移)。彻底隔离可整段删掉只走 compose 内网。
ports:
- "127.0.0.1:5432:5432"
restart: unless-stopped
api:
environment:
DATABASE_URL: postgresql+asyncpg://writer:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD 必填}@pg:5432/writer
DATABASE_URL_SYNC: postgresql+psycopg://writer:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD 必填}@pg:5432/writer
APP_ENV: prod
LOG_JSON: "true"
CREDENTIAL_ENC_KEY: ${CREDENTIAL_ENC_KEY:?CREDENTIAL_ENC_KEY 必填(生产 Fernet key勿用占位值}
CORS_ORIGINS: ${CORS_ORIGINS:?CORS_ORIGINS 必填(前端真实来源,逗号分隔,禁通配)}
restart: unless-stopped
web:
build:
context: ./apps/web
args:
# 构建期内联:生产须指向浏览器可达的公网 API通常反代后的 https 域名)。
NEXT_PUBLIC_API_BASE: ${NEXT_PUBLIC_API_BASE:?NEXT_PUBLIC_API_BASE 必填(浏览器可达的公网 API 基址)}
environment:
NEXT_PUBLIC_API_BASE: ${NEXT_PUBLIC_API_BASE:?NEXT_PUBLIC_API_BASE 必填}
API_BASE_INTERNAL: http://api:8000
restart: unless-stopped