Docker: 私有镜像仓库

最后更新:2026-08-26

不想把公司代码推送到公开的 Docker Hub?5 分钟搭建一个私有镜像仓库。

1. 你将学到


2. 一个团队负责人的真实故事

(1) 痛点:代码不能推到公开仓库

Alice 不想把公司代码推送到公开的 Docker Hub——镜像里可能包含配置文件、环境变量默认值等敏感信息。但团队需要一个镜像仓库来共享构建产物,手动 docker save/load 传输太低效,5 个开发者每次传递镜像要 30 分钟。

(2) 私有 Registry 的解法

用 3 行配置就搭建了带认证的私有仓库。

BASH
# Start a private registry with authentication
docker run -d -p 5000:5000 \
  -v registry-data:/var/lib/registry \
  --restart=always \
  --name registry registry:2

(3) 收益:5 分钟共享镜像

团队 5 分钟内就开始使用私有仓库。docker push 一次,所有人 docker pull 即可。镜像传递从 30 分钟降到 30 秒。


3. 镜像仓库方案对比

(1) 三种方案对比

维度 Docker Hub(公开) 私有 Registry Harbor
费用 免费有限额,付费 $5/月 完全免费 免费开源
认证 Docker 账号 htpasswd/TLS LDAP/OIDC/DB
Web UI
镜像扫描 ✅(付费) ✅(Trivy 集成)
部署难度 零(已上线) 低(1 条命令) 中(Docker Compose)
适用规模 个人/小团队 中小团队 企业级

(2) 镜像命名规范

TEXT 📖 仅展示
# Official images on Docker Hub
docker.io/library/nginx:1.25

# User images on Docker Hub
docker.io/myorg/myapp:v2.0

# Private registry images
localhost:5000/myapp:v2.0
registry.example.com/team/app:v1.0

4. 部署私有 Registry

▶ 示例:启动 Registry 容器(难度⭐)

BASH
# Start a basic private registry
docker run -d \
  -p 5000:5000 \
  --name registry \
  --restart=always \
  -v registry-data:/var/lib/registry \
  registry:2

# Verify it's running
curl http://localhost:5000/v2/_catalog
💻 输出:

TEXT 📖 仅展示
{"repositories":[]}

(1) 数据持久化

方式 命令 说明
Named Volume -v registry-data:/var/lib/registry Docker 管理的持久化存储
Bind Mount -v /data/registry:/var/lib/registry 指定主机目录
默认(无 -v) 无持久化 容器删除后镜像数据丢失
⚠️ 注意: 生产环境必须使用 Volume 或 Bind Mount 持久化数据。否则 Registry 容器删除后,所有推送的镜像都会丢失。


5. 推送与拉取镜像

▶ 示例:推送到私有仓库(难度⭐⭐)

BASH
# 1. Tag an image for the private registry
docker tag nginx:1.25-alpine localhost:5000/web/nginx:v1

# 2. Push the image
docker push localhost:5000/web/nginx:v1

# 3. Verify it's in the registry
curl http://localhost:5000/v2/web/nginx/tags/list
💻 输出:

TEXT 📖 仅展示
{"name":"web/nginx","tags":["v1"]}

▶ 示例:从私有仓库拉取镜像(难度⭐⭐)

BASH
# 1. Remove the local copy
docker rmi localhost:5000/web/nginx:v1

# 2. Pull from the private registry
docker pull localhost:5000/web/nginx:v1

# 3. Run the pulled image
docker run --rm localhost:5000/web/nginx:v1 nginx -v
💻 输出:

TEXT 📖 仅展示
nginx version: nginx/1.25.3

6. 仓库认证配置

默认 Registry 无认证,任何人都能 push/pull。生产环境需要配置认证。

▶ 示例:生成 htpasswd 密码文件(难度⭐⭐⭐)

BASH
# Create a directory for auth data
mkdir -p auth

# Generate htpasswd file (requires httpd-tools / apache2-utils)
htpasswd -Bbn admin secret123 > auth/htpasswd

# Start registry with authentication
docker run -d \
  -p 5000:5000 \
  --name registry-auth \
  --restart=always \
  -v registry-data:/var/lib/registry \
  -v $(pwd)/auth:/auth \
  -e "REGISTRY_AUTH=htpasswd" \
  -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
  -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \
  registry:2

(1) 认证后的操作

BASH
# Login to the private registry
docker login localhost:5000
# Username: admin
# Password: secret123

# Push (requires login)
docker push localhost:5000/myapp:v1

# Pull (requires login)
docker pull localhost:5000/myapp:v1

# Logout
docker logout localhost:5000

7. 查看仓库目录

▶ 示例:curl 查看 catalog 和 tags(难度⭐⭐)

BASH
# List all repositories
curl -s http://localhost:5000/v2/_catalog | python3 -m json.tool

# List tags for a specific repository
curl -s http://localhost:5000/v2/web/nginx/tags/list | python3 -m json.tool

# View image manifest (detailed metadata)
curl -s -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
  http://localhost:5000/v2/web/nginx/manifests/v1 | python3 -m json.tool
💻 输出:

