七千二百袋水泥
七千二百袋水泥
Published on 2025-10-25 / 3 Visits

全面指南:使用VPS和Nginx搭建私有Docker镜像仓库,解决SSL证书配置难题并加速镜像拉取

最近不少朋友向我咨询:我日常使用大量Docker镜像,是如何顺利拉取下来的?毕竟Docker Hub在国内访问受限,这个问题确实困扰了许多开发者。

实际上,有多种方法可以解决这个难题:

  • 方法一:借助公共镜像源

    这种方法操作简单,只需在搜索引擎中输入“Docker镜像源”即可找到众多可用资源。网络上有许多热心开发者分享了可直接使用的镜像仓库地址或加速节点,他们的无私奉献精神值得敬佩。

  • 方法二:利用Cloudflare Workers搭建代理

    这种方法得益于Cloudflare提供的免费Workers服务,可以自行构建代理加速节点。

    但需要满足一定条件:用户必须拥有自己的顶级域名,并且该域名需托管在Cloudflare平台上。

    尽管这种方法在技术社区中较为流行,但由于存在频率和速度限制,大多数用户不会公开分享自己搭建的代理源,通常仅在小范围内使用,以避免因流量过大导致服务被封禁。

    值得一提的是,我个人也长期采用这种方法来加速镜像拉取。

  • 方法三:使用境外VPS基于Nginx反向代理Docker Hub

    这种方法优势明显,通过自有VPS搭建服务,稳定性和可靠性更高。镜像拉取速度完全取决于VPS的带宽性能。

    当然,这种方法也有较高门槛:需要具备境外VPS资源和域名。


前几天有朋友再次提出这个问题时,我深入考虑了第三种方案。恰巧我手头有域名和韩国VPS资源,于是决定亲自实践一番。

不过,这篇文章未详细说明如何获取SSL证书。基于此,我进行了进一步探索:

  1. 使用腾讯DNSPod提供的免费SSL证书
  2. 生成自签名SSL证书

方法一:配置DNSPod免费SSL证书

目前大多数域名托管服务商都提供免费的SSL证书服务,只要域名托管在其平台上即可申请,例如阿里云和腾讯云。但需要注意的是,这些免费证书的有效期通常仅为三个月。

每三个月就需要重新申请证书,这个过程较为繁琐。因此,我们尝试第二种方法。

方法二:生成自签名SSL证书

首先通过脚本生成自签名证书。

重要提示:不能使用简单方法生成证书,因为Docker基于Golang实现,在拉取镜像时,Golang会验证证书中的SAN(Subject Alternative Name)信息。

如果证书不包含SAN信息,在执行docker pull命令时会报错:x509: certificate relies on legacy Common Name field, use SANs or temporarily enable Common Name matching with GODEBUG=x509ignoreCN=0。因此,建议使用以下脚本生成证书。

#!/bin/bash  
  
[-z "${1}"]&&{  
echo "usage: $0 domain"  
exit 1  
}  
  
cd $(dirname $0)  
  
domain="${1}"  
gendir="${domain}/$(date +'%Y%m%d')"  
mkdir -p ${gendir}2>/dev/null  
  
privkey="${gendir}/${domain}.key"# 私钥  
srvcsr="${gendir}/${domain}.csr"# 签发文件  
srvcrt="${gendir}/${domain}.crt"# crt证书  
srvpem="${gendir}/${domain}.pem"# pem证书  
  
openssl genrsa -out ${privkey}2048  
cat >${domain}/req.conf <<EOF  
[ req ]  
default_bits       =2048  
default_md         = sha256  
prompt             = no  
distinguished_name = req_distinguished_name  
req_extensions     = req_ext  
  
[ req_distinguished_name ]  
countryName               = CN  
stateOrProvinceName       =Beijing  
localityName             =Beijing  
organizationName         =ExampleInc  
commonName               = ${domain}  
  
[ req_ext ]  
subjectAltName =@alt_names  
  
[ alt_names ]  
DNS.1= ${domain}  
EOF  
  
openssl req -new -key ${privkey} -out ${srvcsr} -config ${domain}/req.conf   
openssl x509 -req -days 3650 -in ${srvcsr} -signkey ${privkey} -out ${srvcrt} -extensions req_ext -extfile ${domain}/req.conf  
  
cat ${privkey} ${srvcrt} >${srvpem}  
chmod 600 ${srvpem}  
ls -l ${gendir}/*

将生成的.pem和.key文件替换到Nginx配置和SSL目录下,然后重启Nginx服务:/usr/sbin/nginx -t && /usr/sbin/nginx -s reload

此时如果执行docker pull命令,可能会遇到错误:x509: certificate signed by unknown authority。这个错误表示证书未被系统信任,出于安全考虑被拒绝。

解决方法如下:

  • 方案一:明确告知Docker连接的是可信任的私有仓库
# cat /etc/docker/daemon.json   
## 添加以下配置  
{  
  "insecure-registries": [  
    "你的域名"  // 私有仓库地址,请替换为实际使用的域名  
  ]  
}  
## 然后重启Docker服务  
sudo systemctl restart docker
  • 方案二:将生成的证书添加到系统可信证书列表
sudo cp myca.crt /etc/pki/ca-trust/source/anchors/  ## 将生成的证书复制到指定目录  
sudo update-ca-trust extract  ## 更新可信证书数据库  
## 注意:不同操作系统的目录和操作方法可能有所差异,请根据实际情况调整
  • 方案三:在NAS提供的Docker可视化管理工具中添加新创建的镜像源,并务必勾选“信任证书”选项。

根据实际测试,目前已知群晖和威联通支持此选项,而飞牛和极空间暂不支持。

完成以上配置后,您就可以顺畅地使用Docker了。这种方法不仅解决了镜像拉取问题,还提供了更高的自定义灵活性。