写在前面

在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 多阶段构建实践的更多相关文章

  1. Dockerfile多阶段构建原理和使用场景

    本文转载自Dockerfile多阶段构建原理和使用场景 导语 Docker 17.05版本以后,新增了Dockerfile多阶段构建.所谓多阶段构建,实际上是允许一个Dockerfile 中出现多个 ...

  2. Dockerfile多阶段构建

    多阶段构建 之前的做法: 在Docker17.05版本之前,构建Docker镜像,通常采用两种方式: 1.全部放入一个Dockerfile 一种方式是将所有的构建过程全都包含在一个Dockerfile ...

  3. Dockerfile构建实践

    Dockerfile构建实践 本文介绍了用于构建有效图像的推荐最佳实践和方法. Docker通过从一个Dockerfile文本文件中读取指令来自动构建映像,该文本文件按顺序包含构建给定映像所需的所有命 ...

  4. 8、Dockerfile介绍和最佳实践

    一.Dockerfile 概念 1.Dockerfile是什么 Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序.库.资源.配置等文件外,还包含了一些为运行时准备的一些配置参数(如 ...

  5. 多阶段构建Docker镜像

    在Docker 17.05及更高的版本中支持支持一种全新的构建镜像模式:多阶段构建: 多阶段构建Docker镜像的最大好处是使构建出来的镜像变得更小: 目前常见的两个构建镜像的方式为: 1.直接使用某 ...

  6. [Docker] 使用 Dockerfile 的多级构建 (multi-stage builds)

      Multi-stage build 即在一个 Dockerfile 中使用多个 FROM 指令.   每个 FROM 指令可以使用不同的基础镜像,并且每一个都开启新的构建阶段.   你可以有选择地 ...

  7. docker 多阶段构建

    构建镜像最具挑战性的一点是使镜像大小尽可能的小.Dockerfile中的每条指令都为图像添加了一个图层,您需要记住在移动到下一层之前清理任何不需要的工件.对于多阶段构建,您可以在Dockerfile中 ...

  8. Docker多阶段构建实战(multi-stage builds)

    在编写Dockerfile构建docker镜像时,常遇到以下问题: RUN命令会让镜像新增layer,导致镜像变大,虽然通过&&连接多个命令能缓解此问题,但如果命令之间用到docker ...

  9. 《Docker从入门到跑路》之多阶段构建

    多阶段构建就是在一个Dokcerfile中定义多个FROM,每个FROM都可以使用不同的基础镜像,并表示开始一个新的构建阶段,我们可以很方便的将一个阶段的文件复制到另外一个阶段中,在最终的阶段保存你需 ...

随机推荐

  1. Hadoop知识总结

    ------------恢复内容开始------------ Hadoop知识点 Hadoop知识点什么是HadoopHadoop和Spark差异Hadoop常见版本,有哪些特点,一般是如何进行选择H ...

  2. C语言:函数

    1. int scanf ( char * format [ ,argument, ... ]);   返回被赋值的参数的个数

  3. C语言:打印所有char字符

    #include <stdio.h> int main() { int aa; char bla; for(aa=0;aa<=255;aa++) { if(aa%10==0 and ...

  4. c语言:scanf()高级应用

    1) 指定读取长度 还记得在 printf() 中可以指定最小输出宽度吗?就是在格式控制符的中间加上一个数字,例如,%10d表示输出的整数至少占用 10 个字符的位置: 如果整数的宽度不足 10,那么 ...

  5. PYTHON 转化函数

    ord(c)#字符转ASCII码值,10进制:自变量只能是一个字符 chr(a)#通过ASCII码值得到对应的字符 bin()函数:将整数(十 等进制)转化为二进制 bool():将指定参数转化为bo ...

  6. Python爬取网易云热歌榜所有音乐及其热评

    获取特定歌曲热评: 首先,我们打开网易云网页版,击排行榜,然后点击左侧云音乐热歌榜,如图: 关于如何抓取指定的歌曲的热评,参考这篇文章,很详细,对小白很友好: 手把手教你用Python爬取网易云40万 ...

  7. 用Python分析下王小波与李银河写情书最爱用哪些词

    作家王小波其实也是我国最早期的程序员,突发奇想,王小波写情书最喜欢用哪些词呢?用Python词云分析下! 直接上代码吧,有注释很好理解.输出的图片设置的比较大,所以运行的比较慢,可以适当把图片尺寸改小 ...

  8. 【Lucas组合数定理】组合-FZU 2020

    组合 FZU-2020 题目描述 给出组合数C(n,m), 表示从n个元素中选出m个元素的方案数.例如C(5,2) = 10, C(4,2) = 6.可是当n,m比较大的时候,C(n,m)很大!于是x ...

  9. Visual Studio2019下载最新离线安装包

    首先可以参考微软官方的离线安装说明-->点击这里打开 =================================================================== 1. ...

  10. C#曲线分析平台的制作(五,Sqldependency+Signalr+windows 服务 学习资料总结)

    在前篇博客中,利用interval()函数,进行ajax轮询初步的实现的对数据的实时显示.但是在工业级别实时显示中,这并非是一种最好的解决方案.随着Html5 websocket的发展,这种全双工的通 ...