上一篇 下一篇 分享链接 返回 返回顶部

内网 Docker 私有镜像仓库搭建实战:Registry、Nginx 与 HTTPS 配置全套示例

发布人:慈云数据-客服中心 发布时间:3小时前 阅读量:1

Docker 私有化部署方案|附配置文件

在企业内部系统建设、研发测试环境搭建、离线交付、私有云部署等场景中,Docker 已经成为非常常见的基础设施组件。相比传统的应用部署方式,Docker 能够将应用、依赖、运行环境统一封装,提升交付一致性,降低环境差异带来的问题。

不过,在实际生产环境中,很多企业并不会直接依赖公网镜像仓库或云厂商镜像服务,而是会选择搭建一套Docker 私有化部署方案。这样既可以保证镜像资产的安全性,也能提升镜像拉取速度,并满足内网、离线、合规审计等要求。

本文将围绕 Docker 私有化部署进行完整说明,包括方案架构、部署步骤、Registry 私有镜像仓库搭建、Docker Compose 配置、Nginx 反向代理、HTTPS 配置、认证配置、镜像推送与拉取、常见问题及生产建议等内容,并附带可直接参考的配置文件。


一、为什么需要 Docker 私有化部署?

在很多公司或项目中,使用 Docker 时最常见的方式是直接从 Docker Hub、阿里云镜像仓库、腾讯云镜像仓库等公网服务拉取镜像。例如:

docker pull nginx:latest
docker pull mysql:8.0
docker pull redis:7

这种方式在互联网环境中比较方便,但在企业级场景下存在一些问题。

1. 网络环境受限

很多政企、金融、能源、医疗、工业等行业项目部署在内网环境中,服务器无法直接访问公网。如果依赖公网镜像仓库,就会导致镜像无法拉取,部署流程无法持续。

2. 镜像安全不可控

公网镜像来源复杂,即使是官方镜像,也可能存在版本变化、漏洞未修复、供应链风险等问题。企业通常希望对镜像进行统一扫描、统一维护、统一发布。

3. 镜像拉取速度不稳定

公网镜像仓库受网络带宽、跨境链路、限流策略等因素影响,拉取速度可能很慢,尤其是 CI/CD 批量构建时会明显影响效率。

4. 版本管理要求

企业内部通常会维护自己的基础镜像,例如:

  • company/openjdk:17
  • company/nginx:1.24
  • company/node:20
  • company/python:3.11
  • project/backend:v1.0.0

这些镜像需要放在内部仓库中进行统一管理。

5. 满足合规与审计

在生产环境中,镜像发布、下载、更新都需要具备可追溯性。私有镜像仓库能够结合权限控制、日志审计、漏洞扫描等能力,满足企业管理要求。


二、整体部署架构

本文采用比较通用、轻量、可维护的方案:

客户端 / CI/CD / 业务服务器
        |
        | docker login / pull / push
        |
    Nginx HTTPS 反向代理
        |
        | proxy_pass
        |
 Docker Registry 私有镜像仓库
        |
        |
   本地磁盘 / NAS / 对象存储

核心组件如下:

组件 说明
Docker Engine 容器运行时
Docker Compose 编排 Registry 和 Nginx
Registry Docker 官方私有镜像仓库服务
Nginx 提供 HTTPS 反向代理、统一入口
htpasswd 用于配置基础认证
SSL 证书 用于 HTTPS 加密访问
存储目录 保存镜像层数据和元信息

本文示例中,我们假设私有仓库域名为:

registry.example.com

服务器内网 IP 为:

192.168.10.20

Registry 对外访问地址为:

https://registry.example.com

如果没有正式域名,也可以使用内网 DNS 或 hosts 方式解析。


三、服务器环境准备

1. 推荐服务器配置

如果只是中小型团队使用,推荐配置如下:

项目 推荐配置
CPU 2 核及以上
内存 4GB 及以上
磁盘 200GB 起步,建议使用独立数据盘
系统 Ubuntu 22.04 / Debian 12 / CentOS 7+ / Rocky Linux
网络 内网千兆网络优先

如果企业镜像较多,建议磁盘空间至少 500GB 起步,并规划定期清理策略。

2. 安装 Docker

以 Ubuntu 为例:

sudo apt update
sudo apt install -y ca-certificates curl gnupg lsb-release

添加 Docker 官方 GPG Key:

sudo install -m 0755 -d /etc/apt/keyrings

curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

添加 Docker 软件源:

echo \
  "deb [arch=$(dpkg --print-architecture) \
  signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" \
  | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

