持续集成时,构建镜像后,通常会产生一些临时镜像
很不docker,一点也不绿色
使用DinD的方案可以解决该问题

1. 手动构建的流程

  • 代码提交到git仓库中
  • 在宿主机git pull最新代码
  • 通过docker build 使用Dockerfile进行多阶段构建
    • 编译(*.java -> .class -> jar包, *.go -> 可执行文件)
    • 使用上一步生成的文件构建镜像
  • 将构建好的镜像推送到镜像私服
  • 在服务器上将容器替换成最新镜像运行

在采用多阶段构建时,会产生中间镜像,一个tag为none的镜像。
而N个构建任务则导致N个tag为none的镜像 另外from的镜像通常也占磁盘空间
使用docker image可看到这些无用的镜像

容器的一个特色就是能绿色的运行软件
既然用了docker 自然希望构建的步骤也在容器中执行

2. 容器内构建镜像-两种方式

docker是一个c/s架构的程序

  • docker-daemon 类似于mysql-server
  • docker-client 类似于mysql-client

DinD (Docker in Docker)

在该容器内的cmd-docker类似普通的容器服务
运行 docker images 显示空 就好像一个全新的系统
docker run --privileged --name some-docker -d docker:stable-dind

DooD (Docker-outside-of-Docker)

在该容器内的cmd(docker ...)调用的是宿主机的docker-daemon
如运行 docker images 显示的就是宿主机的镜像列表
docker run -v /var/run/docker.sock:/var/run/docker.sock ...

采用DooD的方案较简单
缺点:
由于docker build实际上还是连的宿主机的 docker-daemon
宿主机最终还是会有这些tag为none的镜像 并没有达到绿色的目的
此时考虑下DinD则比较绿色

使用DinD 缺点:
由于每次都是启动一个新的容器去构建镜像 , 新的容器意味着其环境下没有任何的镜像
如果有N个任务都是from amazoncorretto:8u212 这一镜像 则每次任务都是重新拉取镜像
这种情况下的确绿色了,但重复下载镜像很浪费时间

3. 更好的方案

单独创建一个容器运行 docker-deamon 开放2375端口 所有的构建任务执行docker命令(docker ps, docker pull…)时都会被发送到此容器内执行 这样既可以绿色运行,也能使用镜像的缓存

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
容器交互图
+-------------------------------------------+
|  host-node                                |
|                                           |
|                                           |
|  +-------------------------------+        |
|  |                               |        |
|  | container: docker-deamon      |        |
|  |  dind-mode                    |        |
|  +-------------------------------+        |
|                                           |
|                 ^      ^      ^           |
|                 |      |      |           |
|                 |      |      |           |
|  +--------------+---+  |      |           |
|  | container: task1 |  |      |           |
|  +------------------+  |      |           |
|                        |      |           |
|       +----------------+-+    |           |
|       | container: task2 |    |           |
|       +------------------+    |           |
|                               |           |
|               +---------------+--+        |
|               | container: task3 |        |
|               +------------------+        |
|                                           |
+-------------------------------------------+

每次执行构建任务时,依然是在一个新的容器(taskN)中进行构建镜像
只不过容器task-N中运行的docker build命令,会被发送到docker-deamon容器中执行

3.1. 要点

  • 给docker-deamon配置镜像加速器
  • 给docker-deamon开放2375端口 以提供外部访问服务
  • 执行构建任务的容器(task) 的docker需要配置export DOCKER_HOST="tcp://192.168.6.7:2375" 以让其连接docker-deamon容器
  • 如果docker-deamon部署在k8s上, 还可考虑设置多个pod 应对并发的构建任务