咱們在編寫 CI 時經過聲明鏡像做爲 job 的執行環境,每一個 job 都在一個純淨的容器中執行。有時,咱們須要一個 docker
容器環境來執行 docker build
、docker push
等操做。查看官方的 docker 鏡像,咱們發現存在兩個主要的版本:docker:latest
、docker:dind
和 docker:git
。git
該鏡像包含 Docker 客戶端(命令行工具)和 Docker daemon。docker
經過 docker history docker:dind
命令咱們發現 docker:dind
是在 docker:latest
基礎上又安裝了 Docker daemon,而且最後兩個構建命令爲:shell
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 客戶端,須要有 Docker daemon 支持,能夠使用 docker:dind
的,也能夠掛載宿主機的 /var/run/docker.sock
。工具
該鏡像啓動不須要 --privileged
參數。ui
經過 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 ...
$ docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock docker:latest
將 docker:dind
和 docker:latest
放入相同網絡,而且指定 dind
容器在該網絡中的別名爲 docker
,由於 latest
容器中默認設定的 daemon host
就叫 docker
。日誌
另外須要注意 證書 問題,新版本 Docker 客戶端與 Docker daemon 通信須要 TLS 證書保證通信安全,docker:dind
容器會生成證書到環境變量 DOCKER_TLS_CERTDIR
指定的目錄,需將證書掛載並提供給 docker:latest
容器使用。code
$ 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
是包含了 git
命令的 docker:latest
,方便 CI 時使用 Git。