背景:
在編寫 CI 時通過聲明鏡像作為 job 的執行環境,每個 job 都在一個純凈的容器中執行。
有時,我們需要一個?docker?容器環境來執行?docker build、docker push?等操作。查看官方的 docker 鏡像,我們發現存在兩個主要的版本:docker:latest、docker:dind?和?docker:git。
(推薦教程:docker教程)
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?????????????????? ...</missing>
在?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?????????????????? ...</missing>
啟動方式一:掛載宿主機 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。