共计 767 个字符,预计需要花费 2 分钟才能阅读完成。
文章目录 [显示]
你有没有遇到过这样的场景:公司开发了一套内部系统,打好了 Docker 镜像,然后问题来了——这镜像往哪放?推到 Docker Hub?老板第一个不答应,公司代码怎么能放公网。放本地?那隔壁工位的同事怎么拉取?更别说生产环境部署了,总不能每次都用 U 盘拷吧。
这就是私有镜像仓库要解决的问题。它就像公司内部的 " 快递驿站 ",所有镜像统一存放、统一管理,谁要用谁来取,安全又高效。
本文你将学到
- Docker Registry 的工作原理和架构
- 5 分钟搭建一个私有镜像仓库
- 为 Registry 配置 HTTPS 和访问认证
- Harbor 企业级镜像仓库的部署和使用
- 镜像推送、拉取、删除的完整操作流程
- 生产环境的安全加固方案
阅读时间:10 分钟 | 实操时间:30 分钟 | 难度等级:中级
为什么需要私有镜像仓库
在聊怎么搭建之前,先说说为什么要搞这个东西。
用生活中的例子来类比:Docker Hub 就像淘宝,什么都有,但你不可能把公司的机密产品挂上去卖。私有镜像仓库就是公司的内部仓库,东西只在内部流通。
具体来说,私有仓库解决了这几个痛点:
安全性 :代码和配置不出内网,满足合规要求。金融、医疗、政府行业,这是硬性要求。
速度 :从内网拉镜像,速度比从公网快几十倍。特别是那些动辄几个 G 的镜像,内网几秒搞定,公网可能要等半天。
可控性 :谁能推、谁能拉、哪些镜像允许上生产,全都你说了算。
稳定性 :不依赖外网,Docker Hub 挂了也不影响你部署。
整体架构
先看看私有镜像仓库在整个开发流程中的位置:
开发者本机 私有仓库 生产服务器
+-----------+ docker push +-----------+ docker pull +-----------+
| | ---------------> | | -------------> | |
| Build | | Registry | | Deploy |
| 镜像 | | 存储镜像 | | 运行容器 |
| | <--------------- | | <------------- | |
+-----------+ docker pull +-----------+ docker push +-----------+
|
| Web UI (Harbor)
v
+-----------+
| 管理员 |
| 审核 / 管理 |
+-----------+
方案一:Docker Registry(轻量级)
Docker 官方提供了一个开源的镜像仓库实现,叫 Docker Registry。它就像一个 " 毛坯房 "——功能够用,但比较朴素,适合小团队或测试环境。
快速启动
一条命令就能跑起来:
docker run -d \
--name registry \
--restart always \
-p 5000:5000 \
-v /data/registry:/var/lib/registry \
registry:2
就这么简单,你已经有了一个私有镜像仓库。我们来验证一下:
curl http://localhost:5000/v2/_catalog
预期输出:
{"repositories":[]}
空的,因为还没推过镜像。接下来试试推一个。
推送镜像到私有仓库
假设你本地有一个 nginx 镜像,要推到私有仓库,需要先给它打个标签:
# 先拉一个测试镜像
docker pull nginx:alpine
# 打标签,格式:仓库地址 / 镜像名: 标签
docker tag nginx:alpine localhost:5000/my-nginx:v1
# 推送
docker push localhost:5000/my-nginx:v1
预期输出:
The push refers to repository [localhost:5000/my-nginx]
v1: digest: sha256:a1b2c3d4... size: 1568
再查一下仓库里有什么:
curl http://localhost:5000/v2/_catalog
预期输出:
{"repositories":["my-nginx"]}
镜像已经躺在私有仓库里了。
从私有仓库拉取镜像
在其他机器上(或者先删掉本地的),就可以从私有仓库拉取了:
# 先删掉本地的
docker rmi localhost:5000/my-nginx:v1
# 从私有仓库拉取
docker pull localhost:5000/my-nginx:v1
查看镜像标签列表
curl http://localhost:5000/v2/my-nginx/tags/list
预期输出:
{"name":"my-nginx","tags":["v1"]}
配置 HTTPS(生产环境必须)
刚才用的是 HTTP,在生产环境中这是不可接受的。就好比你把仓库大门敞开,谁都能进来搬东西。我们需要给它上把锁——HTTPS。
生成自签名证书
如果你有正式的 SSL 证书当然更好,这里先用自签名证书演示:
# 创建证书目录
mkdir -p /data/registry/certs
# 生成自签名证书(把 registry.example.com 换成你的域名或 IP)openssl req -newkey rsa:4096 -nodes -sha256 \
-keyout /data/registry/certs/domain.key \
-x509 -days 365 \
-out /data/registry/certs/domain.crt \
-subj "/CN=registry.example.com" \
-addext "subjectAltName=DNS:registry.example.com"
启动带 HTTPS 的 Registry
先停掉之前的容器,再用新配置启动:
docker rm -f registry
docker run -d \
--name registry \
--restart always \
-p 5000:5000 \
-v /data/registry/data:/var/lib/registry \
-v /data/registry/certs:/certs \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
registry:2
客户端信任证书
使用自签名证书时,Docker 客户端默认不信任,需要手动添加:
# 在每台需要访问仓库的机器上执行
mkdir -p /etc/docker/certs.d/registry.example.com:5000
cp /data/registry/certs/domain.crt \
/etc/docker/certs.d/registry.example.com:5000/ca.crt
# 重启 Docker
systemctl restart docker
配置访问认证
光有 HTTPS 还不够,还要控制谁能访问。我们用 HTTP Basic Auth 来实现。
创建密码文件
mkdir -p /data/registry/auth
# 创建用户(用户名: admin,会提示输入密码)docker run --rm --entrypoint htpasswd \
httpd:2 -Bbn admin yourpassword > /data/registry/auth/htpasswd
启动带认证的 Registry
docker rm -f registry
docker run -d \
--name registry \
--restart always \
-p 5000:5000 \
-v /data/registry/data:/var/lib/registry \
-v /data/registry/certs:/certs \
-v /data/registry/auth:/auth \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
-e REGISTRY_AUTH=htpasswd \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
registry:2
登录和使用
# 登录
docker login registry.example.com:5000
# 输入用户名和密码后,就可以正常推拉镜像了
docker push registry.example.com:5000/my-nginx:v1
方案二:Harbor(企业级)
Docker Registry 虽然能用,但它就像一个命令行工具——没有图形界面、没有权限管理、没有镜像扫描。如果你们公司有几十号开发人员,光靠 Registry 管理镜像,运维同学怕是要疯。
Harbor 就是来解决这个问题的。它是 VMware 开源的企业级镜像仓库,你可以把它理解为 " 精装修 " 的 Registry,自带 Web 管理界面、细粒度权限控制、镜像漏洞扫描、镜像签名等功能。
Harbor 的核心特性
Harbor 功能全景
+--------------------------------------------------+
| Web 管理界面 | 基于角色的访问控制 (RBAC) |
| 项目管理 | 管理员 / 开发者 / 访客 三种角色 |
+--------------------------------------------------+
| 镜像漏洞扫描 | 镜像复制(多仓库同步)|
| 自动扫描新镜像 | 支持主从 / 双主复制策略 |
+--------------------------------------------------+
| Webhook 通知 | 审计日志 |
| CI/CD 集成 | 记录所有操作,满足合规要求 |
+--------------------------------------------------+
| Helm Chart 仓库 | 垃圾回收 |
| 统一管理容器和 Chart| 自动清理无引用的镜像层 |
+--------------------------------------------------+
安装 Harbor
Harbor 依赖 Docker Compose,确保你的机器上已经安装了。
# 下载 Harbor 离线安装包(以 v2.11 为例)wget https://github.com/goharbor/harbor/releases/download/v2.11.0/harbor-offline-installer-v2.11.0.tgz
# 解压
tar xzvf harbor-offline-installer-v2.11.0.tgz
cd harbor
# 复制配置模板
cp harbor.yml.tmpl harbor.yml
修改配置文件
编辑 harbor.yml,主要改这几个地方:
# 访问地址
hostname: harbor.example.com
# HTTPS 配置
https:
port: 443
certificate: /data/harbor/certs/domain.crt
private_key: /data/harbor/certs/domain.key
# 管理员密码(首次登录后请立即修改)harbor_admin_password: Harbor12345
# 数据存储路径
data_volume: /data/harbor/data
执行安装
# 带镜像扫描组件一起安装
./install.sh --with-trivy
预期输出(最后几行):
✔ ----Harbor has been installed and started successfully.----
安装完成后,打开浏览器访问 https://harbor.example.com,用 admin 账号登录。
Harbor 日常操作
创建项目 :
在 Web 界面点击 " 新建项目 ",填写项目名称,比如 backend。可以设置为公开或私有。
推送镜像到 Harbor:
# 登录 Harbor
docker login harbor.example.com
# 打标签,格式:Harbor 地址 / 项目名 / 镜像名: 标签
docker tag my-app:latest harbor.example.com/backend/my-app:v1.0
# 推送
docker push harbor.example.com/backend/my-app:v1.0
权限管理 :
在项目设置中可以添加成员,并分配角色:
| 角色 | 权限 |
|---|---|
| 项目管理员 | 完全控制,包括成员管理 |
| 开发者 | 推送和拉取镜像 |
| 访客 | 只能拉取镜像 |
Harbor vs Docker Registry 对比
| 特性 | Docker Registry | Harbor |
|---|---|---|
| 安装复杂度 | 一条命令 | 需要 Docker Compose |
| Web 界面 | 无 | 有,功能丰富 |
| 权限管理 | 仅 Basic Auth | RBAC,细粒度控制 |
| 镜像扫描 | 无 | 内置 Trivy |
| 镜像复制 | 无 | 支持多种策略 |
| 审计日志 | 无 | 完整审计 |
| 适用场景 | 个人 / 小团队 | 中大型企业 |
常见问题 Q&A
Q1:推送镜像时报 "http: server gave HTTP response to HTTPS client" 怎么办?
这是因为 Docker 默认要求使用 HTTPS,但你的 Registry 用的是 HTTP。有两种解决办法:
方法一(推荐):给 Registry 配上 HTTPS,参考上文的证书配置。
方法二(仅限测试环境):在 Docker 客户端配置中添加不安全仓库:
# 编辑 /etc/docker/daemon.json
{"insecure-registries": ["your-registry:5000"]
}
# 重启 Docker
systemctl restart docker
Q2:镜像越来越多,磁盘快满了怎么办?
Docker Registry 删除镜像后并不会立即释放磁盘空间,需要执行垃圾回收:
# 进入 Registry 容器执行垃圾回收
docker exec registry bin/registry garbage-collect \
/etc/docker/registry/config.yml
Harbor 的话,可以在 Web 界面的 " 系统管理 - 垃圾回收 " 中配置定时清理任务,省心很多。
Q3:如何实现多机房镜像同步?
如果你有多个数据中心,可以用 Harbor 的镜像复制功能。在源 Harbor 中创建 " 复制规则 ",指定目标 Harbor 地址和触发条件(推送时自动同步 / 定时同步),Harbor 会自动处理增量同步,不用你写脚本。
小结
今天我们学习了两种私有镜像仓库方案:
Docker Registry 适合个人开发者和小团队,一条命令就能搞定。但它功能比较基础,就像一个 " 毛坯房 ",能住但不太舒服。
Harbor 是企业级方案,功能全面——Web 界面、权限管理、镜像扫描、审计日志一应俱全。如果你们公司有正式的 DevOps 需求,强烈推荐 Harbor。
无论选哪个方案,生产环境必须做到两点:一是 HTTPS 加密传输,二是访问认证。裸奔的仓库就像没上锁的保险柜,迟早出事。
明天是 Day 24 容器资源限制 ,我们会聊聊怎么给容器戴上 " 紧箍咒 "——限制 CPU、内存、磁盘 IO,防止某个容器吃光所有资源把整台机器搞崩。这在生产环境中非常重要,不容错过。