Docker-in-Docker (DinD) vs docker.sock
这是一个DevOps / CI / 安全 / 架构设计的高频“生死题”。
docker.sock ≠ 安全
DinD ≠ 干净
生产 CI:两者都不完美,但 docker.sock 更常用
高安全环境:两者都不推荐,优先 rootless / buildkit / kaniko
一句话记忆:
docker.sock 是“借刀杀人”
DinD 是“自带一把刀”
容器
|
| /var/run/docker.sock
v
宿主机 dockerd
volumes:
- /var/run/docker.sock:/var/run/docker.sock
👉 容器里执行 docker 命令 = 操作宿主机 Docker
容器
└─ dockerd(自己的)
└─ containerd
└─ runc
image: docker:dind
privileged: true
👉 容器里跑一个“完整 Docker 引擎”
| 维度 | docker.sock | DinD |
|---|---|---|
| Docker 引擎 | 宿主机 | 容器内 |
| daemon 数量 | 1 | N |
| 是否隔离 | ❌ | ⚠️ 部分 |
| 是否需要特权 | ❌ | ✅ |
| 构建缓存 | 共享 | 独立 |
| 网络复杂度 | 低 | 高 |
谁能访问 docker.sock,谁就等于 root on host
攻击示例(真实):
docker run -v /:/host alpine chroot /host
📌 后果:
- 宿主机完全失陷
- 无任何隔离
- 审计直接 FAIL
👉 docker.sock = root shell 的另一种形式
问题点:
- 必须
--privileged - 能加载内核模块
- 能操作 cgroups / namespace
📌 结果:
- 仍然可逃逸
- 只是路径更绕
👉 DinD ≠ 安全隔离
✅ 构建速度快 ✅ 缓存共享 ✅ 网络简单 ❌ 容易互相污染(删镜像)
✅ 环境相对干净 ✅ 不污染宿主镜像 ❌ 构建慢 ❌ 镜像重复下载 ❌ overlay2 套 overlay2(性能差)
| 维度 | docker.sock | DinD |
|---|---|---|
| 使用率 | ⭐⭐⭐⭐⭐ | ⭐⭐ |
| 排障难度 | 低 | 高 |
| 并发稳定性 | 一般 | 差 |
| 安全审计 | ❌ | ❌ |
📌 大厂 CI 实际:docker.sock 居多(加隔离)
-> 错,privileged 是致命点
-> 错,是 Docker API 的 root 接口
-> 错,生产根本不该在容器里 build 镜像
docker buildx build
- 无需 docker.sock(可控)
- 支持远程 builder
- 支持 rootless
✅ 无需 Docker daemon ✅ 无特权 ✅ 云原生友好
buildah bud
✅ daemonless ✅ rootless ✅ 安全审计友好
- 内部 CI
- 非安全敏感
- 构建机器独占
- 有沙箱 / VM 隔离
📌 前提:CI Runner 是独立 VM
- 多租户 CI
- 需要镜像隔离
- 不允许访问宿主 Docker
📌 但仍需 VM 级隔离
| 场景 | 推荐 |
|---|---|
| 本地开发 | Docker |
| CI 构建 | buildx / Kaniko |
| 生产 | 不在容器内构建 |
docker.sock 是直接共享宿主机 Docker API,等价于 root 权限,安全风险极高;Docker-in-Docker 通过在容器内运行独立 daemon 提供一定隔离,但仍需 privileged,不能视为安全。现代 CI 更推荐使用 BuildKit、Kaniko 或 rootless 构建方案。
docker.sock:最快,但最危险
DinD:看似隔离,实则脆弱
真正安全:不在容器里跑 Docker