Docker-in-Docker

最後更新: 2022-09-14 14:25:00 +0800 +0800
原文以英文撰寫。您正在閱讀AI翻譯版本。

Docker-in-Docker(DinD)會在容器內執行 Docker daemon。對於必須建置或測試映像的可丟棄 CI 工作,有時使用 DinD 很有幫助,但它會增加特權核心存取權、巢狀儲存空間與快取複雜度。每個會呼叫 docker 的工作都不應預設採用 DinD。

選擇適當的建置模型 #

常見模型有三種:

  1. DinD: 專用 daemon 在工作網路命名空間中執行。它與主機 daemon 隔離,但通常需要特權模式。
  2. Docker-outside-of-Docker: 工作掛載主機 Docker socket。這種方式簡單且快速,但任何能使用該 socket 的程序都能控制主機 Docker daemon。
  3. 無 daemon 建置器: BuildKit、Kaniko、Buildah 或受管理的建置器會建立 OCI 映像,而不暴露通用主機 daemon。

使用能支援建置的最低特權選項。無根 BuildKit 或遠端 BuildKit 建置器可以保留快取效率,而不授予 CI 工作存取 runner Docker socket 的權限。

使用 TLS 執行 DinD 服務 #

官方 docker:dind 映像會啟動 dockerd;它預期與獨立的 Docker CLI 容器或 CI 工作搭配使用。讓 daemon 位於隔離網路中,並對其 TCP 監聽器使用 TLS:

sh
docker network create ci-build
docker volume create dind-certs

docker run -d --name dind --privileged --network ci-build \
  -e DOCKER_TLS_CERTDIR=/certs \
  -v dind-certs:/certs/client \
  docker:27-dind

docker run --rm --network ci-build \
  -e DOCKER_HOST=tcp://dind:2376 \
  -e DOCKER_TLS_VERIFY=1 \
  -e DOCKER_CERT_PATH=/certs/client \
  -v dind-certs:/certs/client:ro \
  docker:27-cli version

--privileged 旗標會授予服務廣泛的主機核心功能。只能在隔離且可丟棄的 runner 上執行。不要暴露未驗證身分的 dockerd TCP 埠:任何能連線到該埠的人都能建立特權容器,通常也能控制其主機。

處理快取與清理 #

DinD 的映像與層快取位於服務容器的 /var/lib/docker。持久化快取磁碟區能加速重複建置,但必須限定在受信任的專案或租戶範圍內;映像層可能包含原始碼與建置密鑰。對共用 CI 基礎架構,優先使用由登錄站支援的 BuildKit 快取。

使用根據不可變提交識別碼建立的唯一標籤,只有測試通過後才推送,並依 runner 的保留政策移除暫存容器與映像。絕不要透過 Dockerfile 的 ARG 或 ENV 傳遞密鑰;改用 BuildKit 密鑰掛載或 CI 系統的密鑰機制。

評論

在 GitHub 上閱讀或評論(發表評論需要登入)