安装 Docker:

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

启动并设置开机自启:

sudo systemctl enable docker
sudo systemctl start docker

检查版本:

docker version
docker compose version

四、目录规划

建议将私有仓库相关文件统一放在 /data/docker-registry 目录下:

sudo mkdir -p /data/docker-registry/{registry,nginx,auth,certs,logs}

目录说明:

/data/docker-registry
├── auth        # htpasswd 认证文件
├── certs       # SSL 证书文件
├── logs        # Nginx 日志
├── nginx       # Nginx 配置文件
└── registry    # Registry 镜像数据存储目录

设置权限:

sudo chown -R root:root /data/docker-registry

如果生产环境中使用独立数据盘,可以将数据盘挂载到 /data,避免系统盘被镜像数据占满。


五、创建认证文件

Docker Registry 默认可以匿名访问,但生产环境不建议这么做。我们可以使用 htpasswd 配置用户名和密码。

1. 安装 htpasswd 工具

Ubuntu / Debian:

sudo apt install -y apache2-utils

CentOS / Rocky Linux:

sudo yum install -y httpd-tools

2. 创建用户

假设创建一个用户:

用户名:admin
密码:Admin@123456

执行:

sudo htpasswd -Bbn admin 'Admin@123456' \
  | sudo tee /data/docker-registry/auth/htpasswd

参数说明:

参数 说明
-B 使用 bcrypt 加密
-b 从命令行输入密码
-n 输出到标准输出,不直接写文件

如果需要添加更多用户:

sudo htpasswd -B /data/docker-registry/auth/htpasswd devuser

然后根据提示输入密码。


六、准备 SSL 证书

生产环境建议使用正式 CA 签发的证书。如果是内网环境,可以使用企业内部 CA 或自签名证书。

本文示例证书文件如下:

/data/docker-registry/certs/registry.example.com.crt
/data/docker-registry/certs/registry.example.com.key

如果使用自签名证书,可以执行:

sudo openssl req -newkey rsa:4096 -nodes -sha256 \
  -keyout /data/docker-registry/certs/registry.example.com.key \
  -x509 -days 3650 \
  -out /data/docker-registry/certs/registry.example.com.crt \
  -subj "/C=CN/ST=Beijing/L=Beijing/O=Example/OU=IT/CN=registry.example.com"

注意:如果使用自签名证书,客户端机器需要信任该证书,否则执行 docker logindocker pull 时会报证书错误。


七、Registry 配置文件

创建 Registry 配置文件:

sudo mkdir -p /data/docker-registry/config
sudo vim /data/docker-registry/config/config.yml

内容如下:

version: 0.1

log:
  fields:
    service: registry

storage:
  filesystem:
    rootdirectory: /var/lib/registry
  delete:
    enabled: true
  cache:
    blobdescriptor: inmemory

http:
  addr: :5000
  headers:
    X-Content-Type-Options:
      - nosniff

auth:
  htpasswd:
    realm: basic-realm
    path: /auth/htpasswd

health:
  storagedriver:
    enabled: true
    interval: 10s
    threshold: 3

配置说明:

配置项 说明
storage.filesystem.rootdirectory Registry 容器内镜像数据目录
delete.enabled 开启镜像删除能力
http.addr Registry 监听端口
auth.htpasswd.path 认证文件路径
health.storagedriver 存储健康检查

八、Nginx 配置文件

Nginx 负责对外提供 HTTPS 服务,并将请求转发给 Registry。

创建配置文件:

sudo vim /data/docker-registry/nginx/registry.conf

内容如下:

upstream docker_registry {
    server registry:5000;
}

server {
    listen 80;
    server_name registry.example.com;

    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name registry.example.com;

    ssl_certificate     /etc/nginx/certs/registry.example.com.crt;
    ssl_certificate_key /etc/nginx/certs/registry.example.com.key;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    client_max_body_size 0;
    chunked_transfer_encoding on;

    access_log /var/log/nginx/registry_access.log;
    error_log  /var/log/nginx/registry_error.log;

    location /v2/ {
        proxy_pass http://docker_registry;

        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_read_timeout 900;
        proxy_connect_timeout 900;
        proxy_send_timeout 900;

        proxy_buffering off;
        proxy_request_buffering off;
    }
}

这里有几个关键配置需要注意:

  1. client_max_body_size 0
    表示不限制上传大小,否则推送大镜像时可能失败。

  2. proxy_request_buffering off
    避免 Nginx 先缓存整个上传请求,适合大镜像上传。

  3. /v2/
    Docker Registry API 的核心路径,Docker 客户端访问仓库时会请求该路径。


