Gitlab CI中的Dood与Dind
在通过jenkins或Gitlab使用Docker容器化构建服务的时候,我们会遇到两种构建的方式,分别是DIND与DOOD,这两种的构建的方式却有着很大的差异,接下来分别介绍两种构建方式的区别:
Dood
相信很多人会认为dind就是通过挂载卷的方式通过-p /var/run/docker.sock:/var/run/docker.sock
挂载到容器内,通过docker engine与这个被挂载进来的docker.sock
进行通信,其实这种方式是DOOD
Dind
既然知道了以往我们认为的dind被纠正为Dood
了,那dind
究竟是什么,实际上dind指的是在一个安装有Docker engine的容器内以特权模式和与之--link
的docker daemon
进行通信,并在容器内构建新的Docker镜像。解释起来感觉很绕口,下面我们通过gitlab runner[1]的docker executor
来逐一验证这些概念。
下面是一张dind与dood构建方式的区别,仅供参考:
![7c8237c05427b5df7c91ac325818e9e5.png](https://i-blog.csdnimg.cn/blog_migrate/4485b1e75c55fb5395239962ae8a095c.png)
经过上图,基本上了解了dood与dind之间的区别,现在我们先运行一个通过docker container运行的gitlab-runner,同时注册其的执行器
为docker方式:
docker run --rm -t -i -v /etc/gitlab-runner:/etc/gitlab-runner --name gitlab-runner gitlab/gitlab-runner register \
--executor "docker" \
--docker-image alpine:3 \
--url "https://code.devopsman.cn/" \
--registration-token "PROJECT_REGISTRATION_TOKEN" \
--description "share-platform01" \
--tag-list "p01" \
--run-untagged \
--locked="true"
这里需要了解一下docker executor
的运行方式:
- 创建
.gitlab-ci.yml
中service
指令声明的 容器 - 然后创建用于缓存cache的容器
- 创建 build 容器并且关联到所有通过
service
指令创建的容器,使其可以通过主机名进行通信 - 将job里面声明的shell指令发送到启动后的build容器内
- 执行 job片段内声明的指令
- 检出代码: /builds/group-name/project-name/
- 执行 .gitlab-ci.yml 中定义的步骤.
- 检查脚本执行后的状态码,如果非 0 则构建失败.
- 清理 build 和 service 容器.
在大致的了解docker executor的工作流程之后,我们修改gitlab-runner的配置文件,修改后gitlab-runner会自动加载更新后的配置
[[runners]]
name = "share-platform01"
url = "https://code.devopsman.cn"
token = "AHjrbxtH8_cNyHZtG8KH"
executor = "docker"
privileged = true
[runners.custom_build_dir]
[runners.cache]
[runners.cache.s3]
[runners.cache.gcs]
[runners.docker]
tls_verify = false
image = "busybox"
privileged = true
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
volumes = ["/cache"]
shm_size = 0
在该配置文件中,增加了privileged=true
的指令,让gitlab-runner容器拥有特权模式,而后我们在一个node.js
的项目中,添加一个.gitlab-ci.yml
文件
image: docker:stable
services:
- docker:19.03.7-dind
variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
stages:
- build
- test
- deploy
before_script:
- docker login -u${DOCKER_REGISTRY_USER} -p${DOCKER_REGISTRY_PASSWORD} ${DOCKER_REGISTRY_ADDRESS}
BuildImages:
stage: build
script:
- docker build -t registry.cn-beijing.aliyuncs.com/devopsman/marionxue-ops:${CI_PROJECT_NAME} .
- docker push registry.cn-beijing.aliyuncs.com/devopsman/marionxue-ops:${CI_PROJECT_NAME}
only:
- master
TestImage:
stage: test
script:
- mkdir -pv /logs/${CI_PROJECT_NAME}
- if [ $(docker ps -qa --filter name=${CI_PROJECT_NAME}) ];then docker rm -f ${CI_PROJECT_NAME};fi
- docker run -d --restart=always --name ${CI_PROJECT_NAME} -v /logs/nodedemo:/logs/${CI_PROJECT_NAME} -e NODE_ENV=production --net=host registry.cn-beijing.aliyuncs.com/devopsman/marionxue-ops:${CI_PROJECT_NAME}
- sleep 5
- docker ps -as
- docker ps -a
这个项目的.gitlab-ci.yml
文件,会触发share-platform01
这个runner运行一个新的容器,并且使用含有docker二进制的docker:stable
为基础镜像,同时创建一个运行有docker daemon
的容器与其关联,这样既可在gitlab-runner的容器内使用docker pull
、build
、push
等与docker daemon
通信的命令。同时在gitlab-runner内拉取的镜像和构建的中间产物都存在与gitlab-runner容器内,与宿主机上是完全隔离的。这也适用与多环境的同时测试。
这就是Dind
方式的构建,这里要注意的是Dind使用过程中,文件系统挂载[2]问题
下面我们介绍一下Dood方式的构建,在gitlab-runner配置文件上有部分的区别:
[[runners]]
name = "share_runner_01"
url = "https://code.devopsman.cn"
token = "wiyyzkYq9BHhG4cCQHWu"
executor = "docker"
[runners.custom_build_dir]
[runners.docker]
tls_verify = false
image = "busybox:latest"
privileged = false
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock"]
shm_size = 0
[runners.cache]
[runners.cache.s3]
[runners.cache.gcs]
这里通过volumes
将宿主机上的/var/run/docker.sock
挂载到了gitlab-runner容器内,但实质上是与宿主机上的docker daemon
通信,而在构建过程中拉取的镜像和中间镜像都存在宿主机上,这样虽然可以高效的利用上了Docker的镜像缓存,但是也因为不同的构建环境造成镜像文件过多等后期的磁盘存储问题。
Dind/Dood在K8s上的使用
Dood & k8s
apiVersion: v1
kind: Pod
metadata:
name: dood
spec:
containers:
- name: docker-cmds
image: docker:1.12.6
command: ['docker', 'run', '-p', '80:80', 'httpd:latest']
resources:
requests:
cpu: 10m
memory: 256Mi
volumeMounts:
- mountPath: /var/run
name: docker-sock
volumes:
- name: docker-sock
hostPath:
path: /var/run
Dind & k8s
apiVersion: v1
kind: Pod
metadata:
name: dind
spec:
containers:
- name: docker-cmds
image: docker:1.12.6
command: ['docker', 'run', '-p', '80:80', 'httpd:latest']
resources:
requests:
cpu: 10m
memory: 256Mi
env:
- name: DOCKER_HOST
value: tcp://localhost:2375
- name: dind-daemon
image: docker:1.12.6-dind
resources:
requests:
cpu: 20m
memory: 512Mi
securityContext:
privileged: true
volumeMounts:
- name: docker-graph-storage
mountPath: /var/lib/docker
volumes:
- name: docker-graph-storage
emptyDir: {}
参考资料
[1]gitlab-runner: https://docs.gitlab.com/runner/
[2]Dind-mounts: https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41227