之前的做法
在 Docker 17.05 版本之前,我们构建 Docker 镜像时,通常会采用两种方式:
全部放入一个 Dockerfile
一种方式是将所有的构建过程编包含在一个 Dockerfile 中,包括项目及其依赖库的编译、
测试、打包等流程,这里可能会带来的一些问题:
1、Dockerfile 特别长,可维护性降低
2、镜像层次多,镜像体积较大,部署时间变长
3、源代码存在泄露的风险
例如
编写 app.go 文件,该程序输出 Hello World!
package main
import "fmt"
func main(){
fmt.Printf("Hello World!");
}
编写 Dockerfile.one 文件
FROM golang:1.9-alpine
RUN apk --no-cache add git ca-certificates
WORKDIR /go/src/github.com/go/helloworld/
COPY app.go .
RUN go get -d -v github.com/go-sql-driver/mysql \
&& CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . \
&& cp /go/src/github.com/go/helloworld/app /root
WORKDIR /root/
CMD ["./app"]
构建镜像
$ docker build -t go/helloworld:1 -f Dockerfile.one . 分散到多个 Dockerfile
另一种方式,就是我们事先在一个 Dockerfile 将项目及其依赖库编译测试打包好后,再将其拷贝到运行环境中,这种方式需要我们编写两个 Dockerfile 和一些编译脚本才能将其两个阶段自动整合起来,这种方式虽然可以很好地规避第一种方式存在的风险,但明显部署过程较复杂。
例如
编写 Dockerfile.build 文件
FROM golang:1.9-alpine
RUN apk --no-cache add git
WORKDIR /go/src/github.com/go/helloworld
COPY app.go .
RUN go get -d -v github.com/go-sql-driver/mysql \
&& CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . 编写 Dockerfile.copy 文件
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY app .
CMD ["./app"]
新建 build.sh
#!/bin/sh
echo Building go/helloworld:build
docker build -t go/helloworld:build . -f Dockerfile.build
docker create --name extract go/helloworld:build
docker cp extract:/go/src/github.com/go/helloworld/app ./app
docker rm -f extract
echo Building go/helloworld:2
docker build --no-cache -t go/helloworld:2 . -f Dockerfile.copy
rm ./app
现在运行脚本即可构建镜像
$ chmod +x build.sh
$ ./build.sh
对比两种方式生成的镜像大小
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
go/helloworld 2 f7cf3465432c 22 seconds ago 6.47MB
go/helloworld 1 f55d3e16affc 2 minutes ago 295MB
使用多阶段构建
为解决以上问题,Docker v17.05 开始支持多阶段构建 ( multistage builds )。使用多阶段构建我们就可以很容易解决前面提到的问题,并且只需要编写一个 Dockerfile :
例如 编写 Dockerfile 文件
FROM golang:1.9-alpine as builder
RUN apk --no-cache add git
WORKDIR /go/src/github.com/go/helloworld/
RUN go get -d -v github.com/go-sql-driver/mysql
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
FROM alpine:latest as prod
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/go/helloworld/app .
CMD ["./app"]
构建镜像
$ docker build -t go/helloworld:3 .
对比三个镜像大小
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
go/helloworld 3 d6911ed9c846 7 seconds ago 6.47MB
go/helloworld 2 f7cf3465432c 22 seconds ago 6.47MB
go/helloworld 1 f55d3e16affc 2 minutes ago 295MB
很明显使用多阶段构建的镜像体积小,同时也完美解决了上边提到的问题。 只构建某一阶段的镜像
我们可以使用 as 来为某一阶段命名,例如
FROM golang:1.9-alpine as builder
例如当我们只想构建 builder 阶段的镜像时,我们可以在使用 docker build 命令时加上 --target 参数即可
$ docker build --target builder -t username/imagename:tag . 构建时从其他镜像复制文件
上面例子中我们使用 COPY --from=0 /go/src/github.com/go/helloworld/app . 从上一阶段的镜像中复制文件,我们也可以复制任意镜像中的文件。
$ COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf

最新文章

  1. iScroll知识点
  2. (转)EntityFramework之领域驱动设计实践
  3. Xamarin.IOS之多视图
  4. 15个私有云上的DevOps 开源工具
  5. TCP连接建立的三次握手过程可以携带数据吗?
  6. ios qq 分享 失败
  7. UDP议定书图像高速传输无损失程序
  8. ECP系统J2EE架构开发平台
  9. 关于JS跨域问题的解决
  10. 201521123106《java程序设计》第四周学习总结
  11. 如何录屏制作gif图片
  12. Hadoop DataNode不能正常工作的原因
  13. linux中使用docker-compose部署软件配置分享
  14. react基础学习 一
  15. MongoDB数据创建与使用
  16. 关于mirai的一些研究
  17. Net 4.5 WebSocket 在 Windows 7, Windows 8 and Server 2012上的比较
  18. Gis数据处理2 ---8.18
  19. Linux内核如何装载和启动一个可执行程序(转)
  20. 使用SQL Server Management Studio操作replication时,要用机器名登录,不要用IP地址

热门文章

  1. C# 查看变量的内存占用和分布
  2. CentOS 7 忘记root密码的解决方法
  3. locust中的监听器
  4. unity 2D 物体跟随鼠标旋转 移动
  5. 从零搭建hadoop集群之mysql安装
  6. vim重复、删除、复制、粘贴命令
  7. ORM框架的延迟加载(懒加载)
  8. SQLite检查表是否存在
  9. esxi虚拟机定时创建快照
  10. 220327_IDEA调试debug时step into看不了方法内部的解决办法