> 把配置抽成 include 片段,会弄坏每一条 CI 没在测的组装路径
安全响应头被从 nginx.conf 里抽出来,变成 nginx/snippets/security-headers.conf, 主配置里用 6 条 include /etc/nginx/snippets/security-headers.conf; 引它。
结论先行¶
安全响应头被从 nginx.conf 里抽出来,变成 nginx/snippets/security-headers.conf,
主配置里用 6 条 include /etc/nginx/snippets/security-headers.conf; 引它。
这个仓库有三条把 nginx 配置装进容器的路径,重构只更新了其中一条:
| 组装路径 | 有没有带上 snippets/ |
结果 |
|---|---|---|
Dockerfile(单容器镜像) |
有:COPY nginx/snippets/ /etc/nginx/snippets/ |
能起 |
docker-compose.yml |
没有——只挂了 nginx.conf 和 docs/ 两个路径 |
容器起来立刻退出 |
.github/workflows/docker-publish.yml(内联 Dockerfile) |
没有 | 发布的镜像起不来 |
nginx 在加载配置时解析 include,目标文件缺失是致命错误。
所以 make docker-up 拉起一个立刻退出的容器;
而发布出去的那个 web 镜像是 docker-compose.prod.yml 拉的,
docker-compose.prod.yml 又是 deploy.sh 跑的——对外宣传的一行部署路径发布了一个起不来的容器。
CI 一直是绿的,因为它只 smoke test 了两个 Dockerfile* 镜像,从来没测 docker-compose.yml。
为什么¶
include 重构的危险在于它把一个文件内的依赖变成了文件间的依赖,
而"把文件送进容器"这件事在每条组装路径里是各自独立实现的:
COPY 一次、volumes: 一次、workflow 里内联的 Dockerfile 再一次。
抽取片段时你只会看着主配置文件,看不见这三处。
两条可推广的判断:
- 组装路径的数量 = 这次重构的风险面。 同一个 artifact 有几种装配方式(Dockerfile / compose / workflow 内联 / 手工部署脚本), 就有几处要同步,而其中被 CI 覆盖的往往只有一处。
- "CI 绿"的覆盖面要按路径数去读,不是按 job 数。 这里 CI 覆盖 1/3 条路径,而被覆盖的恰好是不出问题的那条。
这和同一类的另一个 nginx 坑同源:一个 location 块里只要出现任意一条
add_header,就会丢弃 server 块继承来的全部头——
两者都是"配置的组合规则和你脑子里的继承模型不一样"。
怎么用¶
- 抽 include 片段之前,先
grep出所有组装路径。grep -rln 'nginx.conf\|COPY nginx\|volumes:' . --include='*.yml' --include='Dockerfile*'每一处都要么带上新目录,要么确认它不需要。 - 给每条部署路径一个 smoke test,哪怕只是"起来之后还活着"。
docker compose up -d && sleep 3 && docker compose ps能发现这整类问题。 没被 smoke test 的那条路径,就是会在用户那里第一次运行的那条。 - 逐路径验证响应头,不要只验
/。/、一个静态路径、一个用户上传路径分别curl -I一次——它们经常不一样。 - 宣传在 README 里的部署命令,必须有一次真实执行过的记录,否则它就是文档,不是路径。
出处¶
~/Engineering/Mandelbrot-Renderer/PROJECT_ENGINEERING_GUIDE.md§0.2 / §0.3- 2026-10-11 核对现状:
nginx/nginx.conf中 6 条 include、nginx/snippets/security-headers.conf存在、docker-compose.yml的volumes:仅两条且不含 snippets、Dockerfile:54有COPY nginx/snippets/、docker-publish.yml中 grep 不到 snippets - 同一类配置组合陷阱:检查渲染产物,不是源码——Django 的 {# #} 只支持单行