九、Docker Compose 配置文件

创建 docker-compose.yml

sudo vim /data/docker-registry/docker-compose.yml

完整内容如下:

services:
  registry:
    image: registry:2
    container_name: docker-registry
    restart: always
    volumes:
      - ./registry:/var/lib/registry
      - ./auth:/auth
      - ./config/config.yml:/etc/docker/registry/config.yml:ro
    environment:
      REGISTRY_HTTP_ADDR: 0.0.0.0:5000
    networks:
      - registry-net

  nginx:
    image: nginx:1.25
    container_name: docker-registry-nginx
    restart: always
    depends_on:
      - registry
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/registry.conf:/etc/nginx/conf.d/default.conf:ro
      - ./certs:/etc/nginx/certs:ro
      - ./logs:/var/log/nginx
    networks:
      - registry-net

networks:
  registry-net:
    driver: bridge

该配置中包含两个服务:

服务 说明
registry Docker 官方镜像仓库
nginx HTTPS 反向代理

启动服务:

cd /data/docker-registry
sudo docker compose up -d

查看容器状态:

sudo docker compose ps

查看日志:

sudo docker compose logs -f

十、配置域名解析

如果内网有 DNS,可以将域名解析到服务器 IP:

registry.example.com -> 192.168.10.20

如果没有 DNS,可以在每台客户端机器的 hosts 文件中添加:

Linux:

sudo vim /etc/hosts

增加:

192.168.10.20 registry.example.com

Windows:

C:\Windows\System32\drivers\etc\hosts

增加:

192.168.10.20 registry.example.com

十一、客户端信任自签名证书

如果使用的是正式 CA 证书,一般无需额外配置。

如果使用自签名证书,需要在每台 Docker 客户端上配置信任证书。

1. 创建证书目录

sudo mkdir -p /etc/docker/certs.d/registry.example.com

2. 拷贝证书

将服务端的证书复制到客户端:

sudo cp registry.example.com.crt \
  /etc/docker/certs.d/registry.example.com/ca.crt

注意文件名必须是:

ca.crt

3. 重启 Docker

sudo systemctl restart docker

如果仓库使用的是非标准端口,例如 registry.example.com:5000,目录应为:

/etc/docker/certs.d/registry.example.com:5000/ca.crt

十二、登录私有镜像仓库

在客户端执行:

docker login registry.example.com

输入用户名和密码:

Username: admin
Password: Admin@123456

登录成功后会看到类似输出:

Login Succeeded

Docker 会将登录凭据保存到:

~/.docker/config.json

十三、推送镜像到私有仓库

以 Nginx 镜像为例:

docker pull nginx:1.25

重新打标签:

docker tag nginx:1.25 registry.example.com/library/nginx:1.25

推送镜像:

docker push registry.example.com/library/nginx:1.25

成功后,私有仓库中就会保存该镜像。

以后其他服务器可以直接拉取:

docker pull registry.example.com/library/nginx:1.25

十四、业务镜像发布示例

假设有一个 Spring Boot 项目,Dockerfile 如下:

FROM registry.example.com/library/eclipse-temurin:17-jre

WORKDIR /app

COPY target/app.jar /app/app.jar

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "/app/app.jar"]

构建镜像:

docker build -t registry.example.com/project/backend:v1.0.0 .

推送镜像:

docker push registry.example.com/project/backend:v1.0.0

业务服务器部署:

docker pull registry.example.com/project/backend:v1.0.0

docker run -d \
  --name backend \
  -p 8080:8080 \
  --restart=always \
  registry.example.com/project/backend:v1.0.0

十五、查看仓库镜像列表

Docker Registry 原生 API 能力比较基础,可以通过接口查看镜像列表。

查看所有仓库:

curl -u admin:Admin@123456 \
  https://registry.example.com/v2/_catalog

返回示例:

{
  "repositories": [
    "library/nginx",
    "project/backend"
  ]
}

查看某个镜像的标签:

curl -u admin:Admin@123456 \
  https://registry.example.com/v2/library/nginx/tags/list

返回示例:

{
  "name": "library/nginx",
  "tags": [
    "1.25"
  ]
}

如果使用自签名证书且未被 curl 信任,可以临时使用 -k 参数:

curl -k -u admin:Admin@123456 \
  https://registry.example.com/v2/_catalog

十六、删除镜像与垃圾回收

Registry 删除镜像不是简单地删除 tag,需要先获取 manifest digest,再调用删除接口。

1. 获取镜像 Digest

