为什么要折腾一个私有的 Docker 镜像仓库?
很多朋友在玩 Docker 的时候,都会遇到几个让人抓狂的场景:明明服务器带宽很足,但拉取某个热门镜像时速度却像蜗牛爬,甚至直接超时失败;公司内部的项目代码和镜像,总是担心放在公共仓库里不够安全;又或者团队协作时,希望有一个统一的镜像管理中心,而不是各拉各的、版本混乱。
与其每次都在公共仓库里“抢资源”,不如自己动手搭建一个专属的私有容器服务库。这不仅是技术实力的体现,更是解决实际生产问题的关键一步。今天,笔者就把这其中的门道和实操步骤,掰开揉碎了讲给你听。
第一步:准备工作与基础环境选型
在开始敲命令之前,我们得先明确一个原则:私有镜像仓库(Registry)本身是一个非常轻量的服务,它对硬件的要求并不高。如果你只是个人使用或者小团队内部使用,一台 1核2G 的云服务器就绰绰有余了。
不过,这并不代表你可以随便买一台廉价机器。因为镜像的存储和传输非常依赖磁盘 I/O 和网络带宽。如果你打算长期使用,笔者强烈建议你选择一款拥有高性能 SSD 云硬盘和高带宽的靠谱云服务器。毕竟,网络质量直接决定了你每次 docker pull 的体验。如果你对带宽的选择拿捏不准,不妨先看看我们之前做过的深度拆解:云服务器网卡带宽到底怎么选?全网拉测性能指标的一次深度拆解,避免在硬件选型上踩坑。
另外,为了后续访问方便,建议准备一个正规的域名,并提前做好 DNS 解析。这比直接用 IP + 端口要专业得多,也方便配置 HTTPS 证书。
第二步:核心组件解析,Registry 与 Harbor 怎么选?
目前搭建私有仓库,市面上主流的有两个方案:
| 对比项 | Docker Registry(轻量级) | Harbor(企业级) |
|---|---|---|
| 部署复杂度 | 极低,一条命令即可 | 较高,依赖组件多(如 PostgreSQL、Redis) |
| 功能特性 | 仅提供基本的镜像存储与拉取 | 支持 Web UI、权限管理(RBAC)、镜像复制、漏洞扫描 |
| 适用场景 | 个人开发者、极简主义 | 团队协作、企业生产环境 |
如果你只是自己用,追求极致的简单和资源占用低,那么Docker Registry 绝对是首选。但如果你需要管理多个用户,或者希望有一个可视化的管理界面,那么 Harbor 会更适合你。本文我们以最通用的 Docker Registry 为例,因为它最基础,也最能让你理解底层原理。
第三步:实战部署,基于 Docker 容器化搭建
既然我们讲的是“如何使用 Docker 镜像仓库搭建”,那么自然要用 Docker 的方式去运行它。这里我们直接使用官方镜像 registry:2。
3.1 快速启动一个带鉴权的 Registry
直接裸奔的 Registry 是不安全的,任何人都能往里面推镜像。我们必须加上 HTTP Basic 认证。首先,创建存放密码的目录并生成强密码文件:
mkdir -p /opt/registry/auth
# 使用 htpasswd 生成加密密码(需要安装 httpd-tools)
htpasswd -Bbn your_username your_strong_password > /opt/registry/auth/htpasswd
接下来,启动容器,并将数据目录挂载到宿主机,同时映射端口:
docker run -d \
--name private_registry \
--restart=always \
-p 5000:5000 \
-v /opt/registry/data:/var/lib/registry \
-v /opt/registry/auth:/auth \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \
-e "REGISTRY_STORAGE_DELETE_ENABLED=true" \
registry:2
这里特别提一下 REGISTRY_STORAGE_DELETE_ENABLED=true 这个参数,如果不开启,你在 API 层面删除镜像后,磁盘空间并不会释放,这是一个非常实用的避坑点。
3.2 配置 Docker 客户端信任(HTTP 与 HTTPS)
如果你的域名没有配置 SSL 证书,Docker 默认是不允许通过 HTTP 推送镜像的。你需要修改客户端的 daemon.json 文件,将你的仓库地址加入 insecure-registries 列表中:
# 编辑 /etc/docker/daemon.json(Linux)或使用 Docker Desktop 设置(Mac/Win)
{
"insecure-registries": ["your.domain.com:5000"]
}
修改完成后,务必重启 Docker 服务:systemctl restart docker。
3.3 登录并推送你的第一个镜像
现在,我们来测试一下整个链路是否通畅。首先登录你的私有仓库:
docker login your.domain.com:5000 -u your_username -p your_strong_password
然后,给本地已有的镜像打个标签,再推上去:
docker tag nginx:latest your.domain.com:5000/my-nginx:v1.0
docker push your.domain.com:5000/my-nginx:v1.0
看到 latest digest 字样,就说明推送成功了。以后在任何一台连上该仓库的机器上,都可以通过 docker pull your.domain.com:5000/my-nginx:v1.0 快速拉取,速度飞快。
第四步:进阶优化,反向代理与 HTTPS 安全加固
裸奔的 5000 端口虽然能用,但不够优雅,也不安全。我们强烈建议使用 Nginx 反向代理,并签一个免费的 SSL 证书,这样既能加密传输,又能直接用 443 端口访问,看起来就像是一个正规的 SaaS 服务。
关于如何配置 Nginx 以及申请免费的 SSL 证书,我们之前写过一篇非常详细的实战文章,涵盖了从裸机到 HTTPS 的全过程:从裸机到HTTPS:Nginx反向代理配置与免费SSL证书签发,手把手教你搞定。你可以参考那篇文章,将 5000 端口代理到你的域名下,并开启 HTTP/2 支持。
在 Nginx 配置中,需要特别注意添加一段特殊的配置,以保证 Docker Registry 的 API 能正常工作:
location /v2/ {
# 核心配置:禁用对请求体的缓冲,并设置超时时间
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 0; # 允许上传大镜像
chunked_transfer_encoding on;
}
第五步:安全加固与日常维护
搭建完成只是开始,安全运维才是重头戏。
- 定期备份:镜像数据是最宝贵的资产,建议定期将
/opt/registry/data目录备份到异地存储。 - 启用防火墙:只放行 443 端口,关闭宿主机上的 5000 端口外部访问,避免绕过 Nginx 直接攻击。
- 清理无用镜像:虽然我们开启了删除功能,但定期使用
registry:2的 GC(垃圾回收)命令,能有效整理存储碎片。
另外,如果你在配置过程中,发现服务器经常被暴力扫描,请务必检查一下你的 SSH 登录方式。光靠密码登录在公网环境下非常危险,强烈建议你参考我们这篇安全加固的文章,把密码登录彻底关掉:黑客天天扫你的服务器?关掉密码登录,用 SSH 密钥对一把锁死暴力破解。
写在最后的一些建议
至此,一个属于你自己的私有容器服务库就已经稳稳地跑起来了。你会发现,无论是 CI/CD 的构建产物存储,还是个人项目的版本管理,都变得井井有条。
最后,笔者想多说一句。虽然搭建私有仓库能解决隐私和速度问题,但如果你想要一个更完整的家庭服务器或团队协作方案,不妨把镜像仓库与反向代理、DNS 拦截等结合起来。我们之前写过一篇关于 Docker 部署 AdGuard Home 与 Nginx Proxy Manager:从 DNS 拦截到反向代理的一站式家庭服务器方案 的文章,里面提到的 Nginx Proxy Manager 能让你用图形化的方式管理所有子域名转发,配合你的私有仓库使用,体验会再上一个台阶。
技术之路,在于折腾。希望这篇教程能帮你省下一些不必要的麻烦,让你在容器化的道路上走得更顺畅。