Docker 默认通过不联网的 Unix 套接字提供服务,也可以选择通过 SSH 或 TLS(HTTPS)套接字通信。远程客户端既需要找到正确的 Docker 守护进程,也需要验证对端身份;开放一个 TCP 端口本身并不完成这些工作。
用 SSH 保护 Docker 守护进程套接字
连接使用的远程用户名必须有权访问远程机器上的 Docker 套接字。关于非 root 用户的访问权限,参见以非 root 用户管理 Docker。
下面创建一个 Docker context,以远端的 docker-user 用户通过 SSH 连接 host1.example.com 上的 dockerd:
$ docker context create \
--docker host=ssh://docker-user@host1.example.com \
--description="Remote engine" \
my-remote-engine
my-remote-engine
Successfully created context "my-remote-engine"
创建 context 后,用 docker context use 切换 Docker CLI 的目标,再查看远程引擎的信息:
$ docker context use my-remote-engine
my-remote-engine
Current context is now "my-remote-engine"
$ docker info
<prints output of the remote engine>
切换回默认的本地守护进程时,使用 default context:
$ docker context use default
default
Current context is now "default"
也可以设置 DOCKER_HOST 环境变量,临时让 CLI 通过 SSH 连接远程机器。这种方式不必创建 context,适合临时连接另一台引擎:
$ export DOCKER_HOST=ssh://docker-user@host1.example.com
$ docker info
<prints output of the remote engine>
context 与环境变量是两种指定目标的方式。官方 context 文档说明,DOCKER_HOST 或 DOCKER_CONTEXT 可以覆盖活动 context;用过环境变量后,应检查它们是否仍在当前 shell 中生效,避免把随后命令发到错误的引擎。
复用 SSH 连接
为了让多次 Docker CLI 调用复用 SSH 连接,可以在 ~/.ssh/config 中配置:
ControlMaster auto
ControlPath ~/.ssh/control-%C
ControlPersist yes
用 TLS(HTTPS)保护 Docker 守护进程套接字
如果需要通过 HTTP 协议连接 Docker,而不是使用 SSH,可以启用 TLS:设置 tlsverify,并通过 tlscacert 指定受信任 CA 的证书。
在守护进程模式下,Docker 只接受持有该 CA 所签发证书的客户端连接;在客户端模式下,Docker 只连接持有该 CA 所签发证书的服务器。这样可以完成双向身份验证。
TLS 与 CA 管理属于较深入的配置主题。将其用于生产环境前,需要熟悉 OpenSSL、X.509 和 TLS。
创建 CA、服务器与客户端密钥
下面的 $HOST 是示例主机名占位符,应替换为 Docker 守护进程所在机器的 DNS 名称。证书中的主机名和后续连接使用的名称需要对应。代码中的 $ 是终端提示符;英文交互信息和命令输出沿用源文示例,本文没有运行这些命令,具体输出会随 OpenSSL 版本等因素变化。
首先在 Docker 守护进程所在机器上生成 CA 私钥和 CA 证书。交互字段中的信息用于构成证书的可辨别名称(DN);示例邮箱已替换为保留的示例域名地址:
$ openssl genrsa -aes256 -out ca-key.pem 4096
Generating RSA private key, 4096 bit long modulus
..............................................................................++
........++
e is 65537 (0x10001)
Enter pass phrase for ca-key.pem:
Verifying - Enter pass phrase for ca-key.pem:
$ openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem
Enter pass phrase for ca-key.pem:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:Queensland
Locality Name (eg, city) []:Brisbane
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Docker Inc
Organizational Unit Name (eg, section) []:Sales
Common Name (e.g. server FQDN or YOUR name) []:$HOST
Email Address []:operator@example.com
有了 CA 之后,生成服务器私钥与证书签名请求(CSR)。服务器 Common Name 应与连接 Docker 时使用的主机名对应。这里再次提醒:将 $HOST 替换为实际 DNS 名称。
$ openssl genrsa -out server-key.pem 4096
Generating RSA private key, 4096 bit long modulus
.....................................................................++
.................................................................................................++
e is 65537 (0x10001)
$ openssl req -subj "/CN=$HOST" -sha256 -new -key server-key.pem -out server.csr
TLS 连接也可以使用 IP 地址,因此证书中需要包含连接时会使用的 DNS 名称与 IP 地址。例如允许通过 10.10.10.20 和 127.0.0.1 连接时,把这些值加入主题备用名称(SAN):
$ echo subjectAltName = DNS:$HOST,IP:10.10.10.20,IP:127.0.0.1 >> extfile.cnf
把服务器证书的扩展用途限制为服务器身份验证:
$ echo extendedKeyUsage = serverAuth >> extfile.cnf
随后用 CA 签发服务器证书:
$ openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \
-CAcreateserial -out server-cert.pem -extfile extfile.cnf
Signature ok
subject=/CN=your.host.com
Getting CA Private Key
Enter pass phrase for ca-key.pem:
授权插件可以在双向 TLS 的身份验证之外提供更细的权限控制。运行在 Docker 守护进程中的授权插件会接收到连接客户端的证书信息,以及该插件文档描述的其他请求信息。
为客户端身份验证生成客户端私钥和 CSR。为了简化示例,这一步也可以在 Docker 守护进程所在机器上完成:
$ openssl genrsa -out key.pem 4096
Generating RSA private key, 4096 bit long modulus
.........................................................++
................++
e is 65537 (0x10001)
$ openssl req -subj '/CN=client' -new -key key.pem -out client.csr
为客户端身份验证创建独立的扩展配置文件:
$ echo extendedKeyUsage = clientAuth > extfile-client.cnf
用 CA 签发客户端证书:
$ openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem \
-CAcreateserial -out cert.pem -extfile extfile-client.cnf
Signature ok
subject=/CN=client
Getting CA Private Key
Enter pass phrase for ca-key.pem:
生成 cert.pem 和 server-cert.pem 后,两个 CSR 与这次签发使用的扩展配置文件已不再是连接所必需的文件,可以移除:
$ rm -v client.csr server.csr extfile.cnf extfile-client.cnf
限制密钥与证书文件权限
私钥必须受到保护。对于以 0666 为初始权限创建的普通文件,umask 022 会得到 0644,即所有者可读写,组与其他用户只读;它不表示组可以写入。实际密钥文件权限还取决于工具创建文件时的初始模式。这里依据 umask 手册订正源文关于组写权限的表述,仍保留下列显式权限设置。
去除私钥的写权限并只允许所有者读取,可以减少意外修改,也防止其他用户直接读取:
$ chmod -v 0400 ca-key.pem key.pem server-key.pem
证书本身可以公开读取,但也可以去掉写权限,以减少意外修改:
$ chmod -v 0444 ca.pem server-cert.pem cert.pem
启动需要客户端证书的守护进程
下面让 Docker 守护进程只接受提供受 CA 信任证书的客户端连接:
$ dockerd \
--tlsverify \
--tlscacert=ca.pem \
--tlscert=server-cert.pem \
--tlskey=server-key.pem \
-H=0.0.0.0:2376
示例的 0.0.0.0:2376 会在所有 IPv4 接口上监听。TLS 完成身份验证与传输保护,仍应按实际需求限制可达的网络范围,不能把示例地址当成任何环境都适合的暴露范围。
在 Docker 客户端机器上,指定可信 CA、客户端证书和客户端私钥,连接服务器并验证它的证书:
$ docker --tlsverify \
--tlscacert=ca.pem \
--tlscert=cert.pem \
--tlskey=key.pem \
-H=$HOST:2376 version
客户端需要 ca.pem、cert.pem 和与客户端证书对应的 key.pem。源文提示提到了复制 CA、服务器和客户端证书;这里按实际客户端命令补充了必要的客户端私钥。服务器证书由服务器在握手中提供,不必把它当作 --tlscert;CA 私钥 ca-key.pem 和服务器私钥 server-key.pem 也不应作为客户端连接材料分发。TLS 连接使用的 TCP 端口是 2376。
使用证书身份验证时,运行 Docker 客户端不必依赖
sudo或本机的docker用户组。持有这些客户端密钥的人可以向守护进程发送指令,并可能获得守护进程所在机器的 root 权限。因此应像保护 root 密码一样保护这些密钥。
默认启用验证
如果希望后续客户端连接默认使用这些材料,可以把文件放到用户主目录的 .docker 目录,并设置 DOCKER_HOST 与 DOCKER_TLS_VERIFY,减少每次调用都重复传入 -H=tcp://$HOST:2376 和 --tlsverify:
$ mkdir -pv ~/.docker
$ cp -v {ca,cert,key}.pem ~/.docker
$ export DOCKER_HOST=tcp://$HOST:2376 DOCKER_TLS_VERIFY=1
随后可以直接使用 Docker 命令:
$ docker ps
其他 TLS 模式
如果不采用完整的双向验证,可以通过组合不同标志使用其他模式。理解这些组合时,需要区分加密、验证服务器以及验证客户端三个动作。
守护进程模式:
- 设置
tlsverify、tlscacert、tlscert、tlskey:验证客户端身份。 - 设置
tls、tlscert、tlskey:不验证客户端身份。
客户端模式:
- 设置
tls:依据公共/默认 CA 池验证服务器。 - 设置
tlsverify、tlscacert:依据指定的 CA 验证服务器。 - 设置
tls、tlscert、tlskey:提供客户端证书进行身份验证,但不依据指定的 CA 验证服务器。 - 设置
tlsverify、tlscacert、tlscert、tlskey:提供客户端证书,同时依据指定的 CA 验证服务器。
客户端找到客户端证书时会发送它,因此可以把相关材料放在 ~/.docker/{ca,cert,key}.pem。如果想放在其他目录,可以通过 DOCKER_CERT_PATH 指定:
$ export DOCKER_CERT_PATH=~/.docker/zone1/
$ docker --tlsverify ps
用 curl 连接受保护的 Docker 端口
通过 curl 发送测试 API 请求时,还需要三个命令行标志,分别指定客户端证书、客户端私钥和 CA 证书:
$ curl https://$HOST:2376/images/json \
--cert ~/.docker/cert.pem \
--key ~/.docker/key.pem \
--cacert ~/.docker/ca.pem
这里的 /images/json 是源文保留的 Docker API 请求路径,不是下载凭据或创建账号的入口。本文只展示原文调用方式,没有发送请求。
相关资料
来源与许可
作者:Docker 文档团队与贡献者。原文:Protect the Docker daemon socket,文档源码。Copyright 2013–2026 Docker, Inc.,依据 Apache License 2.0发布。本文为全文中文翻译与说明整理,调整分节,订正源文 umask 组写权限表述,澄清客户端需要的证书/私钥,并补充 context 环境变量覆盖与监听范围说明。22 个源代码块中,21 个逐字保留;CA 交互示例仅把公开示例中的邮箱替换为 operator@example.com,命令、标志和 API 路径未改变。本文没有生成证书、连接守护进程或执行代码。











暂无评论内容