docker客户端与守护进程权限隔离核心是限制socket访问,仅root及docker组成员可读写/var/run/docker.sock;生产环境严禁随意加组,应通过tls双向认证、守护进程安全配置及api网关实现细粒度管控。
docker 客户端与守护进程(dockerd)之间的权限隔离,核心在于限制客户端对守护进程的访问控制权,防止未授权用户通过 docker 命令获得宿主机高危操作能力。这不是容器内隔离,而是宿主机上进程间通信(api 调用)层面的身份与权限管控。
明确通信机制:客户端靠 socket 连守护进程
Docker 客户端(docker CLI)默认通过 Unix domain socket /var/run/docker.sock 与守护进程通信。该 socket 文件的文件系统权限直接决定谁能调用 Docker API:
- 默认属主:
root:docker - 默认权限:
srw-rw----(即只有 root 和 docker 组成员可读写)
⚠️ 关键风险:只要用户在 docker 组中,就等同于拥有 宿主机 root 权限(因容器可挂载宿主机路径、执行特权操作等)。
禁止无差别加组:严格控制 docker 组成员
把用户加入 docker 组是最常见也最危险的“便捷做法”。必须避免“为开发方便全员加组”。
-
✅ 正确做法:
- 仅授予真正需要构建/管理容器的运维或 CI/CD 服务账户
- 使用独立系统用户(如
ci-runner,deploy-bot),而非开发者个人账号 - 配合
sudo策略做二次鉴权(例如只允许运行特定docker run模板命令)
-
❌ 错误示例:
sudo usermod -aG docker $USER # 开发者本地测试可接受,生产服务器严禁
启用 TLS 加密通信(远程 API 场景)
当客户端需通过 TCP(如 docker -H tcp://192.168.1.10:2376)连接远程守护进程时,必须启用 TLS 双向认证,否则等同于裸奔暴露 Docker API:
- 守护进程启动参数:
{ "hosts": ["tcp://0.0.0.0:2376", "unix:///var/run/docker.sock"], "tls": true, "tlscacert": "/etc/docker/ca.pem", "tlscert": "/etc/docker/server.pem", "tlskey": "/etc/docker/server-key.pem" } - 客户端必须提供有效 client cert + key,并验证服务端证书 CA;
- 每个客户端证书可绑定特定角色(如仅允许
pull和run,禁用build或exec),需配合外部策略引擎(如 Open Policy Agent)实现细粒度 RBAC。
限制守护进程监听范围与能力
即使 socket 权限收紧,也要防止守护进程本身被滥用:
-
✅ 禁用不安全的启动方式:
- 不使用
--host=fd://以外的非 socket 方式暴露 API(尤其避免tcp://0.0.0.0:2375明文) - 不挂载
/var/run/docker.sock进容器(除非绝对必要,且容器必须是可信系统组件)
- 不使用
-
✅ 启用守护进程级安全选项:
- 在
/etc/docker/daemon.json中设置:{ "userns-remap": "default", "icc": false, "no-new-privileges": true, "default-ulimits": { "nofile": { "Name": "nofile", "Hard": 65536, "Soft": 65536 } } } - 重启后生效:
sudo systemctl restart docker
- 在
这些配置不改变客户端权限,但大幅降低客户端一旦越权后的破坏半径。
替代方案:用代理或网关收口 API 访问
对多租户或 SaaS 类平台,建议在客户端与 dockerd 之间插入一层轻量网关(如 Portainer Agent、Docker Socket Proxy 或自研 API 网关):
- 客户端只连网关(HTTP),网关以最小权限身份连
docker.sock - 网关可做:
- 请求白名单(只放行
container list,image pull等安全操作) - 参数校验(拦截
--privileged,--cap-add=SYS_ADMIN等高危参数) - 用户身份绑定与审计日志落库
- 资源配额(如单用户最多运行 3 个容器)
- 请求白名单(只放行
这种方式将权限判断逻辑从 Linux 文件权限层,上升到应用逻辑层,更可控。
不复杂但容易忽略。











