使用证书验证仓库客户端
在使用 HTTPS 运行 Docker中,您了解到默认情况下,Docker 通过非网络化的 Unix 套接字运行,必须启用 TLS 才能让 Docker 客户端和守护进程通过 HTTPS 安全通信。TLS 确保注册表端点的真实性以及与注册表之间的流量加密。
本文演示如何确保 Docker 注册表服务器和 Docker 守护进程(注册表服务器的客户端)之间的流量通过基于证书的客户端-服务器身份验证进行加密和正确验证。
我们向您展示如何安装注册表的证书颁发机构(CA)根证书,以及如何设置客户端 TLS 证书进行验证。
了解配置
通过在守护进程的证书根目录下创建与注册表主机名相同的目录(例如 localhost)来配置自定义证书。所有 *.crt 文件都作为 CA 根添加到此目录中。
该证书根目录的位置取决于平台:
- 原生 Linux Engine:
/etc/docker/certs.d/ - 无根(Rootless)Linux:
$XDG_CONFIG_HOME/docker/certs.d(默认为~/.config/docker/certs.d),而不是/etc/docker/certs.d - 原生 Windows Engine(Windows 容器):
%PROGRAMDATA%\docker\certs.d(通常为C:\ProgramData\docker\certs.d)。如果注册表地址包含端口,请从目录名中去掉冒号,因为 Windows 文件名不能包含:。例如,registry.example.com:5000变为registry.example.com5000。 - 使用 Linux 容器的 Docker Desktop:将客户端证书放在主机的
~/.docker/certs.d中。Docker Desktop 会将它们复制到 VM 中;不要自己在 VM 内配置/etc/docker/certs.d。受信任的 CA 也可以来自主机证书存储(在 Windows 上为 Windows 证书存储)。
Note在 Linux 上,任何根证书颁发机构都会与系统默认值合并,包括主机的根 CA 集。如果您在 Windows Server 上运行 Docker,或在 Windows 上使用 Windows 容器运行 Docker Desktop,则仅在未配置自定义根证书时使用系统默认证书。
存在一个或多个 <filename>.key/cert 对表示 Docker 需要自定义证书才能访问所需的仓库。
Note如果存在多个证书,将按字母顺序尝试每个证书。如果出现 4xx 级或 5xx 级身份验证错误,Docker 会继续尝试下一个证书。
以下说明了具有自定义证书的配置:
/etc/docker/certs.d/ <-- 证书目录
└── localhost:5000 <-- 主机名:端口
├── client.cert <-- 客户端证书
├── client.key <-- 客户端密钥
└── ca.crt <-- 签署注册表证书的根 CA,PEM 格式上述示例是特定于操作系统的,仅用于说明目的。您应该查阅操作系统文档以创建操作系统提供的捆绑证书链。
创建客户端证书
使用 OpenSSL 的 genrsa 和 req 命令首先生成 RSA 密钥,然后使用该密钥创建证书。
$ openssl genrsa -out client.key 4096
$ openssl req -new -x509 -text -key client.key -out client.cert
Note这些 TLS 命令仅在 Linux 上生成一组可工作的证书。macOS 中的 OpenSSL 版本与 Docker 所需的证书类型不兼容。
故障排除提示
Docker 守护进程将 .crt 文件解释为 CA 证书,将 .cert 文件解释为客户端证书。如果 CA 证书意外使用了扩展名 .cert 而不是正确的 .crt 扩展名,Docker 守护进程会记录以下错误消息:
Missing key KEY_NAME for client certificate CERT_NAME. CA certificates should use the extension .crt.如果未使用端口号访问 Docker 注册表,请不要在目录名中添加端口。以下显示了在默认端口 443 上的注册表的配置,通过 docker login my-https.registry.example.com 访问:
/etc/docker/certs.d/
└── my-https.registry.example.com <-- 不带端口的主机名
├── client.cert
├── client.key
└── ca.crt