Docker-in-Docker(DinD)在容器内运行 Docker 守护进程。对于必须构建或测试镜像的一次性 CI 作业,它有时很有用,但会增加特权内核访问、嵌套存储和缓存方面的复杂性。调用 docker 的作业不应默认都采用它。
选择正确的构建模型 #
常见模型有三种:
- **DinD:**专用守护进程在作业的网络命名空间中运行。它与主机守护进程隔离,但通常需要特权模式。
- **Docker-outside-of-Docker:**作业挂载主机 Docker 套接字。方案简单且快速,但任何能够使用该套接字的进程都可以控制主机 Docker 守护进程。
- **无守护进程构建器:**BuildKit、Kaniko、Buildah 或托管构建器在不暴露通用主机守护进程的情况下创建 OCI 镜像。
使用能够支持构建的最低特权选项。无 root 的 BuildKit 或远程 BuildKit 构建器可以保持缓存效率,同时不向 CI 作业授予访问运行器 Docker 套接字的权限。
使用 TLS 运行 DinD 服务 #
官方 docker:dind 镜像会启动 dockerd;它设计为与独立的 Docker CLI 容器或 CI 作业配合使用。让守护进程处于隔离网络中,并为其 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 标志会向服务授予广泛的主机内核能力。只能在隔离的一次性运行器上运行它。不要暴露未经身份验证的 dockerd TCP 端口:任何能够访问该端口的人都可以创建特权容器,并通常能够控制其主机。
处理缓存与清理 #
DinD 的镜像和层缓存位于服务容器的 /var/lib/docker 中。持久化缓存卷可以加快重复构建,但必须限定在受信任的项目或租户范围内;镜像层可能包含源代码和构建密钥。对于共享 CI 基础设施,应优先使用由镜像仓库支持的 BuildKit 缓存。
使用基于不可变提交标识符的唯一标签,仅在测试通过后推送,并根据运行器的保留策略删除临时容器和镜像。绝不要通过 Dockerfile 的 ARG 或 ENV 传递密钥;应改用 BuildKit 密钥挂载或 CI 系统的密钥机制。
评论
在 GitHub 上阅读或评论(发表评论需要登录)