写在前面

在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. 跨域解决之JSONP和CORS的详细介绍

    JSONP跨域和CORS跨域 什么是跨域? 跨域:指的是浏览器不能执行其它网站的脚本,它是由浏览器的同源策略造成的,是浏览器的安全限制! 同源策略 同源策略:域名.协议.端口均相同. 浏览器执行Jav ...

  2. flask 的安装与使用

    一.Flask Flask 是一个轻量级的框架,可以将数据库中的数据呈现到页面上(动态网站). 之前搭建的网站是静态网站(没有连接数据库)页面的数据不会改变.但是现在用的网站都是动态网站. 1.下载F ...

  3. [zebra源码]分片语句ShardPreparedStatement执行过程

    主要过程包括: 分库分表的路由定位 sql语句的 ast 抽象语法树的解析 通过自定义 SQLASTVisitor (MySQLSelectASTVisitor) 遍历sql ast,解析出逻辑表名 ...

  4. Django基础005-Django开发的整体过程

    1.写views views.py代码块 1.在前端以/article/{{ article.id }}这种方式请求后台, 参数配置在urls.py中path('category/<int:id ...

  5. python numpy 数据集合操作函数

    arrarray([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])arr1array([0, 1, 2, 3, 4])np.intersect1d(arr,arr1)#计算数组ARR A ...

  6. maven添加阿里云镜像

    apache的maven服务器国内访问太慢了,用阿里的镜像会好很多. 1.maven的配置文件有两个,安装目录conf文件夹下settings.xml和用户目录.m2文件夹下的settings.xml ...

  7. React 之 组件生命周期

    React 之 组件生命周期 理解1) 组件对象从创建到死亡它会经历特定的生命周期阶段2) React组件对象包含一系列的勾子函数(生命周期回调函数), 在生命周期特定时刻回调3) 我们在定义组件时, ...

  8. Hive——元数据表含义

    Hive--元数据表含义 1.VERSION   -- 查询版本信息   Field Type Comment   VER_ID bigint(20) ID主键   SCHEMA_VERSION va ...

  9. P2476-记忆化搜索

    链接 DP? 我们看看,这个状态似乎有亿点点多. 我们看看数据范围,数量不超过5,颜色数不超过15. 15维DP显然不靠谱. 那么我们就思考一下--个数? 记忆化搜索可ac: #include< ...

  10. SSM框架中,利用ajax,jQuery,json动态刷新局部页面,实现用户名查重提示

    1.在applicationContext.xml配置json文件 2.jsp页面 3.js语句 js语句在script标签中使用, 4.控制层 5.逻辑处理层 6.Dao层方法 7.Mapping层 ...