咱们在编写 CI 时通过申明镜像作为 job 的执行环境,每个 job 都在一个污浊的容器中执行。有时,咱们须要一个 docker
容器环境来执行 docker build
、docker push
等操作。查看官网的 docker 镜像,咱们发现存在两个次要的版本:docker:latest
、docker:dind
和 docker:git
。
docker:dind
该镜像蕴含 Docker 客户端(命令行工具)和 Docker daemon。
通过 docker history docker:dind
命令咱们发现 docker:dind
是在 docker:latest
根底上又装置了 Docker daemon,并且最初两个构建命令为:
IMAGE CREATED CREATED BY SIZE COMMENT
66dc2d45749a 8 weeks ago /bin/sh -c #(nop) CMD [] 0B
<missing> 8 weeks ago /bin/sh -c #(nop) ENTRYPOINT ["dockerd-entr… 0B
...
在 run
该镜像时,不能指定 sh
CMD 参数,dockerd-entrypoint.sh
命令接管到该参数并不会启动 Docker daemon。想要正确启动容器里的 Docker daemon 并且进入容器须要分步进行:
$ docker run -d --name dind --privileged docker:dind # 启动容器
$ docker logs -f dind # 查看启动日志
$ docker exec -it dind sh # 进入容器
启动 docker:dind
容器时,参数 --privileged
必须加上,否则 Docker daemon 启动时会报错。
docker:latest
该镜像只蕴含 Docker 客户端,须要有 Docker daemon 反对,能够应用 docker:dind
的,也能够挂载宿主机的 /var/run/docker.sock
。
该镜像启动不须要 --privileged
参数。
通过 docker history docker:latest
命令发现 CMD 默认为 sh
:
81f5749c9058 3 months ago /bin/sh -c #(nop) CMD ["sh"] 0B
<missing> 3 months ago /bin/sh -c #(nop) ENTRYPOINT ["docker-entry… 0B
...
启动形式一:挂载宿主机 sock 文件
$ docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock docker:latest
启动形式二:配合 docker:dind
将 docker:dind
和 docker:latest
放入雷同网络,并且指定 dind
容器在该网络中的别名为 docker
,因为 latest
容器中默认设定的 daemon host
就叫 docker
。
另外须要留神 证书 问题,新版本 Docker 客户端与 Docker daemon 通信须要 TLS 证书保障通信平安,docker:dind
容器会生成证书到环境变量 DOCKER_TLS_CERTDIR
指定的目录,需将证书挂载并提供给 docker:latest
容器应用。
$ docker run --privileged --name some-docker -d \
--network some-network --network-alias docker \
-e DOCKER_TLS_CERTDIR=/certs \
-v some-docker-certs-ca:/certs/ca \
-v some-docker-certs-client:/certs/client \
docker:dind
$ docker run --rm --network some-network \
-e DOCKER_TLS_CERTDIR=/certs \
-v some-docker-certs-client:/certs/client:ro \
docker:latest
docker:git
docker:git
是蕴含了 git
命令的 docker:latest
,不便 CI 时应用 Git。
参考链接
- Docker Hub – docker