局域网内部署 Docker Registry(推荐)

发布时间 - 2026-01-11 01:16:24    点击率:

在局域网内部署 Docker Registry 可以极大的提升平时 pull、push 镜像的速度,从而缩短自动化操作的过程。同时也可以缓解带宽不足的问题,真是一举多得。本文将从创建单机的 Docker Registry 开始,逐步完成局域网内可用的 Docker Registry 的创建,并重点解释如何使用 IP 地址访问 Registry 的方法。

注意,本文假设你已经在使用的 OS 中安装了 docker 引擎。

创建本机使用的 Docker Registry

这是一个非常简单的过程,简单到只需要运行一个 docker 容器就可以了:

$ docker run -d -p 5000:5000 --restart=always --name registry \
-v `pwd`/registry:/var/lib/registry \
registry:2

查看一下 5000 端口是否已被监听:

看起来还不错,让我们向本地的 Registry 中推送一个镜像试试。

先找个镜像,打上自己的 tag:

$ docker pull ubuntu
$ docker tag ubuntu localhost:5000/myubuntu:20170520

从上图我们可以看到,两个镜像完全是一样的,只不过我们创建的 tag 名称不一样而已。

接下来把镜像 push 到本地的 Registry 中:

$ docker push localhost:5000/myubuntu:20170520

上图显示 push 操作成功了,那再看看文件系统发生了什么变化:

在我们挂载的 ~/registry 目录的子目录中出现了保存镜像 myubuntu 的目录,在这个目录下保存了镜像相关的数据。

最后我们看看能不能从自己的库中 pull 镜像。先把本地的镜像 localhost:5000/myubuntu:20170520 删除掉:

$ docker rmi localhost:5000/myubuntu:20170520

然后从本地的库中 pull 镜像:

$ docker pull localhost:5000/myubuntu:20170520

是不是 pull 操作已经成功啦!

创建局域网内可用的 Docker Registry

前面创建的 Registry 可以在局域网内使用吗?我们来做个试验。

运行 Registry 的机器 IP 为:192.168.171.156,我们在局域网中的另一台机器上创建 tag 并执行推送命令:

推送失败了!原因是为了保证安全,跨机的镜像推送操作默认采用的都是 https 协议。也就是说,为了在局域网内使用 Docker Registry, 我们必须配置 https 版的 Registry 服务器。

选择通过 IP 地址访问 registry

由于种种原因,笔者无法为这台 Docker Registry Server 提供一个有效的域名。好在它的 IP 地址是固定的,因此决定通过 IP 地址来访问这台 Registry 服务器。假设这台机器的 IP 地址为:10.32.2.140,下面的描述都以此 IP 地址为例。

创建自签名的证书

既然是在局域网中使用,因此不会大动干戈的去购买 https 证书,自己生成一个自签名的就足够了。但这也存在一个缺点,就是需要在作为客户端的 docker daemon 中安装这个根证书,本文的稍后部分会介绍这一步骤。

在 ubuntu 系统中,下面的命令会在 dcerts 目录下生成秘钥和自签名的证书:

openssl req \
  -newkey rsa:4096 -nodes -sha256 \
  -keyout dcerts/domain.key \
  -x509 -days 356 \
  -out dcerts/domain.crt

注意,在执行此命令前需要在当前目录下创建 dcerts 目录。此命令的细节本文就不解释了,有兴趣的同学去查 openssl 命令的帮助文档。

生成证书时,openssl 要求我们输入相关的信息。比如地域和公司、部门的信息。比较重要的是 Common Name,如果你是要为某个域名生成证书,那么这里就应该是你的域名。我们使用的是 IP 地址,所以我就想当然的把 IP 地址放在了这里。很遗憾的是这并不正确!如果拿此时生成的证书去配置 Docker Registry,我们将无法完成 pull/push 操作。配置的 Registry 根本无法在局域网中使用。

此处是一个很隐晦的 openssl 配置问题,当我们使用 IP 地址作为访问服务器的名称时就会碰到。解决的方法也很简单,就是在生成证书的配置文件中指定 subjectAltName 。打开文件 /etc/ssl/openssl.cnf,在 [v3_ca] 节点添加配置项:

subjectAltName = IP:10.32.2.140

保存并退出,然后重新执行上面生成证书的命令。

运行 https 版的 Registry

有了前面创建的证书,我们就可以运行新版的 Registry 了:

$ docker run -d -p 5000:5000 \
  --restart=always \
  --name registry \
  -v `pwd`/dstorage:/var/lib/registry \
  -v `pwd`/dcerts:/certs \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
  registry:2

命令中我们把证书所在的目挂载到了容器的 /certs 目录。然后分别指定了容器的环境变量 REGISTRY_HTTP_TLS_CERTIFICATE 和 REGISTRY_HTTP_TLS_KEY,这两个环境变量会引用我们常见的秘钥文件和证书文件。

好了,到目前为止新版的 Docker Registry 已经可以提供服务了。

在 client 端设置根证书

