使用多阶段构建

预计阅读时间: 6分钟

多阶段构建是守护程序和客户端上需要Docker 17.05或更高版本的新功能。多阶段构建对于那些努力优化Dockerfiles同时使其易于阅读和维护的人来说非常有用。

FROM RICH 七哥

在多阶段构建之前

构建镜像最具挑战性的一点是保持镜像尺寸不变。Dockerfile中的每条指令都为镜像添加了一个图层,您需要记住在移动到下一层之前清除任何不需要的工件。为了编写一个真正高效的Dockerfile,传统上需要使用shell技巧和其他逻辑来保持层尽可能小,并确保每个层都具有前一层所需的工件,而不是其他任何东西。

实际上很常见的是有一个Dockerfile用于开发(其中包含构建应用程序所需的所有内容),以及一个用于生产的精简版Dockerfile,它只包含您的应用程序以及运行它所需的内容。这被称为“建造者模式”。维护两个Dockerfiles并不理想。

这里有一个例子Dockerfile.buildDockerfile它遵守上面建造者模式:

Dockerfile.build

FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
COPY app.go .
RUN go get -d -v golang.org/x/net/html \
&& CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

  

请注意,此示例还RUN使用Bash &&运算符人为地压缩两个命令,以避免在镜像中创建其他图层。这很容易出错并且难以维护。例如,插入另一个命令并忘记使用该\字符继续行是很容易的。

Dockerfile

FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY app .
CMD ["./app"]

  

build.sh

#!/bin/sh
echo Building alexellis2/href-counter:build docker build --build-arg https_proxy=$https_proxy --build-arg http_proxy=$http_proxy \
-t alexellis2/href-counter:build . -f Dockerfile.build docker container create --name extract alexellis2/href-counter:build
docker container cp extract:/go/src/github.com/alexellis/href-counter/app ./app
docker container rm -f extract echo Building alexellis2/href-counter:latest docker build --no-cache -t alexellis2/href-counter:latest .
rm ./app

  

当您运行build.sh脚本时,它需要构建第一个镜像,从中创建容器以复制工件,然后构建第二个镜像。这两个镜像占用了您的系统空间,您仍然可以在app 本地磁盘上使用该工件。

多阶段构建极大地简化了这种情况!

使用多阶段构建

对于多阶段构建,您可以FROM在Dockerfile中使用多个语句。每条FROM指令可以使用不同的基础,并且每个指令都开始构建的新阶段。您可以选择性地将工件从一个阶段复制到另一个阶段,从而在最终镜像中留下您不想要的所有内容。为了说明这是如何工作的,让我们调整上一节中的Dockerfile以使用多阶段构建。

Dockerfile

FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]

您只需要单个Dockerfile。您也不需要单独的构建脚本。只要运行docker build

$ docker build -t alexellis2/href-counter:latest .
Rich 七哥https://www.cnblogs.com/fusheng11711/

最终结果是与以前相同的微小生产镜像,复杂性显着降低。您不需要创建任何中间镜像,也不需要将任何工件提取到本地系统。

它是如何工作的?第二FROM条指令以alpine:latest镜像为基础开始一个新的构建阶段。该COPY --from=0行仅将前一阶段的构建工件复制到此新阶段。Go SDK和任何中间工件都被遗忘,而不是保存在最终镜像中。 Rich 七哥https://www.cnblogs.com/fusheng11711/

命名您的构建阶段

默认情况下,阶段未命名,您可以通过整数来引用它们,第一FROM条指令从0开始。但是,您可以通过AS <NAME>FROM指令中添加一个来命名您的阶段。此示例通过命名阶段并使用COPY指令中的名称来改进前一个示例。这意味着即使Dockerfile中的指令稍后重新排序,COPY也不会中断。

FROM golang:1.7.3 AS builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]

  

停在特定的构建阶段

构建映像时,不一定需要构建整个Dockerfile,包括每个阶段。您可以指定目标构建阶段。以下命令假定您使用的是前一个Dockerfile但在名为的阶段停止builder

$ docker build --target builder -t alexellis2/href-counter:latest .

一些可能非常强大的场景是:

  • 调试特定的构建阶段
  • 使用debug启用了所有调试符号或工具的production阶段,以及精益阶段
  • 使用testing您的应用程序填充测试数据的阶段,但使用使用实际数据的不同阶段构建生产

使用外部镜像作为“舞台”

使用多阶段构建时,您不仅可以从先前在Dockerfile中创建的阶段进行复制。您可以使用该COPY --from指令从单独的映像进行复制,使用本地映像名称,本地或Docker注册表中可用的标记或标记ID。如有必要,Docker客户端会提取镜像并从那里复制工件。语法是:

COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf

  

												

