介绍
保护你的 Docker 环境至关重要,而验证你的 Docker 注册表使用的 SSL 证书是维护这种安全性的一个重要步骤。本教程将指导你完成 Docker 注册表 SSL 证书的验证过程,帮助你确保安全通信并解决任何与 SSL 证书相关的的问题。
通过完成这个实验(Lab),你将了解 Docker 如何使用 SSL 证书,能够检查和验证 Docker 注册表使用的证书,并知道如何处理常见的证书问题。
保护你的 Docker 环境至关重要,而验证你的 Docker 注册表使用的 SSL 证书是维护这种安全性的一个重要步骤。本教程将指导你完成 Docker 注册表 SSL 证书的验证过程,帮助你确保安全通信并解决任何与 SSL 证书相关的的问题。
通过完成这个实验(Lab),你将了解 Docker 如何使用 SSL 证书,能够检查和验证 Docker 注册表使用的证书,并知道如何处理常见的证书问题。
Docker 注册表是存储和分发 Docker 镜像的仓库。这些注册表使用 SSL/TLS 证书来保护你的 Docker 客户端和注册表服务器之间的通信。让我们来了解一下这些证书是什么以及它们为什么重要。
SSL/TLS 证书是一个数字文档,它:
当你连接到 Docker 注册表时,你的 Docker 客户端会检查注册表的 SSL 证书,以确保连接是安全的,并且你连接到的是合法的注册表。
让我们从探索如何使用 OpenSSL(一个用于处理 SSL 证书的强大工具)来检查证书信息开始。
首先,让我们为我们的实验工作创建一个目录:
mkdir -p ~/project/ssl-lab
cd ~/project/ssl-lab
现在,让我们检查 Docker Hub 的 SSL 证书,Docker Hub 是一个常见的 Docker 注册表:
openssl s_client -connect hub.docker.com:443 -showcerts < /dev/null
这个命令连接到 Docker Hub 并显示有关其 SSL 证书的信息。你应该在输出中看到很多信息,包括:
让我们以更易读的格式提取证书信息:
echo | openssl s_client -connect hub.docker.com:443 2> /dev/null | openssl x509 -text -noout | head -20
这个命令显示证书详细信息的前 20 行,其中包括重要信息,例如:
理解这些信息是验证证书真实性的第一步。
现在我们了解了 SSL 证书的基础知识,让我们学习如何使用 Docker CLI 专门验证 Docker 注册表的证书。
Docker CLI 提供了检查注册表配置的工具,包括它们的证书设置。
让我们检查 Docker 知道的当前注册表配置:
docker info --format '{{json .RegistryConfig.IndexConfigs}}' | python3 -m json.tool
此命令输出 Docker 守护程序知道的所有注册表的配置详细信息,并以可读的 JSON 结构格式化。你会注意到 Docker Hub(在 index.docker.io)上是默认配置的。
让我们尝试连接到 Docker Hub 来验证其证书:
docker login
当提示时,你可以按 Ctrl+C 取消登录,因为我们只是在测试连接,而不是实际登录。
Docker 客户端会在登录过程中自动验证注册表的 SSL 证书。如果证书有效,你将看到登录提示。如果无效,Docker 将显示一条错误消息。
让我们创建一个脚本来更彻底地检查特定注册表的证书:
cat > check_registry_cert.sh << 'EOF'
#!/bin/bash
REGISTRY=${1:-"hub.docker.com"}
PORT=${2:-"443"}
echo "Checking certificate for $REGISTRY:$PORT..."
echo | openssl s_client -connect $REGISTRY:$PORT 2>/dev/null | openssl x509 -noout -dates -issuer -subject
echo -e "\nVerifying certificate chain..."
openssl s_client -connect $REGISTRY:$PORT -showcerts </dev/null 2>/dev/null | grep -A 1 "Certificate chain"
EOF
现在使脚本可执行:
chmod +x check_registry_cert.sh
让我们运行它来检查 Docker Hub 的证书:
./check_registry_cert.sh
你应该看到输出显示:
我们还可以检查另一个注册表,即 Microsoft 的容器注册表的证书:
./check_registry_cert.sh mcr.microsoft.com
比较输出,看看证书在注册表之间如何不同。
即使有了正确的验证过程,在处理 Docker 注册表时,你仍然可能会遇到 SSL 证书问题。让我们学习如何识别和解决最常见的问题。
最常见的 SSL 证书问题包括:
让我们创建一个目录来模拟和解决这些问题:
mkdir -p ~/project/ssl-lab/troubleshooting
cd ~/project/ssl-lab/troubleshooting
首先,让我们创建一个自签名证书来了解如何处理它们:
openssl req -newkey rsa:2048 -nodes -keyout registry.key -x509 -days 365 -out registry.crt -subj "/CN=registry.example.com"
此命令创建:
registry.key
)registry.crt
),有效期为 365 天让我们检查我们的自签名证书:
openssl x509 -in registry.crt -text -noout | grep -E "Issuer|Subject|Not"
请注意,在自签名证书中,颁发者(Issuer)和主题(Subject)是相同的,因为证书是自己签名的。
要使 Docker 信任自签名证书,你通常会将其添加到 Docker 证书目录中。让我们创建必要的目录结构:
sudo mkdir -p /etc/docker/certs.d/registry.example.com:5000
sudo cp registry.crt /etc/docker/certs.d/registry.example.com:5000/ca.crt
添加证书后,你通常会重启 Docker:
## 在真实的实验环境中,你将运行:sudo systemctl restart docker
echo "在真实的实验环境中,你将运行:sudo systemctl restart docker"
让我们通过创建一个具有过去到期日期的证书来模拟检查过期证书:
openssl req -newkey rsa:2048 -nodes -keyout expired.key -x509 -days -30 -out expired.crt -subj "/CN=expired.example.com"
现在让我们检查过期证书:
openssl x509 -in expired.crt -text -noout | grep -E "Issuer|Subject|Not"
你将看到“Not After”日期在过去,这意味着证书已过期。
在某些情况下,你可能需要使用存在证书问题的注册表。Docker 允许你将特定的注册表标记为“不安全”:
cat > daemon.json << 'EOF'
{
"insecure-registries": [
"registry.example.com:5000",
"expired.example.com:5000"
]
}
EOF
echo "在真实的实验环境中,你将把这个文件放在 /etc/docker/daemon.json"
cat daemon.json
此配置告诉 Docker 跳过对这些注册表的证书验证,这对于测试环境可能很有用,但在生产环境中应避免使用。
让我们创建一个有用的脚本来检查证书是否即将过期:
cat > check_expiration.sh << 'EOF'
#!/bin/bash
CERT_FILE=$1
DAYS_WARNING=${2:-30}
if [ ! -f "$CERT_FILE" ]; then
echo "Certificate file not found: $CERT_FILE"
exit 1
fi
## Get expiration date in seconds since epoch
EXPIRY=$(openssl x509 -in "$CERT_FILE" -noout -enddate | cut -d= -f2)
EXPIRY_SECONDS=$(date -d "$EXPIRY" +%s)
NOW_SECONDS=$(date +%s)
SECONDS_LEFT=$((EXPIRY_SECONDS - NOW_SECONDS))
DAYS_LEFT=$((SECONDS_LEFT / 86400))
echo "Certificate: $CERT_FILE"
echo "Expires on: $EXPIRY"
echo "Days remaining: $DAYS_LEFT"
if [ $DAYS_LEFT -lt 0 ]; then
echo "CRITICAL: Certificate has EXPIRED!"
exit 2
elif [ $DAYS_LEFT -lt $DAYS_WARNING ]; then
echo "WARNING: Certificate will expire in less than $DAYS_WARNING days!"
exit 1
else
echo "OK: Certificate is valid for more than $DAYS_WARNING days."
exit 0
fi
EOF
chmod +x check_expiration.sh
让我们使用这两个证书测试我们的脚本:
./check_expiration.sh registry.crt
./check_expiration.sh expired.crt
你将看到脚本正确地识别了有效证书和过期证书。
现在我们了解了如何验证和解决 SSL 证书问题,让我们探讨使用 Docker 注册表管理证书的最佳实践。
定期验证你的证书以防止意外故障至关重要。让我们创建一个可以定期运行的脚本:
cd ~/project/ssl-lab
cat > monitor_registry_certs.sh << 'EOF'
#!/bin/bash
## 要检查的注册表列表
REGISTRIES=(
"hub.docker.com"
"mcr.microsoft.com"
"registry.k8s.io"
"quay.io"
)
echo "========================================"
echo "Docker 注册表证书监视器"
echo "========================================"
echo "日期: $(date)"
echo ""
for registry in "${REGISTRIES[@]}"; do
echo "正在检查 $registry..."
CERT_INFO=$(echo | openssl s_client -connect $registry:443 2>/dev/null | openssl x509 -noout -dates -issuer -subject 2>/dev/null)
if [ -z "$CERT_INFO" ]; then
echo "错误: 无法检索 $registry 的证书"
else
echo "$CERT_INFO"
## 提取到期日期
EXPIRY=$(echo "$CERT_INFO" | grep "notAfter" | cut -d= -f2)
EXPIRY_SECONDS=$(date -d "$EXPIRY" +%s)
NOW_SECONDS=$(date +%s)
DAYS_LEFT=$(( (EXPIRY_SECONDS - NOW_SECONDS) / 86400 ))
echo "剩余到期天数: $DAYS_LEFT"
if [ $DAYS_LEFT -lt 30 ]; then
echo "警告: 证书将在 30 天内过期!"
fi
fi
echo "----------------------------------------"
done
EOF
chmod +x monitor_registry_certs.sh
让我们运行脚本,看看它是如何工作的:
./monitor_registry_certs.sh
此脚本检查多个注册表,并在任何证书即将过期时发出警告,这对于防止意外停机至关重要。
让我们创建一个文档,概述 Docker 注册表证书管理的最佳实践:
cat > certificate_best_practices.md << 'EOF'
## Docker 注册表证书管理最佳实践
### 证书采购
- 对于生产环境,使用来自受信任的证书颁发机构(Certificate Authorities)的证书
- 根据需要使用适当的证书类型(DV、OV 或 EV)
- 确保证书与用于访问注册表的精确域名匹配
- 考虑使用通配符证书(wildcard certificates)用于多个子域名
- 使用适当的密钥长度(RSA 至少 2048 位)
### 证书部署
- 安全地存储证书
- 使用正确的文件权限(仅 Docker 守护程序可读)
- 安全地备份证书和私钥
- 实施正确的证书轮换程序
- 在集群中的所有节点上保持证书路径一致
### 监控和维护
- 设置证书即将到期(至少提前 30 天)的警报
- 维护正在使用的所有证书的清单
- 记录续订程序
- 在登台环境(staging environment)中测试证书续订,然后再投入生产
- 尽可能自动化证书续订(使用 certbot 等工具)
### 安全注意事项
- 永远不要在生产环境中使用不安全的注册表
- 避免在生产中使用自签名证书
- 实施正确的证书吊销程序
- 定期审计证书使用情况和权限
- 在所有系统上保持 CA 捆绑包的更新
EOF
cat certificate_best_practices.md
最后,让我们为安全 Docker 注册表配置创建一个模板:
cat > secure_registry_config.yml << 'EOF'
version: '3'
services:
registry:
image: registry:2
ports:
- 5000:5000
environment:
REGISTRY_HTTP_TLS_CERTIFICATE: /certs/domain.crt
REGISTRY_HTTP_TLS_KEY: /certs/domain.key
## 附加安全设置
REGISTRY_STORAGE_DELETE_ENABLED: "true"
REGISTRY_HTTP_HEADERS_X_CONTENT_TYPE_OPTIONS: nosniff
REGISTRY_HTTP_HEADERS_X_FRAME_OPTIONS: DENY
volumes:
- ./certs:/certs
- ./data:/var/lib/registry
restart: always
## 可选:为你的注册表添加一个 UI
registry-ui:
image: joxit/docker-registry-ui:latest
ports:
- 8080:80
environment:
- REGISTRY_URL=https://registry:5000
- REGISTRY_TITLE=Secure Docker Registry
- SINGLE_REGISTRY=true
depends_on:
- registry
EOF
cat secure_registry_config.yml
此配置提供了一个模板,用于运行具有正确 SSL 证书配置的安全 Docker 注册表。
让我们为 Docker 的 SSL 证书管理创建一个快速参考:
cat > ssl_management_summary.txt << 'EOF'
## Docker 注册表 SSL 证书管理摘要
1. 验证注册表的证书:
openssl s_client -connect registry.example.com:443 -showcerts </dev/null
2. 添加自定义证书到注册表:
sudo mkdir -p /etc/docker/certs.d/registry.example.com:5000
sudo cp registry.crt /etc/docker/certs.d/registry.example.com:5000/ca.crt
sudo systemctl restart docker
3. 配置不安全的注册表(仅用于开发):
添加到 /etc/docker/daemon.json:
{ "insecure-registries": ["registry.example.com:5000"] }
sudo systemctl restart docker
4. 定期检查到期日期:
openssl x509 -in certificate.crt -noout -dates
5. 自动化证书监控:
创建并定期运行脚本以检查证书
EOF
cat ssl_management_summary.txt
此摘要用作与 Docker 注册表 SSL 证书相关的最常见操作的快速参考。
在这个实验中,你学习了如何验证和管理 Docker 注册表的 SSL 证书。你现在拥有以下知识和工具:
这些技能对于维护安全的 Docker 环境至关重要,尤其是在安全至上的生产环境中。通过定期验证和正确管理你的 Docker 注册表 SSL 证书,你可以防止安全漏洞并确保容器化应用程序的顺利运行。