curl -I \
  -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
  -u admin:Admin@123456 \
  https://registry.example.com/v2/library/nginx/manifests/1.25

响应头中会包含:

Docker-Content-Digest: sha256:xxxxxxxxxxxxxxxx

2. 删除 Manifest

curl -X DELETE \
  -u admin:Admin@123456 \
  https://registry.example.com/v2/library/nginx/manifests/sha256:xxxxxxxxxxxxxxxx

3. 执行垃圾回收

进入 Registry 容器执行:

docker exec -it docker-registry sh

执行垃圾回收:

registry garbage-collect /etc/docker/registry/config.yml

为了避免在垃圾回收过程中仍有镜像上传或拉取,建议先停止 Registry 服务:

cd /data/docker-registry
docker compose stop registry

然后临时执行:

docker run --rm \
  -v /data/docker-registry/registry:/var/lib/registry \
  -v /data/docker-registry/config/config.yml:/etc/docker/registry/config.yml:ro \
  registry:2 \
  registry garbage-collect /etc/docker/registry/config.yml

最后启动服务:

docker compose start registry

十七、生产环境增强建议

上面的方案适合中小规模私有镜像仓库。如果用于生产环境,建议进一步增强。

1. 使用 Harbor 替代原生 Registry

Docker Registry 功能较简单,适合轻量使用。如果企业需要更完整的镜像管理平台,建议使用 Harbor。

Harbor 支持:

  • Web 管理界面
  • 项目与用户权限管理
  • 镜像漏洞扫描
  • 镜像复制
  • 镜像签名
  • 机器人账号
  • 审计日志
  • 镜像保留策略
  • LDAP / OIDC 集成

如果是企业生产级环境,Harbor 通常是更推荐的选择。

2. 配置磁盘监控

镜像仓库非常容易占用大量磁盘空间,需要配置监控和告警。

可以关注:

df -h
du -sh /data/docker-registry/registry

建议结合 Prometheus、Grafana、Node Exporter 配置磁盘容量告警。

3. 定期清理无用镜像

CI/CD 高频构建时会产生大量版本镜像,例如:

backend:feature-xxx
backend:test-20240101
backend:commit-abcdef

这些镜像如果不清理,会快速占满磁盘。

建议制定镜像保留策略:

  • 生产版本永久保留;
  • 测试版本保留最近 30 天;
  • 临时分支镜像保留最近 7 天;
  • 每周执行一次垃圾回收。

4. 配置访问控制

虽然 htpasswd 可以满足基础认证,但权限粒度较粗。如果需要项目级权限,例如:

  • A 项目成员只能访问 A 项目镜像;
  • B 项目成员只能访问 B 项目镜像;
  • CI 账号只能 push,生产服务器只能 pull;

则建议使用 Harbor 或其他更完整的镜像仓库产品。

5. 配置备份策略

镜像仓库数据目录非常重要,建议定期备份:

/data/docker-registry/registry
/data/docker-registry/auth
/data/docker-registry/config
/data/docker-registry/certs
/data/docker-registry/nginx

可使用 rsync、对象存储、NAS 快照等方式进行备份。

示例备份脚本:

#!/bin/bash

BACKUP_DIR="/backup/docker-registry"
DATE=$(date +%F-%H%M%S)

mkdir -p ${BACKUP_DIR}

tar -czf ${BACKUP_DIR}/docker-registry-${DATE}.tar.gz \
  /data/docker-registry/auth \
  /data/docker-registry/config \
  /data/docker-registry/certs \
  /data/docker-registry/nginx

echo "backup finished: ${BACKUP_DIR}/docker-registry-${DATE}.tar.gz"

对于镜像数据目录,如果数据量很大,不建议频繁 tar 打包,可以使用增量同步:

rsync -av --delete /data/docker-registry/registry/ /backup/docker-registry-data/

6. 配置日志轮转

Nginx 日志如果长期不清理,也会占用磁盘空间。可以配置 logrotate:

sudo vim /etc/logrotate.d/docker-registry-nginx

内容如下:

