docker client与daemon是解耦的独立角色,client仅解析命令并发送http请求至daemon,后者通过rest api和socket/tcp通信接收请求,交由containerd、runc等模块执行容器操作,支持跨机器、跨工具、跨协议调用。

Docker 的 Client 与 Daemon 并非紧耦合的单体程序,而是通过明确接口(REST API + Socket/TCP)分离的两个独立角色。理解这种解耦,是掌握远程调用机制的关键入口——它决定了你能否在笔记本上一键启停服务器上的容器,也决定了 Kubernetes 是如何接管底层容器生命周期的。
Client 不执行任何容器操作,只负责“传话”
Docker 命令行(如 docker run nginx)本身不拉镜像、不创建命名空间、不启动进程。它只做三件事:
- 解析参数(-d、-p 8080:80、--name web 等),校验语法合法性
- 把请求组装成标准 HTTP 请求(例如 POST /containers/create,Body 是 JSON 描述)
- 发给 Daemon 地址(默认 unix:///var/run/docker.sock),等响应并格式化输出
这意味着:删掉本地的 docker 二进制文件,只要能构造出同样结构的 HTTP 请求,照样能控制容器。curl、Postman、甚至 Python 的 requests 库,都是合法的 “Docker Client”。
Daemon 是唯一真正干活的后台服务
dockerd 进程常驻系统,监听来自任意 Client 的请求。它内部不关心你是从本机终端、CI 脚本,还是另一台云主机连过来的——只要请求合法、认证通过,就照常调度 containerd → runc → 启动容器进程。
- 默认监听 Unix Socket(unix:///var/run/docker.sock),仅限本机通信
- 修改配置启用 TCP 监听(如 tcp://0.0.0.0:2375),Client 就可通过 docker -H tcp://192.168.1.100:2375 ps 远程管理
- 生产环境必须开启 TLS(证书双向验证),否则裸开 2375 端口等于把服务器控制权暴露在公网
解耦带来的真实能力:跨机器、跨工具、跨协议
正因为 Client/Server 彼此独立,才支撑起现代容器生态的灵活性:
- 跨机器运维:开发机装 Docker CLI,目标服务器只运行 dockerd(不装 CLI),通过 -H 连接即可部署
- 跨工具协同:Docker Compose、Portainer、Jenkins 插件、Kubernetes kubelet,本质都是不同形态的 Client,共用同一套 Daemon 接口
- 跨协议接入:不用 docker 命令也能操作——直接调 curl -X POST http://host:2375/containers/create,传 JSON body,和 CLI 效果完全一致
验证解耦最简单的方法:手动模拟一次请求
无需写代码,用 curl 就能绕过 CLI,直连 Daemon:
- 确保 dockerd 已配置并监听 tcp://127.0.0.1:2375(测试环境可暂不启用 TLS)
- 执行:curl -X POST "http://127.0.0.1:2375/containers/create?name=test" -H "Content-Type: application/json" -d '{"Image":"alpine","Cmd":["sleep","300"]}'
- 再执行:curl -X POST "http://127.0.0.1:2375/containers/test/start"
- 最后:docker ps 就能看到这个由 curl 创建的容器
整个过程没出现一个 docker run,但容器照常运行——这正是 C/S 解耦最直观的体现。











