Dockerfile 多阶段构建实践

写在前面
在Docker Engine 17.05 中引入了多阶段构建,以此降低构建复杂度,同时使缩小镜像尺寸更为简单。这篇小作文我们来学习一下如何编写实现多阶段构建的Dockerfile
关于dockerfile基础编写可参考之前docker容器dockerfile详解
一 、不使用多阶段构建
我们知道在Dockerfile中每新增一个指令都会在镜像中生产新的层,一个高效的Dockerfile应该在继续下一层之前清除之前所有不需要的资源。
不使用多阶段构建时,我们通常会创建两dockerfile文件,一个用于开发及编译应用,另一个用于构建精简的生产镜像。这样能比较大限度的减小生产镜像的大小。
我们以一个go应用来看看。我首先会创建一个dockerfile,构建这个镜像的主要目的就是编译我们的应用。
FROM golang:1.16
WORKDIR /go/src
COPY app.go ./
#go编译
RUN go build -o myapp app.go
构建镜像
[root@localhost dockerfiles]# docker build -t builder_app:v1 .
Sending build context to Docker daemon 3.072kB
Step 1/4 : FROM golang:1.16
---> 019c7b2e3cb8
Step 2/4 : WORKDIR /go/src
---> Using cache
---> 15362720e897
Step 3/4 : COPY app.go ./
---> Using cache
---> 8f14ac97a68a
Step 4/4 : RUN go build -o myapp app.go
---> Running in 4368cc4617a7
Removing intermediate container 4368cc4617a7
---> 631f67587803
Successfully built 631f67587803
Successfully tagged builder_app:v1
这样在这个镜像中就包含了我们编译后的应用myapp,现在我们可以创建容器将myapp拷贝到宿主机等待后续使用。
# docker create --name builder builder_app:v1
fafc1cf7ffa42e06d19430b807d24eafe0bf731fc45ff0ecf31ada5a6075f1d5
# docker cp builder:/go/src/myapp ./
我们有了应用,下一步就是构建生产镜像
FROM scratch
WORKDIR /server
COPY myapp ./
CMD ["./myapp"]
由于此时我们不需要其他依赖环境,所以我们采用scratch这个空镜像,不仅可以减小容器尺寸,还可以提高安全性。
构建镜像
#docker build --no-cache -t server_app:v1 .
我们看一次构建的两个镜像大小
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
server_app v1 6ebc0833cad0 6 minutes ago 1.94MB
builder_app v1 801f0b615004 23 minutes ago 921MB
显然在不使用多阶段构建时,我们也可以构建出生产镜像,但是我们需要维护两个dockerfile,需要将app遗留到本地,并且带来了更多存储空间开销。在使用多阶段构建时能比较好的解决以上问题。
二、使用多阶段构建
在一个Dockerfile中使用多个FROM指令,每个FROM都可以使用不同的基镜像,并且每条指令都将开始新阶段构建。在多阶段构建中,我们可以将资源从一个阶段复制到另一个阶段,在最终镜像中只保留我们所需要的内容。
我们将上面实例的两个Dockerfile合并为如下:
#阶段1
FROM golang:1.16
WORKDIR /go/src
COPY app.go ./
RUN go build app.go -o myapp
#阶段2
FROM scratch
WORKDIR /server
COPY --from=0 /go/src/myapp ./
CMD ["./myapp"]
构建镜像
# docker build --no-cache -t server_app:v2 .
查看构建好的镜像
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
server_app v2 20225cb1ea6b 12 seconds ago 1.94MB
这样我们无需创建额外镜像,以更简单的方式构建出了同样微小的目标镜像。可以看到在多阶段构建dockerfile中最关键的是COPY --from=0 /go/src/myapp ./ 通过 --from=0指定我们资源来源,这里的0即是指第一阶段。
命令构建阶段
默认情况下构建阶段没有名称,我们可以通过整数0~N来引用,即第一个from从0开始。其实我们还可以在FROM指令中添加AS <NAME> 来命名构建阶段,接着在COPY指令中通过<NAME>引用。我们对上面dockerfile修改如下:
#阶段1命名为builder
FROM golang:1.16 as builder
WORKDIR /go/src
COPY app.go ./
RUN go build app.go -o myapp
#阶段2
FROM scratch
WORKDIR /server
#通过名称引用
COPY --from=builder /go/src/myapp ./
CMD ["./myapp"]
只构建某个阶段
构建镜像时,您不一定需要构建整个 Dockerfile,我们可以通过--target参数指定某个目标阶段构建,比如我们开发阶段我们只构建builder阶段进行测试。
#docker build --target builder -t builder_app:v2 .
使用外部镜像
使用多阶段构建时,我们局限于从之前在 Dockerfile 中创建的阶段进行复制。还可以使用COPY --from指令从单独的镜像复制,如本地镜像名称、本地或 Dockerhub上可用的标签或标签 ID。Docker 客户端在必要时会拉取需要的镜像到本地。
COPY --from httpd:latest /usr/local/apache2/conf/httpd.conf ./httpd.conf
从上一阶段创建新的阶段
我们可以通过FROM指令来引用上一阶段作为新阶段的开始
#阶段1命名为builder
FROM golang:1.16 as builder
WORKDIR /go/src
COPY app.go ./
RUN go build app.go -o myapp
#阶段2
FROM builder as builder_ex
ADD dest.tar ./
...
通过上面我们对dockerfile多阶段构建有了一个整体的了解。
NEXT
- Dockerfile 与Docker容器安全实践
希望小作文对你有些许帮助,如果内容有误请指正。
您可以随意转载、修改、发布本文章,无需经过本人同意。 个人blog:iqsing.github.io
Dockerfile 多阶段构建实践的更多相关文章
- Dockerfile多阶段构建原理和使用场景
本文转载自Dockerfile多阶段构建原理和使用场景 导语 Docker 17.05版本以后,新增了Dockerfile多阶段构建.所谓多阶段构建,实际上是允许一个Dockerfile 中出现多个 ...
- Dockerfile多阶段构建
多阶段构建 之前的做法: 在Docker17.05版本之前,构建Docker镜像,通常采用两种方式: 1.全部放入一个Dockerfile 一种方式是将所有的构建过程全都包含在一个Dockerfile ...
- Dockerfile构建实践
Dockerfile构建实践 本文介绍了用于构建有效图像的推荐最佳实践和方法. Docker通过从一个Dockerfile文本文件中读取指令来自动构建映像,该文本文件按顺序包含构建给定映像所需的所有命 ...
- 8、Dockerfile介绍和最佳实践
一.Dockerfile 概念 1.Dockerfile是什么 Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序.库.资源.配置等文件外,还包含了一些为运行时准备的一些配置参数(如 ...
- 多阶段构建Docker镜像
在Docker 17.05及更高的版本中支持支持一种全新的构建镜像模式:多阶段构建: 多阶段构建Docker镜像的最大好处是使构建出来的镜像变得更小: 目前常见的两个构建镜像的方式为: 1.直接使用某 ...
- [Docker] 使用 Dockerfile 的多级构建 (multi-stage builds)
Multi-stage build 即在一个 Dockerfile 中使用多个 FROM 指令. 每个 FROM 指令可以使用不同的基础镜像,并且每一个都开启新的构建阶段. 你可以有选择地 ...
- docker 多阶段构建
构建镜像最具挑战性的一点是使镜像大小尽可能的小.Dockerfile中的每条指令都为图像添加了一个图层,您需要记住在移动到下一层之前清理任何不需要的工件.对于多阶段构建,您可以在Dockerfile中 ...
- Docker多阶段构建实战(multi-stage builds)
在编写Dockerfile构建docker镜像时,常遇到以下问题: RUN命令会让镜像新增layer,导致镜像变大,虽然通过&&连接多个命令能缓解此问题,但如果命令之间用到docker ...
- 《Docker从入门到跑路》之多阶段构建
多阶段构建就是在一个Dokcerfile中定义多个FROM,每个FROM都可以使用不同的基础镜像,并表示开始一个新的构建阶段,我们可以很方便的将一个阶段的文件复制到另外一个阶段中,在最终的阶段保存你需 ...
随机推荐
- create-react-app 入门学习
全局安装 create-react-app npm install create-react-app -g 创建项目 在全局安装了create-react-app 后 创建项目,如果按照下面的第一种办 ...
- ARTS第十一周
受辞职考研和新冠肺炎疫情影响,一直没更.遗憾,数学和专业课再高点就有戏了.继续. 1.Algorithm:每周至少做一个 leetcode 的算法题2.Review:阅读并点评至少一篇英文技术文章3. ...
- Linux磁盘配额与LVM
一.LVM概述 逻辑卷管理 Logical Volume Manager二.LVM机制的基本概念三.LVM的管理命令 ① 主要命令 ② ==LVM逻辑卷操作流程== ③ 举例四.磁盘配额概述 ...
- Linux磁盘管理与文件系统
文章目录一.硬盘结构二.MBR与磁盘分区表示三.磁盘分区结构四.文件系统类型●1.XFS文件系统●2.SWAP,交换文件系统●3.Linux支持的其他文件系统类型五.命令部分--检测并确认新硬盘●1. ...
- 从 Vue 中 parseHTML 方法来看前端 html 词法分析
先前我们在 从 Vue parseHTML 所用正则来学习常用正则语法 这篇文章中分析了 parseHTML 方法用到的正则表达式,在这个基础上我们可以继续分析 parseHTML 方法. 先来看该方 ...
- C语言:最大公约数和最小公倍数
#include <stdio.h> int main() { int a,b,c,m,t; printf("请输入两个数:\n"); scanf("%d%d ...
- C语言:清空缓冲区
缓冲区的优点很明显,它加快了程序的运行速度,减少了硬件的读写次数,让整个计算机变得流畅起来:但是,缓冲区也带来了一些负面影响,经过前面几节的学习相信读者也见识到了.那么,该如何消除这些负面影响呢?思路 ...
- PAT乙级:1070 结绳 (25分)
PAT乙级:1070 结绳 (25分) 题干 给定一段一段的绳子,你需要把它们串成一条绳.每次串连的时候,是把两段绳子对折,再如下图所示套接在一起.这样得到的绳子又被当成是另一段绳子,可以再次对折去跟 ...
- Delimiter must not be alphanumeric or backslash php报错原因
昨天写了一个小程序,其中用到了正则表达式去匹配内容. php源代码如下: preg_match("\b(\w+)\b\s+\1\b",$match): 此报错警告的中文意思是 ...
- C++五十一篇 -- VS2017开发人员新闻无法联网
参考链接:https://blog.csdn.net/zz1589275782/article/details/88364983 这几天玩了下以前的电脑,本来想更新一下Visual Studio In ...