Docker中使用多阶段Dockerfile构建容器镜像image(镜像优化)的更多相关文章

  1. Docker自学纪实(五) 使用Dockerfile构建php网站环境镜像

    一般呢,docker构建镜像容器的方式有两种:一种是pull dockerhub仓库里面的镜像,一种是使用Dockerfile自定义构建镜像. 很多时候,公司要求的镜像并不一定符合dockerhub仓 ...

  2. Docker学习(六)Dockerfile构建自定义镜像

    Docker学习(六)Dockerfile构建自定义镜像 前言 通过前面一篇文章可以知道怎么去使用一个镜像搭建服务,但是,如何构造自己的一个镜像呢,docker提供了dockerfile可以让我们自己 ...

  3. docker中怎样设置开机启动--随容器的启动而启动服务?

    docker可以说给我们的部署带来极大的方便和可逢凶化吉性!(懂的同学自然懂) 在初步了解之后,我们就能简单使用docker了. 刚开始玩docker时,可以基于系统级别的镜像做定制,比如基于  ce ...

  4. Docker中的三个基本概念容器(container)、镜像(image)和仓库(registry)之间有什么关系?

    Docker镜像是一个特殊的文件系统,除了提供容器运行时所需的程序.库.资源.配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷.环境变量.用户等).镜像不包含任何动态数据,其内容在构建之 ...

  5. Docker在Centos下使用Dockerfile构建远程Tomcat和Jenkins镜像

    镜像构建准备环境原料 构建CentOS Docker tomcat镜像 Dockerfile文件内容: FROM centos:latest MAINTAINER boonya <boonya@ ...

  6. 修改docker中mysql登入密码(包括容器内和本地远程登入的密码)

    查看docker中正在运行的容器 docker ps 进入MySQL 容器中 sudo docker exec -it cd800a1cd503 /bin/bash 在容器中: /etc/mysql/ ...

  7. Docker学习笔记_使用Dockerfile创建flask的一个镜像

    一.实验环境 1.宿主机OS:Win10 64位 2 .虚拟机OS:Ubuntu18.04 64位    虚拟机名称:Ubuntu18VM1   虚拟机IP:192.168.8.25 3.账号:doc ...

  8. 在docker中快速创建包含ip相关tool的ubuntu镜像

    在docker学习中需要创建轻量级的,包含ip相关工具的容器,支持ping,ip,ethtool,brctrl等相关指令. 下面就是快速创建一个满足需求的ubunut镜像的过程: 1) 在docker ...

  9. Centos上Docker 使用dockerfile构建容器实现ssh

    这几日在学习docker.遇到的问题数一年都数不完,网上大多数都是ubuntu的,百度或者谷歌的时候心好累.写写文档来帮助使用centos的docker爱好者们. docker基本操作这里就不介绍了 ...

随机推荐

  1. 03python面向对象编程之Python中单下划线和双下划线的区别7

    通常Python类中会有_和__的方法,是指什么意思呢?如下: 双下划线表示内部不允许访问,一个下划线表示这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽 ...

  2. 北京师范大学第十五届ACM决赛-重现赛 B Borrow Classroom (树 ——LCA )

    链接:https://ac.nowcoder.com/acm/contest/3/B 来源:牛客网 Borrow Classroom 时间限制:C/C++ 3秒,其他语言6秒 空间限制:C/C++ 2 ...

  3. 针对360浏览器读取不了cookie的问题

    今天学习cookie的时候发现在360和谷歌浏览器下设置cookie打开是空白的!经过一番搜索才知道在本地是访问不了cookie只能在服务器端进行访问,但是仍然可以在火狐下进行访问

  4. zookeeper之一 安装和配置(单机+集群)

    这里我以zookeeper3.4.10.tar.gz来演示安装,安装到/usr/local/soft目录下. 一.单机版配置 1.安装和配置 #.下载 wget http://apache.fayea ...

  5. NOIP2015 D1T1 神奇的幻方

    洛谷P2615 很简单的模拟题……每枚举一个点只要保存上一个点的x,y值即可,不用开数组存放 另外题目中对于K的操作都在K-1的九宫格范围内,所以我们巧妙运用++和--就可以做到每个分支一行代码 还有 ...

  6. Arduino-LiquidCrystal_I2C 液晶库

    I2C转接板上[PCF8574T转接板]VCC接5V,GND接GND,SCL接SCL(即A05),SDA接SDA(即A04) 常用的函数是 lcd.init(),lcd初始化 setCursor(x, ...

  7. Python---面向对象编程---自定义列表和集合操作类

    一.定义一个列表的操作类Listinfo 包括的方法 1.列表元素添加:add_key()  添加的必须是数字或者是字符串 2.列表元素取值:get_key() 3.列表合并:update_list( ...

  8. hbase完全分布式搭建

    1.解压缩hbase的软件包,使用命令: tar -zxvf hbase-1.3.0-bin.tar.gz 2.进入hbase的配置目录,在hbase-env.sh文件里面加入java环境变量.即: ...

  9. ASP:CheckBox获取前台的checked的属性

    后台代码: for (int i = 0; i < this.GvCourses.Rows.Count; i++) { CheckBox chb = this.GvCourses.Rows[i] ...

  10. 【bzoj2064】【分裂】状态压缩表示合并子集

    (上不了p站我要死了,画师当然是wlop大大啦) 感觉这个做法还是挺难想的. 但还是总结一下思路吧.. "只可意会不可言传的状压dp"(乱说) Description 背景: 和久 ...