/data/docker-registry/logs/*.log {
    daily
    rotate 14
    compress
    missingok
    notifempty
    copytruncate
}

十八、常见问题排查

1. docker login 报 x509 证书错误

错误示例:

x509: certificate signed by unknown authority

原因通常是客户端不信任自签名证书。

解决方式:

sudo mkdir -p /etc/docker/certs.d/registry.example.com
sudo cp registry.example.com.crt /etc/docker/certs.d/registry.example.com/ca.crt
sudo systemctl restart docker

2. 推送镜像时报 413 Request Entity Too Large

说明 Nginx 限制了上传大小。

确认 Nginx 配置中存在:

client_max_body_size 0;

修改后重启:

cd /data/docker-registry
docker compose restart nginx

3. 推送大镜像超时

可适当增大 Nginx 超时时间:

proxy_read_timeout 900;
proxy_connect_timeout 900;
proxy_send_timeout 900;

4. no basic auth credentials

说明没有登录,或登录地址与推送地址不一致。

执行:

docker login registry.example.com

注意以下地址必须一致:

docker login registry.example.com
docker push registry.example.com/project/backend:v1.0.0

如果一个使用 IP,一个使用域名,Docker 会认为是两个不同仓库。

5. http: server gave HTTP response to HTTPS client

说明 Docker 客户端按 HTTPS 访问,但服务端只提供 HTTP,或者反向代理配置异常。

推荐解决方式是启用 HTTPS。如果只是测试环境使用 HTTP,需要在客户端配置 insecure registry。

编辑:

sudo vim /etc/docker/daemon.json

增加:

{
  "insecure-registries": ["registry.example.com"]
}

重启 Docker:

sudo systemctl restart docker

生产环境不建议使用该方式。


十九、完整文件结构汇总

最终目录结构如下:

/data/docker-registry
├── auth
│   └── htpasswd
├── certs
│   ├── registry.example.com.crt
│   └── registry.example.com.key
├── config
│   └── config.yml
├── docker-compose.yml
├── logs
├── nginx
│   └── registry.conf
└── registry

核心文件包括:

1. docker-compose.yml

services:
  registry:
    image: registry:2
    container_name: docker-registry
    restart: always
    volumes:
      - ./registry:/var/lib/registry
      - ./auth:/auth
      - ./config/config.yml:/etc/docker/registry/config.yml:ro
    environment:
      REGISTRY_HTTP_ADDR: 0.0.0.0:5000
    networks:
      - registry-net

  nginx:
    image: nginx:1.25
    container_name: docker-registry-nginx
    restart: always
    depends_on:
      - registry
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/registry.conf:/etc/nginx/conf.d/default.conf:ro
      - ./certs:/etc/nginx/certs:ro
      - ./logs:/var/log/nginx
    networks:
      - registry-net

networks:
  registry-net:
    driver: bridge

2. config.yml

version: 0.1

log:
  fields:
    service: registry

storage:
  filesystem:
    rootdirectory: /var/lib/registry
  delete:
    enabled: true
  cache:
    blobdescriptor: inmemory

http:
  addr: :5000
  headers:
    X-Content-Type-Options:
      - nosniff

auth:
  htpasswd:
    realm: basic-realm
    path: /auth/htpasswd

health:
  storagedriver:
    enabled: true
    interval: 10s
    threshold: 3

3. registry.conf

upstream docker_registry {
    server registry:5000;
}

server {
    listen 80;
    server_name registry.example.com;

    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name registry.example.com;

    ssl_certificate     /etc/nginx/certs/registry.example.com.crt;
    ssl_certificate_key /etc/nginx/certs/registry.example.com.key;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    client_max_body_size 0;
    chunked_transfer_encoding on;

    access_log /var/log/nginx/registry_access.log;
    error_log  /var/log/nginx/registry_error.log;

    location /v2/ {
        proxy_pass http://docker_registry;

        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_read_timeout 900;
        proxy_connect_timeout 900;
        proxy_send_timeout 900;

        proxy_buffering off;
        proxy_request_buffering off;
    }
}

二十、总结

本文介绍了一套基于 Docker Registry、Nginx、HTTPS 和 htpasswd 的 Docker 私有化部署方案。该方案具有部署简单、依赖少、可维护性高的特点,适合中小团队、测试环境、离线交付环境以及轻量级生产场景使用。

通过本文配置,可以实现:

  • 内网私有镜像仓库;
  • HTTPS 安全访问;
  • 用户名密码认证;
  • 镜像推送与拉取;
  • 镜像删除与垃圾回收;
  • 日志管理与备份扩展;
  • 与业务 Dockerfile、CI/CD 流程集成。

如果只是需要一个轻量、稳定、易部署的私有仓库,Docker Registry 已经足够使用;如果企业对权限、审计、漏洞扫描、可视化管理要求更高,则建议进一步采用 Harbor 作为企业级镜像仓库平台。

无论选择哪种方式,Docker 私有化部署的核心目标都是一致的:让镜像交付更安全、更稳定、更可控,让应用部署更加标准化和自动化。

目录结构
全文