Table of Contents
多层多克建材是什么?.
多级多克构建是多克17.05引入的功能,它允许您在一个单一多克文件内使用多个]语句. 每个指令开始一个新的阶段,可以有自己的基础图像,依赖性和命令. Artiffacts可以被从一个阶段有选择地复制到另一个阶段,而最终图像只能保留运行应用程序的严格必要内容. 这种方法消除了手动链多克文件或依赖复杂构建脚本的需要,并且通过排除编译器,开发库,和中间文件来大幅缩小图像大小.
核心理念是将构建环境与运行时环境区分开来. 在典型的单阶段构建中,开发者将所有构建工具(如编译器,软件包管理器,测试框架)安装在用于制作的相同图像中,这样可以将图像膨胀,增加攻击表面. 多阶段构建通过使用厚厚,特性丰富的图像进行编译,然后只将所产生的文物复制到最小运行时图像中,如或].
多层次建筑的好处
采用多阶段建设的好处不仅仅是简单缩小规模,而且对安全、可维持性和部署速度具有深远影响。
1. 缩小图像大小
通过丢弃构建时的依赖性,多阶段构建往往会将图像缩水50%到90%。例如,使用完整图像(超过300MB)构建的节点Js应用程序,只能将已建的文件夹复制到基 , 就可以将它缩水到20MB以下。 这种存储节省直接转化为更快的拉动时间,减少网络带宽,降低注册成本。
2. 改善安全
容器图像中每个安装的软件包或工具都有可能存在弱点。多级构建允许您从最终图像中排除编译器、调试器和开发库,从而显著降低攻击表面。您甚至可以使用像 或 这样的图像来运行时阶段,这些图像只包含执行应用程序二进制的最小值 。
3. 简化的建设进程
所有构建步骤都在一个Dockerfile中定义,使过程自成一体,易于版本. CI/CD 管道从一个单一的入口:Dockerfile中受益. 不需要单独保存构建脚本或人工清理步骤.
4. 提高可复制性和一致性
由于整个构建在一个Dockerfile中被捕获,任何开发者或系统都可以复制完全相同的层. 使用特定版本标记来建立基础图像进一步保证了在环境中的一致性.
构建一个多层多文件:一步步
此操作包括创建一个用于节点/ js 和 React 应用程序的“ 已准备好的多阶段” Dockerfile。 任何编译语言都适用同样的原则 。
1. 规划阶段
在写入代码之前, 绘制您需要的阶段。 典型的多阶段构建至少有两个阶段 :
- 构建器阶段[] – 安装所有构建工具,安装依赖性,并运行构建命令.
- 运行时阶段[] –使用最小的基部图像,只复制从建设者阶段中建造出来的文物,并定义运行时的行为.
对于复杂的项目,您可能加入测试、静态分析或资产压缩的中间阶段。
2. 写入构建器阶段
以包含所需工具链的基图像开始。 使用 [[ FLT: 0] ] 命名的级 [[ [FLT: 1] , 以后再引用它们。 对于节点. js :
FROM node:14-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
要点:
- 使用,用于确定性,更快的依赖性安装.
- 尽可能将命令作为单独的层保存 以杠杆缓存。
- 仅在此阶段安装构建工具( 如 TypeScript, Webpack) 。
3. 增加中级试验阶段(备选)
要强制执行代码质量, 请添加一个运行测试的阶段。 这个阶段可以重用构建器图像或安装额外的工具。 因为这不是最终阶段, 测试失败将不会出现在最终图像中 。
FROM builder AS test
RUN npm run test
您可以在您的 CI 管道中运行这个阶段, 使用 [ [FLT: 14]]] 来及早捕获失败, 而无需构建整个最终图像 。
4. 确定运行时间阶段
对于 React 应用程序,运行时图像可以是 Nginx 服务器。对于后端 API , 它可能是无向底像, 也可能是带有 Node.js 运行时的最小高山。 只复制使用 [[FLT: 1: 15] 的必需文物 。
FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
如果您需要节点.js运行时间,请避免从构建器复制[];而是在运行时间阶段重新安装生产依赖:
FROM node:14-alpine AS runtime
WORKDIR /app
COPY --from=builder /app/dist ./dist
RUN npm ci --only=production
EXPOSE 3000
CMD ["node", "dist/server.js"]
5. 图像的构建和测试
使用标准命令构建最终图像 :
docker build -t myapp:latest .
为了验证大小,运行,并与单台建筑进行比较。运行容器并确认应用程序正确响应:
docker run -d -p 8080:80 myapp:latest
curl http://localhost:8080
多步骤建设的最佳做法
- 使用特定的基图像标记 – 避免]] 来防止出奇. prefer 或 ]].
- 将层缓冲 – 复制 ]和]] 源代码其余部分之前的层,使得 层只有在依赖关系发生变化时才失效.
- Leverage build Kit – 启用 BuildKit 与 ] 用于更快的建设,内置缓存,以及更好的平行主义.
- 为不同的环境创造多个最终阶段——例如,一个具有调试工具的开发阶段和一个带有硬化底像的制作阶段.
- 使用] 用于开发 建设[ – 在开发中,你可以停在阶段,以获得实时重载和源地图,然后用重建用于生产.
- 保存图像中的秘密 – 如果您在构建过程中需要通过证书,请使用 Docker BuildKit 的旗号; 永远不要将它们包括在最终图像中.
常见模式和使用案例
编译语言( Go, Rust, C++)
对于静态二进制,运行时阶段可以使用 (空基图像) 。 只有二进制和也许一个配置文件被复制。 Go 示例 :
FROM golang:1.20-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o myapp .
FROM scratch
COPY --from=builder /app/myapp /myapp
ENTRYPOINT ["/myapp"]
Python 应用程序
使用一个带有的构建器阶段来安装依赖性并编译任何C扩展,然后只复制已安装的软件包到运行时间阶段:
FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user -r requirements.txt
COPY . .
FROM python:3.11-slim
COPY --from=builder /root/.local /root/.local
COPY --from=builder /app /app
ENV PATH=/root/.local/bin:$PATH
CMD ["python", "app.py"]
API 服务器的前端
将前端和后端都建在一个 Docker 文件中。 使用单独的构建器阶段, 然后将两个文物复制到单个运行时图像 :
FROM node:14-alpine AS frontend-builder
WORKDIR /app
COPY frontend/package*.json ./
RUN npm ci
COPY frontend/ .
RUN npm run build
FROM node:14-alpine AS api-builder
WORKDIR /app
COPY api/package*.json ./
RUN npm ci
COPY api/ .
RUN npm run build
FROM node:14-alpine
WORKDIR /app
COPY --from=frontend-builder /app/build ./public
COPY --from=api-builder /app/dist ./dist
RUN npm ci --only=production
EXPOSE 3000
CMD ["node", "dist/server.js"]
排除多层次的难题
- Layer caching not work –确保]]]在源代码前命令依赖。使用 来排除不必要的文件。
- 艺术未找到 – 验证 语句中的路径。构建器阶段必须在指定位置输出。使用 调试。
- 保密泄漏 — 永远不复制可能包含 或[]的全部目录。明确复制仅需要的文件。
- 尽管有多个阶段 ,但还是要长长最终图像 — — 请检查您是否在无意中复制 或整个源。 请使用 来查看层大小 。
结论
多阶段多堆积物是现代集装箱化的基石。 它们可以使您传送精致、安全且以一个多堆积物文件记录的图像。 通过区分建构和运行时间之间的关切,您可以大幅缩小图像大小,改善安全性,并精简 CI/CD 管道。 这里显示的技术几乎适用于任何堆积物 — 无论是建Node.js、Go、Python、Java还是前端应用程序。 启动时, 您将把现有的多堆积物文件转换为多阶段的建构物, 您将立即看到建构速度、 部署效率和总体基础设施成本的提高 。