离线环境部署Docker私有镜像仓库:registry.tar.gz实战与避坑指南

📅 发布时间:2026/10/12 16:13:18
离线环境部署Docker私有镜像仓库:registry.tar.gz实战与避坑指南
简介本资源为面向内网离线环境的Docker Registry镜像包主要解决服务器无法连接外网时私有仓库难以搭建的问题适合运维人员、后端开发者及需要隔离网络部署容器镜像的团队使用。压缩包共包含18个文件以json元数据、tar层文件、version版本标识及repositories索引为主整体约25.15MB结构符合Docker镜像分层存储规范可直接导入本地Registry服务。目前已有436人学习下载说明其在离线部署场景中具有一定参考价值。借助该镜像包读者能够在内网快速完成私有仓库的初始化与镜像推送避免因外网受限而中断容器化流程同时可结合分层文件理解镜像的存储与索引机制为后续镜像迁移、备份及仓库维护提供可复用的基础素材。1. 从 registry.tar.gz 说起离线环境里把镜像仓库搬回家如果你在机房、产线或者客户内网里干过交付大概率遇到过这种场面服务器没有外网Docker 镜像拉不下来docker pull转圈转到天荒地老最后甩给你一个connection timed out。这时候手里如果有一个registry.tar.gz事情就完全不一样了——它本质上是把一整套私有镜像仓库Registry打包成了一个压缩包解压、加载、起容器几分钟内就能在内网里跑起一个能推能拉的镜像仓库。这份资源解决的核心问题就一个在没有外网的环境里让 Docker 镜像的存储和分发重新跑起来。它适合三类人一是做离线交付的运维和交付工程师二是需要在隔离网络里搭 CI/CD 的开发者三是想在自己机器上研究 Registry 行为、不想依赖公网的技术人。下面我从这个包怎么用、参数怎么调、坑在哪一步步拆开讲。2. 拆包与加载registry.tar.gz 里到底装了什么拿到一个registry.tar.gz第一反应不应该是直接解压而是先看清楚它的结构。不同来源的包内容差别很大有的里面是一个完整的registry二进制加配置文件有的是一份docker save出来的镜像 tar 包还有的是把镜像 tar 再套一层 gzip。搞错了结构后面的命令全是白费。2.1 先看包结构再动手我一般会先用tar -tzf列出内容不急着解压。这一步能帮你判断这个包属于哪种类型# 只列出压缩包内容不解压先看结构 tar -tzf registry.tar.gz | head -30 # 常见输出一直接是镜像 tar # registry.tar # # 常见输出二带目录结构 # registry/ # registry/registry # registry/config.yml如果输出里只有一个.tar文件那它多半是docker save导出的镜像归档需要先解压再docker load。如果输出里有config.yml和二进制文件那它是一套可以直接运行的 Registry 程序走的是另一条路。这两种情况后面的处理方式完全不同所以第一步的判断不能省。提示head -30只是看开头如果包很大别用tar -tzf反复扫扫一次把结果存到文件里后面查起来快。2.2 镜像归档型docker load 的正确姿势假设确认里面是镜像 tar标准流程是解压再加载。这里有个细节很多人忽略docker load加载出来的镜像名和标签取决于打包时docker save用的名字不是你想改就能在 load 阶段改的。# 解压出内层 tar tar -xzf registry.tar.gz # 加载镜像到本地 Docker docker load -i registry.tar # 查看加载结果确认 REPOSITORY 和 TAG docker images | grep registrydocker load -i的-i指定输入文件加载完成后用docker images核对。如果加载出来的镜像名是registry:2或registry:latest说明这是一个标准的 Registry 镜像。如果名字是一串none那说明打包时镜像没有打标签需要手动docker tag补一个名字再用。参数上唯一需要留意的是docker load不支持在加载时重命名所以标签管理要在 load 之后做。另外如果内层 tar 很大几个 GB加载过程会占满磁盘 IO别在业务高峰期干这事。2.3 程序目录型直接跑二进制还是起容器如果包里是registry二进制加config.yml你有两个选择直接跑二进制或者把它做成镜像再起容器。直接跑二进制最省事适合临时用# 解压 tar -xzf registry.tar.gz # 前台启动方便看日志 ./registry serve config.ymlserve是 Registry 的子命令后面跟配置文件路径。前台启动的好处是日志直接打在终端上排错方便确认没问题后再用nohup或 systemd 托管。如果选择容器方式就需要先写 Dockerfile 把二进制和配置打进去多一步但更干净。两种方式没有绝对优劣临时验证用二进制长期运行用容器。3. 把 Registry 跑起来配置、存储与端口映射包能加载只是第一步真正让 Registry 可用靠的是配置文件里的几个关键参数。很多人跑起来之后发现推不上去、拉不下来八成是config.yml没配对。这一章把配置拆开讲每个参数说清楚它管什么。3.1 config.yml 里必须搞懂的四个字段一份典型的 Registry 配置长这样我把它精简到最核心的部分version: 0.1 storage: filesystem: rootdirectory: /var/lib/registry delete: enabled: true http: addr: :5000 headers: X-Content-Type-Options: [nosniff]version是配置格式版本固定写0.1别改。storage.filesystem.rootdirectory是镜像数据实际落盘的位置这个目录会随着推送的镜像越来越多而膨胀务必挂到大盘上。storage.delete.enabled设为true才允许删除镜像默认是关的不打开的话你删了标签空间也不会释放。http.addr是监听地址:5000表示监听所有网卡的 5000 端口。注意delete.enabled打开只是允许删除操作真正回收空间还需要跑垃圾回收garbage-collect这两步是分开的后面会讲。3.2 用容器方式启动并挂载数据卷如果走容器路线启动命令里最关键的是数据卷映射。镜像数据不能放在容器内部否则容器一删全没了# 启动 Registry 容器 docker run -d \ --name registry \ --restartalways \ -p 5000:5000 \ -v /data/registry:/var/lib/registry \ -v /data/registry-config/config.yml:/etc/docker/registry/config.yml \ registry:2-p 5000:5000把容器端口映射到宿主机内网其他机器通过宿主机IP:5000访问。-v /data/registry:/var/lib/registry是数据持久化的关键左边是宿主机目录右边要和配置文件里的rootdirectory一致。--restartalways保证宿主机重启后 Registry 自动起来离线环境里没人盯着这个参数很实用。启动后用docker ps确认容器状态再用curl探一下# 探测 Registry 是否存活 curl -s http://127.0.0.1:5000/v2/ # 正常返回{}返回{}说明 Registry 的 API 正常响应了。如果返回连接拒绝检查容器是否真的起来了如果返回 404检查端口映射对不对。3.3 客户端配置让 docker 信任这个仓库Registry 默认走 HTTP而 Docker 客户端默认要求 HTTPS所以直接推会报http: server gave HTTP response to HTTPS client。解决办法是在客户端的daemon.json里把它加进信任列表{ insecure-registries: [192.168.1.100:5000] }把192.168.1.100换成你 Registry 所在机器的实际 IP。改完重启 Docker 服务# 重启 Docker 使配置生效 systemctl restart docker这一步是离线环境里最容易翻车的地方。很多人 Registry 起得好好的一推就报错就是忘了配insecure-registries。配完之后打标签、推送、拉取就顺了# 给本地镜像打上私有仓库标签 docker tag nginx:latest 192.168.1.100:5000/nginx:latest # 推送到私有仓库 docker push 192.168.1.100:5000/nginx:latest # 从私有仓库拉取 docker pull 192.168.1.100:5000/nginx:latest标签格式是仓库地址/镜像名:标签缺一不可。推送成功后数据就落在/data/registry下面了可以用du -sh看增长情况。4. 避坑与排查Registry 离线部署的五个血泪经验这一章是我自己踩过的坑每条都按「现象 → 原因 → 解决」写。离线环境没有外网兜底出了问题只能自己扛所以这些经验比命令本身更值钱。4.1 推送报 413请求体过大现象小镜像推得上去大镜像推到一半报413 Request Entity Too Large。原因如果 Registry 前面挂了 Nginx 做反向代理Nginx 默认的client_max_body_size是 1MB超过就拦。即使没挂 Nginx某些版本的 Registry 也有默认限制。解决在 Nginx 配置里加client_max_body_size 0;0 表示不限制重启 Nginx。如果没挂代理检查 Registry 配置里有没有maxuploadsize之类的限制项。4.2 删除镜像后空间不释放现象用 API 删了镜像docker images里也没了但/data/registry目录大小纹丝不动。原因Registry 的删除是「标记删除」blob 数据还在磁盘上需要手动跑垃圾回收才能真删。解决先确保delete.enabled: true然后停掉 Registry或进入容器执行# 进入容器执行垃圾回收 registry garbage-collect /etc/docker/registry/config.yml回收完成后再启动 Registry。注意回收期间不要有推送操作否则可能误删正在使用的层。4.3 重启后镜像全没了现象容器重启一次之前推的镜像全消失/v2/_catalog返回空。原因启动容器时没挂数据卷或者挂载路径和rootdirectory不一致数据写在了容器内部容器一重建就丢。解决docker inspect registry看Mounts字段确认/var/lib/registry确实映射到了宿主机目录。没映射的话停容器、加-v重新起之前的数据如果还在容器里可以docker cp出来。4.4 客户端报证书错误现象docker push报x509: certificate signed by unknown authority或server gave HTTP response to HTTPS client。原因客户端没把 Registry 加入insecure-registries或者加了但没重启 Docker。解决确认daemon.json里的 IP 和端口与实际一致改完必须systemctl restart docker。如果用了域名域名也要加进去。改完用docker info看Insecure Registries列表里有没有你的地址。4.5 磁盘写满导致 Registry 假死现象Registry 容器还在跑但推送一直卡住日志里报no space left on device。原因rootdirectory所在分区被镜像数据撑满Registry 无法写入新数据。解决先清理无用镜像并跑垃圾回收长期方案是把数据目录迁到大容量分区或者加监控告警。离线环境里磁盘满了没人通知等发现时业务已经停了所以提前规划容量比事后救火重要。5. 进阶技巧用 API 管理仓库和验证数据完整性Registry 跑起来只是开始真正让它好用得会通过 API 查目录、删镜像、验证数据。这一章讲几个我常用的操作都是命令行能直接抄的。5.1 用 _catalog 接口列出所有仓库Registry 提供了 REST API最常用的是_catalog能列出所有仓库名# 列出所有仓库 curl -s http://192.168.1.100:5000/v2/_catalog # 返回示例{repositories:[nginx,redis,myapp]}如果仓库多可以加分页参数?n10限制返回数量。这个接口在排查「镜像到底推没推上去」时特别有用比翻磁盘目录直观。5.2 查标签和删镜像知道仓库名后可以查它的标签列表# 列出某个仓库的所有标签 curl -s http://192.168.1.100:5000/v2/nginx/tags/list # 返回示例{name:nginx,tags:[latest,1.21]}删除某个标签对应的镜像需要先拿到 digest# 获取镜像的 digest curl -s -I \ -H Accept: application/vnd.docker.distribution.manifest.v2json \ http://192.168.1.100:5000/v2/nginx/manifests/latest \ | grep Docker-Content-Digest # 用 digest 删除 curl -X DELETE http://192.168.1.100:5000/v2/nginx/manifests/sha256:xxxx-I只取响应头Docker-Content-Digest就是 digest 值。删除后记得跑垃圾回收否则空间不释放。这套 API 操作在写自动化脚本时很有用比如定时清理过期镜像。5.3 验证数据完整性离线环境里数据损坏是隐性风险我一般会定期验证。最简单的方式是拉一个镜像下来和源端对比 digest# 拉取镜像并查看 digest docker pull 192.168.1.100:5000/nginx:latest docker inspect --format{{index .RepoDigests 0}} 192.168.1.100:5000/nginx:latest把输出的 digest 和推送时的 digest 对比一致说明数据没坏。如果对不上说明存储层可能出了问题需要检查磁盘健康状态。这个习惯帮我提前发现过一次磁盘坏道避免了交付现场翻车。从那以后我每次部署完 Registry都会强制走一遍「推一个测试镜像 → 拉下来 → 对比 digest → 删掉测试镜像 → 跑垃圾回收」的完整流程确认整条链路通了才交给业务用。希望这些经验帮到你少走几个我踩过的坑。本文还有配套的精品资源点击获取