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 清单与正确部署命令。
This commit is contained in:
@@ -4,6 +4,12 @@ WORKDIR /app
|
||||
COPY pyproject.toml uv.lock* ./
|
||||
COPY packages ./packages
|
||||
COPY apps/api ./apps/api
|
||||
# alembic.ini 在仓库根,随 build context 拷入镜像,供容器内 `alembic upgrade head`(迁移目录
|
||||
# packages/db/migrations 已随 `COPY packages` 进镜像;缺 alembic.ini 迁移会找不到配置而失败)。
|
||||
COPY alembic.ini ./
|
||||
RUN uv sync --no-dev --frozen || uv sync --no-dev
|
||||
EXPOSE 8000
|
||||
# 存活探测:镜像无 curl,用 stdlib urllib 打 /health(非 200/连接失败会抛异常,退出非零)。
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
|
||||
CMD ["python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health').read()"]
|
||||
CMD ["uv", "run", "uvicorn", "ww_api.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||
|
||||
13
apps/web/.dockerignore
Normal file
13
apps/web/.dockerignore
Normal file
@@ -0,0 +1,13 @@
|
||||
# web 镜像构建上下文(context=./apps/web)。排除宿主产物,避免 `COPY . .` 把宿主
|
||||
# node_modules(含平台原生 next-swc/esbuild 二进制)覆盖容器内 `pnpm install` 的 Linux 版,
|
||||
# 导致 `pnpm build` 加载原生绑定失败。同时排除构建产物/日志加速上下文传输、保证可复现。
|
||||
node_modules
|
||||
.next
|
||||
.turbo
|
||||
npm-debug.log*
|
||||
pnpm-debug.log*
|
||||
.env
|
||||
.env.local
|
||||
.DS_Store
|
||||
coverage
|
||||
*.tsbuildinfo
|
||||
@@ -1,9 +1,16 @@
|
||||
FROM node:22-slim AS build
|
||||
RUN corepack enable
|
||||
WORKDIR /app
|
||||
COPY package.json pnpm-lock.yaml* ./
|
||||
# pnpm-workspace.yaml 必须在 install 前就位:它携带 minimumReleaseAgeExclude(豁免新发布包的
|
||||
# 供应链策略)、onlyBuiltDependencies/allowBuilds(构建脚本白名单)。缺它则容器内 install 看不到
|
||||
# 这些策略,会误拒近期发布的依赖(如 @xyflow/*)而失败——与宿主行为不一致。
|
||||
COPY package.json pnpm-lock.yaml* pnpm-workspace.yaml ./
|
||||
RUN pnpm install --frozen-lockfile || pnpm install
|
||||
COPY . .
|
||||
# NEXT_PUBLIC_* 在 Next 构建期内联进浏览器 bundle——必须在 `pnpm build` 前用 build ARG 注入。
|
||||
# 默认 http://localhost:8000 供 dev;生产经 compose build args 传公网 API 基址。
|
||||
ARG NEXT_PUBLIC_API_BASE=http://localhost:8000
|
||||
ENV NEXT_PUBLIC_API_BASE=$NEXT_PUBLIC_API_BASE
|
||||
RUN pnpm build
|
||||
|
||||
FROM node:22-slim AS run
|
||||
@@ -12,4 +19,7 @@ COPY --from=build /app/.next/standalone ./
|
||||
COPY --from=build /app/.next/static ./.next/static
|
||||
COPY --from=build /app/public ./public
|
||||
EXPOSE 3000
|
||||
# 存活探测:node 打首页(run 阶段无 curl);5xx/连接失败退出非零。
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
|
||||
CMD ["node", "-e", "require('http').get('http://127.0.0.1:3000/',r=>process.exit(r.statusCode<500?0:1)).on('error',()=>process.exit(1))"]
|
||||
CMD ["node", "server.js"]
|
||||
|
||||
Reference in New Issue
Block a user