fix(content): harden Docker practice guide

This commit is contained in:
yeasy
2026-06-16 21:23:21 -07:00
parent f4e684afeb
commit 9fdffa9d91
67 changed files with 343 additions and 278 deletions
+9 -21
View File
@@ -2,7 +2,7 @@
**BuildKit** 是下一代的镜像构建组件 [moby/buildkit](https://github.com/moby/buildkit) 开源。
> **重要** Docker 23 BuildKit 已成为 **默认稳定构建器**无需手动启用Docker Engine 29 进一步将 Containerd 镜像存储设为默认提升与 Kubernetes 的互操作性
> **重要** Docker 23 BuildKit 已成为 **默认稳定构建器**无需手动启用Docker Engine 29 在新安装场景中进一步将 containerd image store 设为默认提升多平台镜像SBOM/Provenance OCI 元数据能力
目前Docker Hub 自动构建已经支持 BuildKit具体请参考 [docker-practice/docker-hub-buildx](https://github.com/docker-practice/docker-hub-buildx)。
@@ -46,7 +46,7 @@ COPY --from=builder /app/dist /app/dist
```
使用多阶段构建构建的镜像中只包含了目标文件夹 `dist`但仍然存在一些问题 `package.json` 文件变动时`RUN npm i && rm -rf ~/.npm` 这一层会重新执行变更多次后生成了大量的中间层镜像
为解决这个问题进一步的我们可以设想一个类似 **数据卷** 的功能在镜像构建时把 `node_modules` 文件夹挂载上去在构建完成后这个 `node_modules` 文件夹会自动卸载实际的镜像中并不包含 `node_modules` 这个文件夹这样我们就省去了每次获取依赖的时间大大增加了镜像构建效率同时也避免了生成了大量的中间层镜像
为解决这个问题可以把包管理器的下载缓存挂载到构建步骤中例如 npm `/root/.npm`注意`type=cache` 只能作为性能优化不能成为构建正确性的前提缓存目录可能被并发构建改写也可能被 GC 清理所以不要把 `node_modules`编译产物等必须存在的内容只放在 cache mount
`BuildKit` 提供了 `RUN --mount=type=cache` 指令可以实现上边的设想
@@ -59,35 +59,23 @@ WORKDIR /app
COPY package.json /app/
RUN --mount=type=cache,target=/app/node_modules,id=my_app_npm_module,sharing=locked \
--mount=type=cache,target=/root/.npm,id=npm_cache \
npm i --registry=https://registry.npmmirror.com
RUN --mount=type=cache,target=/root/.npm,id=npm_cache \
npm install --registry=https://registry.npmmirror.com
COPY src /app/src
RUN --mount=type=cache,target=/app/node_modules,id=my_app_npm_module,sharing=locked \
## --mount=type=cache,target=/app/dist,id=my_app_dist,sharing=locked \
npm run build
RUN npm run build
FROM nginx:alpine
## COPY --from=builder /app/dist /app/dist
## 为了更直观的说明 from 和 source 指令,这里使用 RUN 指令
RUN --mount=type=cache,target=/tmp/dist,from=builder,source=/app/dist \
# --mount=type=cache,target=/tmp/dist,from=my_app_dist,sharing=locked \
mkdir -p /app/dist && cp -r /tmp/dist/* /app/dist
COPY --from=builder /app/dist /app/dist
```
第一个 `RUN` 指令执行后`id` `my_app_npm_module` 的缓存文件夹挂载到了 `/app/node_modules` 文件夹中多次执行也不会产生多个中间层镜像
第一个 `RUN` 指令执行后`id` `npm_cache` 的缓存文件夹挂载到了 `/root/.npm`后续构建可复用下载缓存
第二个 `RUN` 指令执行时需要用到 `node_modules` 文件夹`node_modules` 已经挂载命令也可以正确执行
第二个 `RUN` 指令执行时`node_modules` 已经作为上一层真实写入到 builder 阶段的文件系统中构建不依赖缓存目录内容
第三个 `RUN` 指令将上一阶段产生的文件复制到指定位置`from` 指明缓存的来源这里 `builder` 表示缓存来源于构建的第一阶段`source` 指明缓存来源的文件夹
最后使用 `COPY --from=builder` 将上一阶段产生的文件复制到最终镜像跨阶段复制构建产物应使用 `COPY --from`如果只是临时读取上一阶段文件可使用 `RUN --mount=type=bind,from=builder,source=/app/dist,target=/tmp/dist,ro`
上面的 `Dockerfile` `--mount=type=cache,...` 中指令作用如下