ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

devops-exercises 容器实战:多阶段构建(Multi-Stage Builds)改造指南与镜像瘦身原理

devops-exercises 容器实战:多阶段构建(Multi-Stage Builds)改造指南与镜像瘦身原理 文档教程DevOps运维【免费下载链接】devops-exercisesLinux, Jenkins, AWS, SRE, Prometheus, Docker, Python, Ansible, Git, Kubernetes, Terraform, OpenStack, SQL, NoSQL, Azure, GCP, DNS, Elastic, Network, Virtualization. DevOps Interview Questions项目地址https://gitcode.com/GitHub_Trending/de/devops-exercises点击查看免费下载本指南以 topics/containers/solutions/multi_stage_builds.md 为核心完整还原将单阶段 Dockerfile 改造为多阶段构建的经典练习与官方解答并结合仓库内容器专题资料深入剖析多阶段构建的工作原理、层layer机制与收益。读完本文你将能够独立把构建工具 运行产物混杂在一起的 Dockerfile 拆分为构建阶段与运行阶段产出体积更小、更安全的容器镜像。一、练习目标与背景本节练习的 Objective 只有一句话Learn about multi-stage builds学习多阶段构建。它属于 topics/containers/README.md 中Exercises → Misc练习列表的一部分Multi-Stage Builds条目题目要求明确不实际构建镜像、不运行任何容器仅凭下面的 Dockerfile将其转换为使用多阶段构建的形式。不构建、不运行意味着这是一道纸面推演题考察的是你对 Dockerfile 指令语义、镜像分层模型以及多阶段构建COPY --from语法的理解而不是命令行操作能力。二、原题还原单阶段 Dockerfile 的问题所在练习给出的原始 Dockerfile 如下仓库原文保留原样FROM nginx RUN apt-get update \ apt-get install -y curl python build-essential \ apt-get install -y nodejs \ apt-get clean -y RUN mkdir -p /my_app ADD ./config/nginx/docker.conf /etc/nginx/nginx.conf ADD ./config/nginx/k8s.conf /etc/nginx/nginx.conf.k8s ADD app/ /my_cool_app WORKDIR /my_cool_app RUN npm install -g ember-cli RUN npm install -g bower RUN apt-get update apt-get install -y git \ npm install \ bower install \ RUN ember build — environmentprod CMD [ “/root/nginx-app.sh”, “nginx”, “-g”, “daemon off;” ]在动手改造之前先拆解这个 Dockerfile 暴露出的核心问题基础镜像职责混乱FROM nginx本意是提供一个 Web 服务器运行环境但紧接着就在同一个镜像里安装了python、build-essential、nodejs、git等构建期工具。这些工具对最终运行 nginx 静态页面毫无作用只会让镜像体积成倍膨胀。构建工具链被永久打包进运行时镜像npm install -g ember-cli、npm install -g bower、npm install、bower install、ember build这一整套前端构建链路只需要在产出 dist 静态文件的那一刻存在。把它们留在最终镜像里既是体积浪费也扩大了攻击面镜像里多一个包管理器就多一份被利用的风险。层数过多、难以维护每次RUN、ADD都会生成一个新的镜像层可参考 topics/containers/solutions/image_layers.md 中FROM、RUN → 新层EXPOSE、ENV、WORKDIR → 元数据的结论。该 Dockerfile 有十余条指令其中大半都与最终运行无关。原文存在笔误不可直接构建ember build — environmentprod中的—是全角破折号应为--environmentprodCMD [ “...”, ... ]使用了全角引号应替换为 ASCII 引号。这也是题目要求不实际构建的原因之一——直接拿原文去docker image build会失败。从仓库的 topics/containers/README.md 对多阶段构建的解释可以确认这一点Multi-stages builds allow you to produce smaller container images by splitting the build process into multiple stages. ... the whole build process of the application might be using packages and libraries you dont really need for running the application later. Moreover, the build process might produce different artifacts which not all are needed for running the application.三、标准解法把构建阶段与运行阶段彻底分离练习给出的参考解答仓库原文如下FROM node:6 RUN mkdir -p /my_cool_app RUN npm install -g ember-cli RUN npm install -g bower WORKDIR /my_cool_app RUN npm install ADD app/ /my_cool_app RUN bower install RUN ember build — environmentprod FROM nginx RUN mkdir -p /my_cool_app ADD ./config/nginx/docker.conf /etc/nginx/nginx.conf ADD ./config/nginx/k8s.conf /etc/nginx/nginx.conf.k8s # Copy build artifacts from the first stage COPY — from0 /my_cool_app/dist /my_cool_app/dist WORKDIR /my_cool_app CMD [ “/root/nginx-app.sh”, “nginx”, “-g”, “daemon off;” ]改造后的 Dockerfile 由两个阶段组成中间以第二个FROM nginx为分界阶段基础镜像职责最终产物阶段 0构建阶段node:6安装 ember-cli / bower拉取应用源码执行npm install、bower install、ember build/my_cool_app/dist静态构建产物阶段 1运行阶段nginx放置 nginx 配置接收阶段 0 的构建产物作为 Web 服务器运行最终交付的镜像核心衔接语句是COPY --from0 /my_cool_app/dist /my_cool_app/dist它把第一个阶段索引 0构建出的dist目录复制进第二个阶段。从第二个FROM开始前一个阶段中的所有工具node、npm、bower、ember-cli、build-essential、git 等都被丢弃最终镜像里只保留 nginx 运行环境 配置文件 静态产物。这里同样需要注意原文笔误COPY — from0 ...与ember build — environmentprod中的—应写为--引号应使用 ASCII 引号。可直接运行的正确版本如下# Stage 0: build stage FROM node:6 RUN mkdir -p /my_cool_app RUN npm install -g ember-cli RUN npm install -g bower WORKDIR /my_cool_app ADD app/ /my_cool_app RUN npm install RUN bower install RUN ember build --environmentprod # Stage 1: runtime stage FROM nginx RUN mkdir -p /my_cool_app ADD ./config/nginx/docker.conf /etc/nginx/nginx.conf ADD ./config/nginx/k8s.conf /etc/nginx/nginx.conf.k8s # Copy build artifacts from the first stage COPY --from0 /my_cool_app/dist /my_cool_app/dist WORKDIR /my_cool_app CMD [/root/nginx-app.sh, nginx, -g, daemon off;]四、核心语法深入COPY --from 与阶段引用多阶段构建的关键在于跨阶段复制产物COPY --from是唯一的衔接手段。仓库解答采用COPY --from0即以阶段索引引用第一个阶段。除索引外Dockerfile 还支持两种更可读的引用方式按索引引用COPY --from0 ...阶段按出现顺序从 0 编号简单但可读性差——一旦前面插入新阶段编号全部错位。按名称引用在阶段前加AS别名例如FROM node:6 AS builder随后COPY --frombuilder /my_cool_app/dist /my_cool_app/dist。这在生产 Dockerfile 中更常见便于维护者快速理解产物来源。可推断的进阶用法还包括--target定向构建docker image build --target builder -t myapp:build .只构建到指定阶段为止可用于只出构建产物而不出运行时镜像的 CI 流水线仅构建阶段多阶段文件在docker image build时默认只产出最后一个阶段但--target可以让中间阶段也可单独被构建与调试。五、为什么多阶段构建能瘦身镜像分层机制要理解收益需要先回顾镜像层模型。topics/containers/README.md 对此有系统描述容器镜像是一个只读层read-only layers的集合每个层由一条或多条 Dockerfile 指令产生每个层有基于其内容的哈希 ID每个层只是相对于前一层的差异集a set of differences from the layer before it层与层叠加在一起创建容器时会在底层镜像之上新增一个可写的容器层container layer所有运行时写入都落在这个薄层上容器删除后该层随之消失底层镜像保持不变多个容器可以共享同一个底层镜像各自拥有独立的可写层与数据状态。把这一模型套到单阶段 Dockerfile 上apt-get install留下的包管理器缓存、node/npm/bower/ember-cli 二进制、git 等全部固化成永久层无论运行阶段是否需要都会被docker pull传输、被docker image ls占用的磁盘空间记录下来。多阶段构建的瘦身逻辑正是分层模型 阶段裁剪的组合拳构建阶段的每一条指令仍然产生层但只存在于构建过程的临时镜像中进入第二个FROM后构建阶段的一切层都被丢弃只保留COPY --from显式复制出来的文件最终镜像只有运行阶段nginx 基础层 配置层 复制产物层的少量层。仓库解答对此的总结非常精炼Multi-stages builds allow you to produce smaller container images by splitting the build process into multiple stages as we did above. The app image doesnt contain anything related to the build process except the actual app.也就是说最终的应用镜像里除了应用本身dist 静态产物不再包含任何与构建过程相关的东西。六、多阶段构建 vs 手动清理为什么前者是更优解针对构建期工具残留问题有人会想到在单阶段里追加清理指令例如安装完再apt-get purge、npm cache clean --force。仓库 README 明确指出了这条路的两个缺陷你必须精确知道该删什么You need to know what to remove exactly and that might be not as straightforward as you think——依赖的传递依赖、缓存目录、临时文件散布在各处很难删干净清理动作本身又会产生新的层You add new layers which are not really needed——清理指令照样写入镜像等于为瘦身额外支付了层数成本。因此更优的做法是一个阶段负责构建build process把相关产物/输出传递给运行应用的阶段one stage is passing the relevant artifacts/outputs to the stage that runs the application。这与仓库在 topics/containers/README.md 中True or False? In multi-stage builds, artifacts can be copied between stages → True. This allows us to eventually produce smaller images.的判断完全一致阶段间复制产物最终得到更小的镜像。七、验证与对比如何证明镜像确实变小了练习虽然要求不构建、不运行但改造完成后你可以用仓库其他练习中提到的手段做可验证的对比实验参考 topics/containers/solutions/image_layers.md 的验证思路# 1. 分别构建单阶段版本与多阶段版本注意用修正后的语法 docker image build -f Dockerfile.single -t myapp:single . docker image build -f Dockerfile.multi -t myapp:multi . # 2. 对比镜像体积多阶段版本应显著更小 docker image ls | grep myapp # 3. 查看每个阶段/指令产生的层及其大小 docker image history myapp:multi # 4. 用 inspect 核对镜像层数量RootFS.Layers docker image inspect myapp:multi对应 Podman 引擎的命令为podman image build、podman image history、podman image inspect仓库 topics/containers/README.md 中多处提到 Docker 与 Podman 命令可互换使用。一个经验性判断标准来自仓库是docker image history中通常创建新层的指令具有非零大小不过不能单独依赖这一点例如某些RUN ls -l结果大小可能为 0需要结合inspect的 RootFS 层数交叉验证。八、落地实操与配套最佳实践把多阶段构建用到真实的容器化应用流程中可以结合仓库另一练习 topics/devops/solutions/containerize_app.md 给出的完整链路git clone一个待容器化的开源项目编写 Dockerfile可用任意基础镜像docker image build -t web_app:latest .构建docker image ls验证镜像存在可选docker login后docker image tag/docker image push推送到 registrydocker container run -d -p 80:3000 web_app:latest运行docker container ls、docker logs 容器ID/名称验证应用在线。将多阶段改造嵌入该流程时建议一并遵循仓库 README 中列出的 Containerfile/Dockerfile 最佳实践FROM 指定 tag不写 tag 意味着永远拉取latest可能随时间变化产生意外结果只包含将要使用的包Keep images small!仅包含应用运行所需内容用合并 RUN 指令减少层数见 image_layers.md 中把多条dd合并为一条RUN ... ...的做法安装后清理缓存如apt-get clean使用.dockerignore默认情况下构建上下文会包含目录下所有文件.dockerignore用于排除无关文件避免把源码、密钥等带入镜像不把敏感信息写入环境变量。九、总结回到练习的两个问题可以这样作答如何改造将 Dockerfile 拆为两个阶段——FROM node:6的构建阶段负责安装构建工具、执行依赖安装与ember build产出/my_cool_app/distFROM nginx的运行阶段只负责放置 nginx 配置并通过COPY --from0 /my_cool_app/dist /my_cool_app/dist接收构建产物最后以CMD启动 nginx。注意原文中的—与全角引号需修正为--与 ASCII 引号才可实际构建。收益是什么多阶段构建通过拆分构建流程让最终镜像只包含应用运行所需内容不携带任何构建期工具链从而显著减小镜像体积、降低层数、缩小攻击面相比安装后再手动清理的方案它不需要精确枚举待删除文件也不会为清理动作额外增加层。这正是 topics/containers/README.md 中artifacts can be copied between stages → smaller images结论的实践落点。如需继续练习可回到 multi_stage_builds.md 原题 独立作答再用本解答对照也可以继续完成 topics/containers/ 下working_with_images.md、image_layers.md、containerized_web_server.md等系列练习从镜像操作、分层模型到完整应用容器化系统掌握容器构建全链路。赞分享文档教程DevOps运维【免费下载链接】devops-exercisesLinux, Jenkins, AWS, SRE, Prometheus, Docker, Python, Ansible, Git, Kubernetes, Terraform, OpenStack, SQL, NoSQL, Azure, GCP, DNS, Elastic, Network, Virtualization. DevOps Interview Questions项目地址https://gitcode.com/GitHub_Trending/de/devops-exercises点击查看免费下载相关推荐Node.js Docker 多阶段构建Multi-stage Builds实战指南从构建环境到精简运行镜像Node.js Docker 多阶段构建Multi stage Builds实战指南从构建环境到精简运行镜像 导读 本文围绕 nodebestpracti文档教程后端SSDB 容器镜像优化多阶段构建与瘦身SSDB 容器镜像优化多阶段构建与瘦身 你是否还在为SSDB容器镜像体积过大而烦恼构建时间长、部署慢、存储成本高本文将通过多阶段构建与镜像瘦身技术教你如数据库KV存储数据存储sshmuxd性能优化指南处理大规模并发连接的秘诀sshmuxd性能优化指南处理大规模并发连接的秘诀 sshmuxd作为一款轻量级SSH代理前端工具在处理大规模并发连接时需要进行合理优化才能发挥最佳性能。本上一篇如何在5分钟内创建专业图表免费在线流程图编辑器的完整指南下一篇OpenProject 手把手教程快速跑起来项目管理创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表