TEXT 📖 仅展示
# catalog
{
  "repositories": [
    "web/nginx",
    "team/api"
  ]
}

# tags/list
{
  "name": "web/nginx",
  "tags": ["v1", "v2"]
}

8. 垃圾回收

Registry 中的镜像被删除后(untag),层数据不会自动清理。需要手动执行垃圾回收。

▶ 示例:垃圾回收(难度⭐⭐⭐)

BASH
# Delete a tag (mark for deletion)
curl -X DELETE -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
  http://localhost:5000/v2/web/nginx/manifests/<digest>

# Run garbage collection inside the registry container
docker exec registry bin/registry garbage-collect \
  /etc/docker/registry/config.yml

# Or with dry-run first (preview only)
docker exec registry bin/registry garbage-collect --dry-run \
  /etc/docker/registry/config.yml

9. HTTP vs HTTPS 仓库

(1) Docker 安全策略

Docker 默认只允许 HTTPS 连接到 Registry(除了 localhost)。远程 Registry 必须配置 HTTPS 或在客户端添加 insecure-registries。

场景 安全级别 配置
localhost:5000 默认允许 HTTP 无需额外配置
远程 HTTP 仓库 不安全,需显式允许 insecure-registries
远程 HTTPS 仓库 ✅ 推荐 TLS 证书

(2) 配置 insecure-registries(仅限测试环境)

JSON
{
  "insecure-registries": ["registry.example.com:5000"]
}
🔒 安全: 生产环境必须使用 HTTPS + 受信任的 TLS 证书。insecure-registries 仅用于内部测试,流量可被中间人攻击。


10. 完整示例:部署带认证的私有仓库

BASH
# ============================================
# Complete walkthrough: Private registry with auth
# Covers: deploy, auth, push, pull, catalog, GC
# ============================================

# 1. Create directories for persistent data
mkdir -p auth registry-data

# 2. Generate htpasswd authentication file
htpasswd -Bbn admin secret123 > auth/htpasswd

# 3. Start the registry with authentication and persistence
docker run -d \
  -p 5000:5000 \
  --name my-registry \
  --restart=always \
  -v $(pwd)/registry-data:/var/lib/registry \
  -v $(pwd)/auth:/auth \
  -e "REGISTRY_AUTH=htpasswd" \
  -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
  -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \
  registry:2

# 4. Login to the registry
docker login localhost:5000 -u admin -p secret123

# 5. Tag and push an image
docker tag nginx:1.25-alpine localhost:5000/web/nginx:v1.0
docker push localhost:5000/web/nginx:v1.0

# 6. Verify the push
curl -s -u admin:secret123 http://localhost:5000/v2/_catalog
curl -s -u admin:secret123 http://localhost:5000/v2/web/nginx/tags/list

# 7. Pull from another machine (after login)
docker pull localhost:5000/web/nginx:v1.0

# 8. Clean up
docker logout localhost:5000
💻 输出(节选):

TEXT 📖 仅展示
# curl catalog
{"repositories":["web/nginx"]}

# curl tags
{"name":"web/nginx","tags":["v1.0"]}

❓ 常见问题

Q 私有仓库需要多大的存储空间?
A 取决于镜像数量和大小。单个镜像 50-500 MB,10 个镜像约 1-5 GB。建议初始分配 50 GB,定期清理旧版本。企业级建议用对象存储(S3/OSS)作为 Registry 后端,存储按需扩容。
Q 怎么给仓库配 HTTPS?
A 两种方式:① 用 Nginx/Caddy 做反向代理,配置 TLS 证书(推荐);② 直接在 Registry 中配置 TLS。推荐反向代理方案——Nginx 处理 TLS 终止,Registry 专注存储。Let's Encrypt 提供免费证书。
Q 镜像多了怎么清理?
A 两步:① 通过 API DELETE 删除不需要的 tag/manifest;② 执行 registry garbage-collect 释放未引用的层数据。建议写脚本定期清理超过 N 天的旧版本。Harbor 有内置的清理策略。
Q 仓库的镜像能被其他人看到吗?
A 无认证时,任何人都能 pull(匿名访问)。配置 htpasswd 认证后,必须 login 才能 push/pull。生产环境建议:pull 需只读权限,push 需写权限(Registry 2.8+ 支持 RBAC)。
Q Harbor 和 Registry 哪个好用?
A Registry 是极简仓库(适合小团队/CI),Harbor 是企业级仓库(Web UI + 镜像扫描 + RBAC + 审计日志)。团队 <10 人用 Registry,>10 人或有合规需求用 Harbor。Harbor 本身用 Docker Compose 部署,5 分钟可搭建。

📖 小节


📝 作业

  1. 基础题(难度⭐):用 docker run 启动一个私有 registry,将 nginx:alpine 推送到 localhost:5000/test/nginx:v1,然后从另一台机器(或删除本地镜像后)拉取验证。
  2. 进阶题(难度⭐⭐):配置 htpasswd 认证,验证未登录时 push 被拒绝,登录后 push 成功。
  3. 挑战题(难度⭐⭐⭐):用 Nginx 反向代理给 Registry 配置 HTTPS(可用自签名证书),通过 https://registry.local/v2/_catalog 访问仓库。
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