为了快速、方便和省钱,我们没有去购买商业版的证书。这种方式的弊端是:必须把我们生成的根证书安装到每一个需要访问 Registry 服务器的客户端上。具体做法如下:

把前面生成的证书文件 dcerts/domain.crt 复制到需要访问 Registry 服务器的机器上。放到目录 /etc/docker/certs.d/10.32.2.140:5000/ 中,并重命名为 ca.crt。当然这个目录需要你自己创建。最后重新启动 docker 服务:

$ sudo systemctl restart docker.service    // 不同的系统重启服务的命令可能不一样。

终于大功告成了,让我们往 Registry 中推送一个镜像吧:

看,redis:3.2 已经被 tag 为 10.32.2.140:5000/myredis:20170520,并推送到了局域网中的 Docker Registry Server 中。
为了验明正身,我们还是到 10.32.2.140 上去看一下文件存储的状态:

从这张图中我们可以看到,myredis:20170520 真的已经被 Registry 保存到文件系统中了。

总结

由于安全性的考虑,配置局域网内可用的 Docker Registry 稍微有点麻烦。尤其是使用 IP 地址的配置方式,需要配置证书的 subjectAltName 才能正常工作。但完成配置后,使用局域网内的 Registry 还是很爽的。希望本文对有类似需求的朋友们有所帮助。


# docker  # registry  # 详解docker国内镜像拉取和镜像加速registry-mirrors配置修改  # 详解Docker Registry之删除镜像、垃圾回收  # Docker Registry 私有仓库搭建详细步骤  # 搭建一个私有的Docker registry教程  # 镜像  # 网内  # 的是  # 自己的  # 这台  # 让我们  # 网中  # 可以看到  # 目录下  # 文件系统  # 就可以  # 上图  # 库中  # 客户端  # 都是  # 是一个  # 验明正身  # 这一  # 是在  # 好了 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel如何编写单元测试和功能测试?(PHPUnit示例)  标题:Vue + Vuex 项目中正确使用 JWT 进行身份认证的实践指南  Laravel如何构建RESTful API_Laravel标准化API接口开发指南  Laravel怎么使用Collection集合方法_Laravel数组操作高级函数pluck与map【手册】  Laravel的契約(Contracts)是什么_深入理解Laravel Contracts与依赖倒置  详解Android——蓝牙技术 带你实现终端间数据传输  Laravel怎么实现API接口鉴权_Laravel Sanctum令牌生成与请求验证【教程】  如何快速搭建高效香港服务器网站?  Laravel如何监控和管理失败的队列任务_Laravel失败任务处理与监控  jQuery validate插件功能与用法详解  Laravel请求验证怎么写_Laravel Validator自定义表单验证规则教程  如何用PHP工具快速搭建高效网站?  UC浏览器如何设置启动页 UC浏览器启动页设置方法  如何为不同团队 ID 动态生成多个“认领值班”按钮  Laravel怎么实现微信登录_Laravel Socialite第三方登录集成  Laravel Blade组件怎么用_Laravel可复用视图组件的创建与使用  Mybatis 中的insertOrUpdate操作  如何确保西部建站助手FTP传输的安全性?  javascript中的数组方法有哪些_如何利用数组方法简化数据处理  如何基于云服务器快速搭建网站及云盘系统?  jQuery 常见小例汇总  Laravel如何生成URL和重定向?(路由助手函数)  Laravel如何优雅地处理服务层_在Laravel中使用Service层和Repository层  Google浏览器为什么这么卡 Google浏览器提速优化设置步骤【方法】  Edge浏览器提示“由你的组织管理”怎么解决_去除浏览器托管提示【修复】  Java类加载基本过程详细介绍  专业型网站制作公司有哪些,我设计专业的,谁给推荐几个设计师兼职类的网站?  Laravel怎么实现验证码(Captcha)功能  Android仿QQ列表左滑删除操作  如何在香港免费服务器上快速搭建网站?  JavaScript 输出显示内容(document.write、alert、innerHTML、console.log)  免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?  Thinkphp 中 distinct 的用法解析  如何批量查询域名的建站时间记录?  公司网站制作需要多少钱,找人做公司网站需要多少钱?  详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)  如何在VPS电脑上快速搭建网站?  Laravel如何升级到最新版本?(升级指南和步骤)  DeepSeek是免费使用的吗 DeepSeek收费模式与Pro版本功能详解  Claude怎样写结构化提示词_Claude结构化提示词写法【教程】  Laravel API路由如何设计_Laravel构建RESTful API的路由最佳实践  Laravel数据库迁移怎么用_Laravel Migration管理数据库结构的正确姿势  如何在阿里云虚拟主机上快速搭建个人网站?  Laravel中的Facade(门面)到底是什么原理  html5的keygen标签为什么废弃_替代方案说明【解答】  Python正则表达式进阶教程_复杂匹配与分组替换解析  使用Dockerfile构建java web环境  微信小程序 闭包写法详细介绍  Laravel如何获取当前登录用户信息_Laravel Auth门面使用与Session用户读取【技巧】  如何在云虚拟主机上快速搭建个人网站?