自动化构建
是应用发布过程当中必不可少的环节, 经常使用的构建工具备jenkins
,walle
等。而这些工具在构建应用时一般会有如下问题:php
- 须要直接或间接的写一坨用于构建的shell命令等,不易管理、兼容性较差
- 上面一点可能还比较容易解决,但最为致命的是:重度依赖如
jenkins
宿主机或打包机上的软件环境,如git
,maven
,java
等
理想状况是: 不一样的应用如java应用、go应用、php应用等等,均可以在某台负责构建的宿主机上并行无干扰的执行构建操做,且构建中依赖的软件环境、构建流程等均可以由开发人员控制。 html
到目前为止,能很好的完成以上使命的,可能非docker莫属了!java
在docker的世界里,构建交付的是镜像
,而可以产生镜像的是Dockerfile
(手动使用docker commit
的另当别论). git
在docker ce 17.05
以后,出现了一个很重要的特性Multi-Stage Build
(多阶段构建) , 它将显著提高你的运维生产力!github
下文将用实战案例来详细解读
Multi-Stage Build
这一特性
如下演示以java
hello world 为例,完整代码在: https://github.com/zhouzhipeng/docker-multi-stage-demoweb
这是一个标准的maven 项目,仅有个HelloWorld主类。大致构建思路为:docker
Dockerfile.build 用于编译和打包jarshell
FROM maven:3.5.2-alpine MAINTAINER zhouzhipeng <admin@zhouzhipeng.com> WORKDIR /app COPY . . # 编译打包 RUN mvn package -Dmaven.test.skip=true
Dockerfile.old 用于运行jar中的主类bash
FROM openjdk:8-jre-alpine MAINTAINER zhouzhipeng <admin@zhouzhipeng.com> WORKDIR /app COPY docker-multi-stage-demo-1.0-SNAPSHOT.jar . # 运行main类 CMD java -cp docker-multi-stage-demo-1.0-SNAPSHOT.jar com.zhouzhipeng.HelloWorld
注意到,两个dockerfile之间关联的 docker-multi-stage-demo-1.0-SNAPSHOT.jar 文件,须要另一个build.sh 脚原本串起来.app
build.sh
#!/usr/bin/env bash # 1. 先构建出带有产物jar的镜像 docker build -t zhouzhipeng/dockermultistagedemo-build -f Dockerfile.build . # 2. 临时建立 dockermultistagedemo-build 容器 docker create --name build zhouzhipeng/dockermultistagedemo-build # 3. 将上面容器中的jar拷贝出来 docker cp build:/app/target/docker-multi-stage-demo-1.0-SNAPSHOT.jar ./ # 4. 构建java执行的镜像 docker build -t zhouzhipeng/dockermultistagedemo -f Dockerfile.old . # 5. 删除临时jar文件 rm -rf docker-multi-stage-demo-1.0-SNAPSHOT.jar
对Dockerfile和shell也了解的朋友相信应该都看得懂,在此不作过多赘述.
看过上一节后,你也许会感受是否是有点麻烦呢? 是的,麻烦之处在于不只要写多个dockerfile,并且还须要一个build.sh 脚原本额外执行。 无疑是增大了构建应用的复杂度!
将上面的Dockerfile.build 和Dockerfile.old 结合起来,稍加修饰,获得以下全新的Dockerfile:
FROM maven:3.5.2-alpine as builder MAINTAINER zhouzhipeng <admin@zhouzhipeng.com> WORKDIR /app COPY src . COPY pom.xml . # 编译打包 (jar包生成路径:/app/target) RUN mvn package -Dmaven.test.skip=true FROM openjdk:8-jre-alpine MAINTAINER zhouzhipeng <admin@zhouzhipeng.com> WORKDIR /app COPY --from=builder /app/target/docker-multi-stage-demo-1.0-SNAPSHOT.jar . # 运行main类 CMD java -cp docker-multi-stage-demo-1.0-SNAPSHOT.jar com.zhouzhipeng.HelloWorld
而后,仍然是熟悉的docker build命令
docker build -t zhouzhipeng/dockermultistagedemo-new .
便可。
细心的你应该不难发现,上面的Dockerfile 中有两处地方不同,
FROM
语句COPY
命令后多了--from=builder
这就是今天的主咖 Multi-Stage Build
, 先来经过一张图来直观感觉下什么是所谓的Multi-Stage Build
(多阶段构建 ):
经过多阶段构建,既能够保持Dockerfile简洁易读,又可让最终的产物镜像很“干净”。
仍是以上文中的Dockerfile为例, 以下图所示:
红框中的部分能够看做是一个个独立的“stage” ,能够粗略想象成就是一个独立的Dockerfile内容。
你们知道镜像构建是一层一层叠加的,按照Dockerfile的命令行顺序,由上至下依次执行叠加。 因此,下层的stage才能够引用到上层的stage,为了方便引用到上层的stage,故须要给其取一个名字, 用as
操做符。
FROM
命令的完整格式以下:
FROM <image>[:<tag>] [AS <name>]
stage之间交互的是文件,故COPY
命令须要扩展,经过--from=<name>
来指定须要从上方的哪一个"stage" 拷贝文件, 其完整命令格式以下:
COPY --from=<name|index> <src>... <dest> # 注意--from 是可选的,当上层的stage没有名字时能够按照index(从0开始)的顺序引用,eg. --from=0
值得一提的是,默认状况下使用docker build
命令构建一个包含多个stage的dockerfile时,最终的产物是最下方的一个stage 所产生的镜像。
固然,若是出于调试缘由或其余需求,docker也是支持构建到指定的stage的,使用 --target builder
就能够只构建builder镜像。
docker build -t zhouzhipeng/builder --target builder .
到目前为止,咱们已经有了一个可以一键构建的Dockerfile 文件,接下来就只差让它可以自动构建了!
你能够用你熟悉的jenkins
结合github的webhook来实现提交一次代码,就执行一次docker build命令。
固然,我推荐我的体验的话就用官方的docker hub 吧,由于这样你构建的镜像还能够与他人共享。
具体的用Docker hub 的 automated build 功能就不详细说明了, 下面用一张gif图快速演示下,感兴趣的朋友能够自行去探索下。
Multi-Stage Build
这一特性很是适合作构建管道流,对于那些依赖环境复杂、流程也复杂的应用来讲最合适不过了。
能够clone下上面的源码试下哦: https://github.com/zhouzhipeng/docker-multi-stage-demo
by zhouzhipeng from https://blog.zhouzhipeng.com/...
本文可全文转载,但须要保留原做者和出处。
https://docs.docker.com/v17.09/engine/userguide/eng-image/multistage-build/