在 Docker 容器中控制宿主机 Docker:DoD 与 DinD 的技术原理解析

在构建 CI/CD 平台、发布系统或容器管理工具时,经常会看到如下配置:

plain 复制代码
volumes:
  - /var/run/docker.sock:/var/run/docker.sock

这个配置看似简单,却涉及 Docker 的核心通信机制。本文从底层原理出发,系统梳理:

  • docker.sock 的作用
  • 容器如何控制宿主机 Docker
  • CLI 与 SDK 两种调用方式的区别
  • DoD 与 DinD 架构差异
  • 生产环境需要关注的安全问题

一、docker.sock 的本质

在 Linux 系统中,Docker Daemon 通过 Unix Socket 提供 API 服务:

plain 复制代码
/var/run/docker.sock

Docker CLI(docker 命令)并不直接管理容器,它只是一个客户端工具。

当执行:

plain 复制代码
docker ps

实际发生的是:

plain 复制代码
docker CLI
    ↓
/var/run/docker.sock
    ↓
Docker Daemon
    ↓
返回容器列表

也就是说,真正执行容器操作的是 Docker Daemon,而 CLI 只是 API 调用者。


二、容器挂载 docker.sock 后发生了什么?

当在容器中挂载:

plain 复制代码
- /var/run/docker.sock:/var/run/docker.sock

意味着容器内部也可以访问宿主机的 Docker API。

此时,在容器内执行:

plain 复制代码
docker ps

控制的仍然是宿主机的 Docker Daemon,而不是容器内部的 Docker。

这也是很多发布平台和容器管理工具的实现方式。


三、两种常见调用方式

1️⃣ 通过 Docker CLI

示例:

plain 复制代码
import { exec } from "child_process";

exec("docker ps", (err, stdout) => {
  console.log(stdout);
});

特点:

  • 需要在容器中安装 docker-cli
  • 本质仍然是 CLI 调用 docker.sock
  • 错误处理依赖字符串解析

调用链:

plain 复制代码
Agent
   ↓
docker CLI
   ↓
/var/run/docker.sock
   ↓
Docker Daemon

2️⃣ 通过 Docker SDK(如 dockerode)

示例:

plain 复制代码
import Docker from "dockerode";

const docker = new Docker({
  socketPath: "/var/run/docker.sock",
});

const containers = await docker.listContainers();

调用链:

plain 复制代码
Agent
   ↓
Docker SDK
   ↓
/var/run/docker.sock
   ↓
Docker Daemon

对比:

维度 CLI 方式 SDK 方式
是否需要 docker-cli
调用方式 shell HTTP API
错误处理 字符串 JSON
日志流支持 复杂 原生支持
可扩展性 一般

两种方式最终控制的都是宿主机 Docker,差异仅在调用层。


四、DoD 与 DinD 的区别

Docker outside of Docker(DoD)

特点:

  • 容器内部没有 Docker Daemon
  • 通过挂载 docker.sock 控制宿主机 Docker
  • 资源消耗低
  • 启动速度快

架构模型:

plain 复制代码
Container (Agent)
       ↓
/var/run/docker.sock
       ↓
Host Docker Daemon

常见于:

  • Portainer
  • Watchtower

Docker in Docker(DinD)

特点:

  • 容器内部运行独立 Docker Daemon
  • 通常需要 privileged 模式
  • 适用于 CI 构建隔离环境

架构模型:

plain 复制代码
Container
   ↓
Docker Daemon(容器内部)
   ↓
子容器

常见于:

  • GitLab CI
  • Jenkins

五、安全风险分析

挂载 docker.sock 等价于授予容器对宿主机 Docker 的完全控制权。

通过 Docker API 可以:

  • 启动特权容器
  • 挂载宿主机目录
  • 修改网络配置
  • 删除任意容器

一旦容器被入侵,宿主机安全将受到影响。

常见缓解方式:

  • 不暴露 Agent 至公网
  • 使用内网通信
  • 使用强认证 Token
  • 尽量使用 SDK 而非 shell 执行

六、核心结论

  1. docker.sock 是 Docker Daemon 的通信入口
  2. 挂载 docker.sock 后,容器可以直接控制宿主机 Docker
  3. CLI 与 SDK 本质相同,区别在调用方式
  4. DoD 是生产环境常见方案
  5. DinD 适用于需要隔离 Docker 环境的场景

理解 docker.sock 的通信模型,有助于在设计 CI/CD 或容器管理系统时做出正确的架构选择。

相关推荐
SuniaWang42 分钟前
Vue 3 + Spring Boot 21 全栈 RAG 项目Docker Compose 容器化部署
vue.js·人工智能·spring boot·spring·阿里云·docker·milvus
ezreal_pan43 分钟前
Kafka Docker 部署避坑指南:监听器配置与客户端连接问题深度解析
分布式·docker·kafka
岁岁种桃花儿1 小时前
kubenetes从入门到上天系列第二十篇:Kubernetes安装Nginx ingress controller
nginx·容器·kubernetes
lpfasd1231 小时前
Kubernetes UI 管理全景指南
ui·容器·kubernetes
00后初来乍到2 小时前
Docker 搭建 LNMP(Nginx+PHP+MySQL)完整踩坑实录
nginx·docker·php
吾诺2 小时前
springboot整合libreoffice(两种方式,使用本地和远程的libreoffice);docker中同时部署应用和libreoffice
spring boot·后端·docker
weixin_397578022 小时前
Docker 完整介绍
运维·docker·容器
the_fat_bird2 小时前
自存 | VSCode+SSH+Docker远程Python Debugger
vscode·docker·ssh
FriendshipT3 小时前
Ultralytics Docker 安装使用教程(以训练 YOLO26 模型为例)
linux·运维·人工智能·目标检测·ubuntu·docker·容器
FriendshipT3 小时前
Ubuntu 20.04 LTS 安装 Docker 指南
linux·ubuntu·docker