使用Docker Registry快速搭建私有镜像仓库

一、为什么需要私有镜像仓库?

在企业级开发中,直接使用Docker Hub等公共仓库存在诸多限制:

  1. 安全性风险:公共仓库的镜像可能被篡改或包含恶意代码,尤其不适合存储包含敏感信息的内部服务镜像。
  2. 网络依赖:国内访问Docker Hub速度不稳定,拉取镜像耗时较长,影响CI/CD效率。
  3. 版本控制困难:公共仓库无法灵活管理镜像版本标签,难以实现镜像的灰度发布或回滚。
  4. 成本问题:Docker Hub对匿名用户的拉取次数有限制,企业级需求需付费订阅。

私有镜像仓库通过本地化部署,可完全控制镜像的存储、访问权限和生命周期,尤其适合金融、医疗等对数据安全要求高的行业。

二、Docker Registry核心优势

Docker Registry是Docker官方提供的轻量级镜像仓库解决方案,具有以下特点:

  • 开箱即用:基于Go语言开发,无外部依赖,单二进制文件即可运行。
  • RESTful API:兼容Docker客户端协议,支持docker push/pull等标准操作。
  • 可扩展性:支持插件机制,可集成存储后端(如S3、MinIO)、认证服务(如OAuth2)等。
  • 低资源占用:在小型服务器上即可运行,适合测试环境或边缘计算场景。

三、快速部署私有Registry

1. 基础部署(无认证)

  1. # 拉取官方Registry镜像
  2. docker pull registry:2.8.1
  3. # 启动Registry容器(默认端口5000)
  4. docker run -d \
  5. --name registry \
  6. -p 5000:5000 \
  7. --restart=always \
  8. registry:2.8.1

验证

  1. # 推送测试镜像(需先tag)
  2. docker tag alpine:latest localhost:5000/my-alpine:v1
  3. docker push localhost:5000/my-alpine:v1
  4. # 拉取测试
  5. docker pull localhost:5000/my-alpine:v1

2. 配置HTTPS安全访问

生产环境必须启用HTTPS,以防止中间人攻击:

  1. # 生成自签名证书(实际环境应使用CA签发证书)
  2. mkdir -p certs
  3. openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key \
  4. -x509 -days 365 -out certs/domain.crt -subj "/CN=registry.example.com"
  5. # 启动带HTTPS的Registry
  6. docker run -d \
  7. --name registry \
  8. -p 5000:5000 \
  9. -v $(pwd)/certs:/certs \
  10. -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
  11. -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
  12. --restart=always \
  13. registry:2.8.1

客户端配置

  1. # 将自签名证书加入Docker信任链(Linux)
  2. sudo mkdir -p /etc/docker/certs.d/registry.example.com:5000
  3. sudo cp certs/domain.crt /etc/docker/certs.d/registry.example.com:5000/ca.crt
  4. sudo systemctl restart docker

3. 用户认证配置

通过htpasswd实现基础认证:

  1. # 生成密码文件
  2. mkdir auth
  3. docker run --entrypoint htpasswd \
  4. registry:2.8.1 -Bbn admin admin123 > auth/htpasswd
  5. # 启动带认证的Registry
  6. docker run -d \
  7. --name registry \
  8. -p 5000:5000 \
  9. -v $(pwd)/auth:/auth \
  10. -e REGISTRY_AUTH=htpasswd \
  11. -e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm" \
  12. -e REGISTRY_AUTH_HTPASSWD_PATH="/auth/htpasswd" \
  13. --restart=always \
  14. registry:2.8.1

登录测试

  1. docker login registry.example.com:5000
  2. # 输入用户名admin和密码admin123

四、进阶配置与优化

1. 存储后端配置

默认使用本地文件系统,可配置为对象存储:

  1. # config.yml示例
  2. version: 0.1
  3. storage:
  4. s3:
  5. accesskey: minioadmin
  6. secretkey: minioadmin
  7. region: us-east-1
  8. bucket: docker-registry
  9. encrypt: true
  10. secure: true
  11. v4auth: true
  12. chunksize: 5242880
  13. delete:
  14. enabled: true

启动命令:

  1. docker run -d \
  2. --name registry \
  3. -p 5000:5000 \
  4. -v $(pwd)/config.yml:/etc/docker/registry/config.yml \
  5. -v $(pwd)/auth:/auth \
  6. -e REGISTRY_AUTH=htpasswd \
  7. -e REGISTRY_AUTH_HTPASSWD_PATH="/auth/htpasswd" \
  8. --restart=always \
  9. registry:2.8.1

2. 镜像清理策略

通过registry garbage-collect命令清理未被引用的镜像层:

  1. # 进入容器执行清理
  2. docker exec -it registry /bin/registry garbage-collect /etc/docker/registry/config.yml

3. 镜像保留策略

结合registry-cli工具实现自动化清理:

  1. # 安装registry-cli
  2. npm install -g docker-registry-cli
  3. # 删除超过30天的镜像
  4. docker-registry-cli search --registry https://registry.example.com:5000 \
  5. --image-name my-app --before 30d --delete

五、与CI/CD集成

1. Jenkins流水线示例

  1. pipeline {
  2. agent any
  3. stages {
  4. stage('Build') {
  5. steps {
  6. script {
  7. docker.build("my-app:${env.BUILD_ID}").push("registry.example.com:5000/my-app:${env.BUILD_ID}")
  8. }
  9. }
  10. }
  11. stage('Deploy') {
  12. steps {
  13. sh "docker pull registry.example.com:5000/my-app:${env.BUILD_ID}"
  14. sh "docker service update --image registry.example.com:5000/my-app:${env.BUILD_ID} my-service"
  15. }
  16. }
  17. }
  18. }

2. GitLab CI配置

  1. build_image:
  2. stage: build
  3. image: docker:latest
  4. services:
  5. - docker:dind
  6. script:
  7. - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD registry.example.com:5000
  8. - docker build -t registry.example.com:5000/my-app:$CI_COMMIT_SHA .
  9. - docker push registry.example.com:5000/my-app:$CI_COMMIT_SHA

六、运维监控建议

  1. 日志收集:通过docker logs -f registry实时查看访问日志。
  2. 性能监控:使用Prometheus采集Registry的API调用指标。
  3. 备份策略:定期备份/var/lib/registry目录或对象存储中的数据。
  4. 高可用方案:部署多个Registry实例,前端通过Nginx实现负载均衡。

七、常见问题解决

  1. 推送失败(401 Unauthorized):检查认证信息是否正确,或htpasswd文件权限是否为600。
  2. 证书错误(x509: certificate signed by unknown authority):确保客户端信任链包含Registry的CA证书。
  3. 存储空间不足:配置storage.delete.enabled=true并定期执行垃圾回收。

通过以上步骤,开发者可在30分钟内完成一个生产级私有Registry的部署。对于超大规模场景,可考虑Harbor等企业级解决方案,但Docker Registry仍是小团队快速上手的最佳选择。