什么是Docker构建阶段?
据我所知,Docker中的构建阶段是最基本的,我对它们有实际的理解,但我很难给出正确的定义,而且我似乎也找不到一个 那么:Docker构建阶段的定义是什么 编辑:我不是问“我如何使用构建阶段?”或“我如何使用多构建阶段?”人们似乎非常渴望回答:-) 我之所以提出这个问题,是因为我在书中看到了以下句子:什么是Docker构建阶段?,docker,dockerfile,Docker,Dockerfile,据我所知,Docker中的构建阶段是最基本的,我对它们有实际的理解,但我很难给出正确的定义,而且我似乎也找不到一个 那么:Docker构建阶段的定义是什么 编辑:我不是问“我如何使用构建阶段?”或“我如何使用多构建阶段?”人们似乎非常渴望回答:-) 我之所以提出这个问题,是因为我在书中看到了以下句子: “FROM指令初始化新的生成阶段” “可以为新生成阶段指定名称” 这让我想知道:构建阶段到底是什么?自17版以来,docker现在在docker构建执行期间支持多个阶段 这意味着,您不再需要在
- “FROM指令初始化新的生成阶段”
- “可以为新生成阶段指定名称”
这让我想知道:构建阶段到底是什么?自17版以来,
docker
现在在docker构建执行期间支持多个阶段
这意味着,您不再需要在docker文件中仅定义一个源映像,并在一次运行中完成整个构建,而是可以在Dockerfile
中为每个阶段定义多个具有多个FROM
定义的不同映像的多个阶段:
# Build stage
FROM microsoft/aspnetcore
# ..do a build with a dev image for creating ./app artifact
# Publish - use a hardened, production image
FROM alpine:latest
CMD ["./app"]
这为您提供了一个好处,可以打破您的图像构建过程,针对您在某个阶段中正在执行的任务进行优化,例如,这些阶段可以是:
使用具有额外linting依赖项的图像检查源
使用已安装了所有开发依赖项的开发人员映像来构建源代码
使用包含测试框架的另一个映像在工件上运行各种测试
一旦一切顺利,使用最小尺寸、优化、加固的图像来捕获最终工件以供生产
阅读有关多级生成的更多详细信息
:
我不认为会对Docker构建阶段有一个严格的定义,因为构建阶段通常是理论性的:
- 可以由您定义
- 取决于您的情况(语言/库)
在这个问题上:其中一个答案是
构建意味着编译项目
我想你也可以这样看。构建阶段是任何生成稍后可以采用和使用的内容的过程
docker多阶段构建的理念是:
生成您需要的内容
留下你不需要的东西,以更轻量级的方式使用步骤1中的产品
如果您已经阅读了文档,Alex Ellis有一个很好的例子,其中发生了相同的逻辑:
他从一个golang
图像开始,添加库,构建他的应用程序(Go生成一个二进制可执行文件)
之后,他不需要golang和库来发布/运行它,因此,他选择了一个alpine
图像,添加步骤1中的可执行文件,并发布了一个小得多的图像
舞台
名词
过程或发展中的点、时期或步骤
举一个实际的例子:您希望构建一个映像,其中包含一个生产就绪的web服务器,该服务器使用编译为Javascript的Typescript文件。您希望在Docker容器中构建该类型脚本以简化依赖关系管理。因此,您需要:
- node.js
- 打字稿
- 编译所需的任何依赖项
- 网页包之类的
- nginx/Apache/随便什么
在最终的图像中,您实际上只需要编译的.js文件和nginx。但要达到目的,你首先需要所有其他的东西。当您上传最终图像时,它将包含所有中间层,即使它们对于最终产品是不必要的
Docker build Stage现在允许您将这些阶段或步骤实际分离到单独的图像中,同时仍然只使用一个Docker文件,而不需要将多个Docker文件与外部shell脚本或诸如此类的脚本粘合在一起。例如:
FROM node as builder
RUN npm install ...
# whatever you need to build your files
FROM nginx as production
COPY --from=builder /final.js /var/www/html
此Dockerfile的最终结果是一个以nginx
为基础的小图像,外加最终的.js文件。它不包含所有不必要的东西,比如node.js和npm依赖项
builder
这里是第一个阶段,生产
是第二个阶段。在这种情况下,第一个阶段将在流程结束时被丢弃,但您也可以选择使用docker build--target=builder
构建特定阶段。来自
的新的引入了一个新的独立阶段。它们本质上是独立的DockerFile,但它们可以使用COPY--from
共享数据。构建阶段从from语句开始,在下一from语句之前的步骤结束。在多阶段构建中,您将经历创建多个映像的过程,但是通常只标记单个映像(多个构建除外,使用buildx等工具构建多体系结构映像清单,以及docker在回答此问题后发布的任何其他内容)
每个阶段都从Dockerfile中的from
行开始,构建一个独特的图像。一个阶段不继承以前阶段中完成的任何操作,它基于自己的基础映像。因此,如果您有以下情况:
FROM alpine as stage1
RUN apk add your_tool
FROM alpine as stage2
RUN your_tool some args
您将收到一个错误,因为您的_工具未在第二阶段安装
您从构建中得到哪个阶段的输出?默认情况下,最后一个阶段,但您可以使用docker image build--target stage1来更改该阶段。
以使用本例中的名称stage1
来构建该阶段。经典docker构建将从Dockerfile的顶部运行,直到完成目标阶段。Buildkit构建一个依赖关系图并同时构建阶段,并且仅在需要时才构建,因此不要依赖于此顺序来控制yo中的测试工作流之类的东西
FROM maven as build
COPY src /app/src
WORKDIR /app/src
RUN mvn install
FROM openjdk:jre as release
COPY --from=build /app/src/target/app.jar /app
CMD java -jar /app/app.jar
FROM upstream as mybuilder
RUN apk add common_tools
FROM mybuilder as stage2
RUN some_tool arg2
FROM mybuilder as stage3
RUN some_tool arg3
FROM minimal_base as release
COPY --from=stage2 /bin2 /
COPY --from=stage3 /bin3 /
FROM alpine
COPY --from=docker:stable /usr/local/bin/docker /usr/local/bin/