使用多阶段构建

预计阅读时间: 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. Uva 10635 - Prince and Princess LCS/LIS

    两个长度分别为p+1和q+1的由1到n2之前的整数组成的序列,每个序列的元素各不相等,两个序列第一个元素均为1.求两个序列的最长公共子序列 https://uva.onlinejudge.org/in ...

  2. os模块 sys模块 json/pickle 模块 logging模块

    目录 模块 1. os模块 2. sys模块 3. json和pickle模块 4. logging模块 (1)日志配置 (2)实际开发中日志的使用 模块 1. os模块 os模块有什么用 与操作系统 ...

  3. eclipse中export 的jar file与 runnable jar file的区别

    (1)直接运行 .class的方法     java  -cp .  com.guangfa.demo1  , 不用加.class后缀 .-cp 是 -classpath 缩写,是指定类运行所依赖其他 ...

  4. 【leetcode】410. Split Array Largest Sum

    题目如下: Given an array which consists of non-negative integers and an integer m, you can split the arr ...

  5. 使用AnnotationConfigApplicationContext注册配置类

    1. AnnotationConfigApplicationContext功能 该类可以实现基于Java的配置类加载自定义在Spring的应用上下文的bean. 1.1 使用方式一:在构造方法中完成注 ...

  6. 最大流 && 最小费用最大流模板

    模板从  这里   搬运,链接博客还有很多网络流题集题解参考. 最大流模板 ( 可处理重边 ) ; const int INF = 0x3f3f3f3f; struct Edge { int from ...

  7. [UVA160]Factors and Factorials 题解

    前言 这道题目本身毫无技术含量珂言,但是输出格式珂以调一年 题解 这道题让我们求\(N!\)中每个质数的个数. 一种方法是直接模拟,枚举\(N!\)中的每个元素,然后暴力查看每个数含有有多少质数. 但 ...

  8. Nginx 作为代理服务与负载均衡

    代理服务 代理一代为办理(代理理财.代理收货等等) 代理区别 区别在于代理的对象不一样 正向代理代理的对象是客户端 反向代理代理的对象是服务端 反向代理配置 server { listen 80; s ...

  9. CF 480 B Long Jumps (map标记)

    题目链接:http://codeforces.com/contest/480/problem/B 题目描述:     Long Jumps   Valery is a PE teacher at a ...

  10. Spring Cloud架构教程 (五)服务网关(过滤器)

    过滤器的作用 通过上面所述的两篇我们,我们已经能够实现请求的路由功能,所以我们的微服务应用提供的接口就可以通过统一的API网关入口被客户端访问到了.但是,每个客户端用户请求微服务应用提供的接口时,它们 ...