从0到1:手把手搭建私有镜像仓库并推送镜像指南

引言:为什么需要私有镜像仓库?

在容器化部署日益普及的今天,Docker镜像已成为软件交付的标准单元。然而,使用公共仓库(如Docker Hub)存在安全隐患、网络依赖、速率限制等问题。对于企业级应用或对安全性要求较高的场景,搭建私有镜像仓库成为必然选择。本文将详细介绍如何从零开始搭建一个安全、高效的私有镜像仓库,并完成镜像的推送与拉取操作。

一、环境准备:基础条件与工具选择

1.1 服务器环境要求

搭建私有镜像仓库的核心是部署Registry服务。推荐使用Linux服务器(如CentOS/Ubuntu),配置建议如下:

  • 操作系统:CentOS 7+/Ubuntu 18.04+(LTS版本优先)
  • 硬件:至少2核CPU、4GB内存、20GB存储空间(根据镜像规模调整)
  • 网络:公网IP或内网可访问地址,开放5000端口(默认Registry端口)

1.2 工具与依赖

  • Docker Engine:用于运行Registry容器(版本≥18.09)
  • Nginx/Apache(可选):用于反向代理和HTTPS配置
  • Let’s Encrypt(可选):免费SSL证书生成工具
  • 认证工具:如htpasswd(Apache工具)或自定义OAuth2服务

二、从0到1搭建私有Registry

2.1 使用Docker官方Registry镜像

Docker官方提供了轻量级的Registry镜像,可通过以下命令快速部署:

  1. # 拉取Registry镜像
  2. docker pull registry:2
  3. # 运行Registry容器(基础版,无认证)
  4. docker run -d -p 5000:5000 --name my-registry registry:2

说明:此方式仅适用于测试环境,生产环境需配置认证和HTTPS。

2.2 生产环境配置:认证与HTTPS

2.2.1 启用基础认证

  1. 生成认证文件

    1. mkdir -p /auth
    2. docker run --entrypoint htpasswd httpd:2 -Bbn username password > /auth/htpasswd
  2. 运行带认证的Registry

    1. docker run -d \
    2. -p 5000:5000 \
    3. --name my-secure-registry \
    4. -e REGISTRY_AUTH=htpasswd \
    5. -e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm" \
    6. -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
    7. -v /auth:/auth \
    8. registry:2

2.2.2 配置HTTPS

  1. 生成SSL证书(使用Let’s Encrypt示例):

    1. # 安装Certbot
    2. sudo apt install certbot python3-certbot-nginx
    3. # 获取证书(假设域名是registry.example.com)
    4. sudo certbot certonly --nginx -d registry.example.com
  2. 通过Nginx反向代理配置HTTPS

    1. server {
    2. listen 443 ssl;
    3. server_name registry.example.com;
    4. ssl_certificate /etc/letsencrypt/live/registry.example.com/fullchain.pem;
    5. ssl_certificate_key /etc/letsencrypt/live/registry.example.com/privkey.pem;
    6. location / {
    7. proxy_pass http://localhost:5000;
    8. proxy_set_header Host $host;
    9. proxy_set_header X-Real-IP $remote_addr;
    10. }
    11. }
  3. 重启Nginx

    1. sudo systemctl restart nginx

2.3 存储配置与持久化

默认情况下,Registry数据存储在容器内,重启后数据丢失。需挂载宿主机目录:

  1. docker run -d \
  2. -p 5000:5000 \
  3. --name my-persistent-registry \
  4. -e REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/var/lib/registry \
  5. -v /data/registry:/var/lib/registry \
  6. -v /auth:/auth \
  7. -e REGISTRY_AUTH=htpasswd \
  8. -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
  9. registry:2

三、推送镜像到私有仓库

3.1 标记镜像并推送

  1. 标记本地镜像

    1. docker tag nginx:latest registry.example.com/myapp/nginx:v1
  2. 登录私有仓库

    1. docker login registry.example.com
    2. # 输入用户名和密码
  3. 推送镜像

    1. docker push registry.example.com/myapp/nginx:v1

3.2 常见问题排查

  • 错误:x509: certificate signed by unknown authority
    原因:客户端未信任私有仓库的SSL证书。
    解决方案

    • 将证书添加到客户端的信任链(Linux:/etc/docker/certs.d/registry.example.com/ca.crt
    • 或临时禁用证书验证(不推荐):echo '{"insecure-registries":["registry.example.com"]}' > /etc/docker/daemon.json,重启Docker。
  • 错误:denied: requested access to the resource is denied
    原因:未登录或权限不足。
    解决方案:重新执行docker login,确保用户名/密码正确。

四、进阶配置:镜像清理与访问控制

4.1 镜像清理策略

Registry默认不自动清理未使用的镜像层。可通过以下方式管理存储:

  1. 手动删除

    1. # 列出所有镜像
    2. curl -X GET https://registry.example.com/v2/_catalog
    3. # 删除特定镜像(需Registry API权限)
    4. # 实际删除需调用Registry的垃圾回收机制
  2. 配置垃圾回收(需Registry 2.4+):

    1. # 停止Registry容器
    2. docker stop my-registry
    3. # 运行垃圾回收(需挂载存储目录)
    4. docker run --rm -v /data/registry:/var/lib/registry \
    5. -e REGISTRY_STORAGE_DELETE_ENABLED=true \
    6. registry:2 garbage-collect /etc/registry/config.yml

4.2 细粒度访问控制

可通过以下方式实现更复杂的权限管理:

  • 基于Token的认证:集成OAuth2/OpenID Connect服务。
  • 仓库级权限:使用registry:2AUTH中间件配置不同用户的读写权限。

五、总结与最佳实践

  1. 安全性优先:始终启用HTTPS和认证,避免使用insecure-registries
  2. 存储规划:根据镜像增长预测分配足够存储,定期清理无用镜像。
  3. 高可用设计:生产环境建议部署多节点Registry集群(如Harbor支持HA)。
  4. 监控与日志:通过Prometheus+Grafana监控Registry指标,配置日志轮转。

通过以上步骤,您已成功从零搭建了一个安全、可用的私有镜像仓库,并完成了镜像的推送操作。这一基础设施将为后续的CI/CD流水线、微服务部署提供坚实的支撑。