1. 项目概述为什么要在 Ubuntu 18.04 上自建 Docker 私有仓库Docker 私有仓库不是“可有可无”的附加功能而是生产环境落地的刚性门槛。我最早在 2017 年给一家做智能硬件的初创公司做 CI/CD 架构时就踩过这个坑——当时所有镜像都推到 Docker Hub 公共仓库结果某天凌晨三点收到告警核心固件升级服务因拉取超时大面积失败。排查发现是 Docker Hub 的限流策略突然收紧非认证用户每 6 小时仅允许 100 次拉取而他们的自动化部署脚本每分钟触发 3 次构建5 分钟内就耗尽配额。更麻烦的是他们用的某个定制化 base 镜像含未开源的驱动模块根本不能上传到公共平台。这件事让我彻底明白私有仓库不是“高级玩法”而是可控交付的生命线。Ubuntu 18.04 是这个项目的关键约束条件。它虽已结束标准支持EOL但在工业控制、边缘网关、嵌入式测试等场景中仍是主力系统——原因很实在LTS 版本的内核稳定性经过数年验证且大量专用驱动如 NVIDIA JetPack、Intel RealSense SDK对 18.04 的适配最成熟。你不可能为了搭个仓库就把整套产线系统升级到 22.04这就像不能因为想换新锅就拆掉整个厨房的燃气管道。所以本方案所有操作都严格限定在 Ubuntu 18.04 的软件生态内不依赖 snap 包、不强求新版内核模块连 OpenSSL 版本都锁定在系统默认的 1.1.1-1ubuntu2.1~18.04.22 范围内。Nginx 和 Docker Compose 的组合不是炫技而是解决三个真实痛点第一Docker Registry 官方镜像默认不带 HTTPS而生产环境强制要求加密传输自己编译带 TLS 的 registry 二进制文件太重第二registry 进程需要常驻运行且自动重启systemd 配置容易出错用 docker-compose 管理生命周期更可靠第三Nginx 作为反向代理能无缝集成基本认证Basic Auth、访问日志审计、请求速率限制这些功能若全塞进 registry 配置里配置文件会变成难以维护的意大利面条。我实测过纯 registry self-signed cert 方案在 Ubuntu 18.04 上遇到过证书链验证失败导致客户端拒绝连接的问题而 Nginx 层面处理证书兼容性要成熟得多。这个方案真正适合的人群很明确不是 Docker 新手而是正在把容器化从开发环境推向生产环境的运维工程师、DevOps 工程师或嵌入式系统集成商。如果你还在用docker run hello-world练习建议先掌握docker build和docker push基础命令但如果你已经能写多阶段构建的 Dockerfile却卡在“怎么让团队安全地共享内部镜像”这一步那接下来的内容就是为你量身定制的实战手册。它不讲 Docker 是什么、不教怎么安装 Docker DesktopWindows/Mac 用户请绕行所有步骤都基于 Ubuntu 18.04 的原生 apt 源和官方二进制包每一步命令都经过三台不同硬件配置的物理服务器交叉验证。2. 整体架构设计与技术选型逻辑2.1 为什么放弃 registry:2 官方镜像直连方案很多人看到 Docker 官方文档第一反应是直接运行docker run -d -p 5000:5000 --restartalways --name registry registry:2这在测试环境确实最快。但在 Ubuntu 18.04 生产环境中这种裸跑方式存在四个致命缺陷第一是网络暴露风险。registry 默认监听 0.0.0.0:5000意味着任何能访问该服务器 IP 的设备都能尝试推送镜像。我们曾遇到客户现场被扫描器探测到开放的 5000 端口半小时内收到 17 次暴力破解尝试。虽然 registry 支持REGISTRY_AUTH环境变量配置 token 认证但其依赖独立的 auth 服务如 dex 或 keycloak部署复杂度陡增且 Ubuntu 18.04 的 Python 3.6 环境对现代 OIDC 库兼容性差。第二是HTTPS 强制缺失。Docker 客户端从 1.3.1 版本起默认禁用 HTTP 协议的 registry 访问除非显式添加--insecure-registry参数。而 Ubuntu 18.04 自带的 docker-ce 18.09.7 版本对此限制极严——即使你在/etc/docker/daemon.json中配置了 insecure-registry只要 registry 返回的响应头中缺少Docker-Distribution-Api-Version字段客户端仍会报错http: server gave HTTP response to HTTPS client。这个问题在官方论坛有上百个类似 issue根源在于 registry:2 镜像的默认配置不满足 Docker 客户端的 TLS 握手预期。第三是日志与监控盲区。裸 registry 容器只输出标准错误日志无法区分是客户端网络超时还是存储后端故障。我们曾在一个使用 NFS 作为 storage backend 的案例中因 NFS 服务器短暂断连导致 registry 返回 500 错误但日志里只有error authorizing context: authorization failed这条模糊信息实际是底层 storage driver 的连接池耗尽。而 Nginx 的 access.log 可以精确记录每个请求的响应时间、状态码、客户端 IP配合log_format自定义字段还能提取 User-Agent 中的 Docker 版本号这对故障定位至关重要。第四是扩展性瓶颈。当团队规模超过 20 人时单纯靠 registry 的storage配置无法实现镜像分片存储。比如你想把基础镜像ubuntu、nginx放在高速 SSD而大体积的 AI 模型镜像放在大容量 HDDregistry:2 的 filesystem driver 不支持按命名空间路由。Nginx 的map指令却可以轻松实现map $request_uri $backend { ~^/v2/library/.*$ ssd_backend; ~^/v2/models/.*$ hdd_backend; }再配合 upstream 模块分发到不同 registry 实例。2.2 Nginx 作为反向代理的核心价值不只是加一层转发把 Nginx 放在 registry 前面绝非简单的“多此一举”。我在为某汽车电子厂商部署时用 Nginx 解决了三个 registry 本身无法处理的硬需求首先是细粒度访问控制。该厂商要求研发部门只能拉取dev/命名空间下的镜像测试部门可拉取test/和dev/而生产发布系统必须能推送prod/前缀的镜像。registry 的htpasswd认证只能控制用户登录无法按镜像路径做权限隔离。而 Nginx 的auth_request模块配合一个轻量级 Python Flask 服务仅 87 行代码就能实现 RBAC 验证当请求/v2/dev/nginx/manifests/latest时Flask 服务查询 LDAP 获取用户所属组返回200 OK或403 Forbidden。这个方案比改造 registry 源码快 10 倍且不影响 registry 升级。其次是请求整形与防护。registry 对恶意请求极其脆弱——比如构造超长的Authorization头长度 8KB会导致 Go runtime panic容器自动退出。Nginx 的client_header_buffer_size和large_client_header_buffers指令可直接截断异常请求返回 400 Bad Request保护后端 registry 进程。我们在压力测试中模拟了 1000 个并发的畸形请求裸 registry 在第 372 个请求时崩溃而 Nginxregistry 组合稳定运行 2 小时无异常。最后是协议兼容性桥接。该厂商的旧版 Jenkins 服务器运行在 Ubuntu 16.04其内置的 Docker 插件使用的是 v1 API已废弃而 registry:2 只支持 v2 API。Nginx 的rewrite指令可以将/v1/repositories/xxx/images请求重写为/v2/xxx/manifests/latest并注入必要的Accept头让老系统无缝对接新仓库。这种协议转换层若由 registry 自己实现需要修改其 HTTP 路由逻辑风险极高。2.3 Docker Compose 的不可替代性进程管理的终极解法有人质疑“为什么不用 systemd 管理 registry 容器更符合 Linux 哲学。” 这个问题我专门做过对比测试。在 Ubuntu 18.04 上用 systemd 启动docker run命令存在三个隐蔽陷阱第一个是信号传递失效。systemd 的ExecStart启动的容器进程其 PID 1 是 docker-containerd-shim而非 registry 进程本身。当执行systemctl restart registry时systemd 发送 SIGTERM 给 shim 进程但 shim 可能因网络延迟未能及时转发信号给 registry导致 registry 进程残留。我们曾观察到重启后 registry 容器状态为Up 2 seconds但实际端口未监听netstat -tlnp | grep :5000显示无进程绑定。第二个是依赖关系混乱。registry 需要先挂载存储卷再启动容器。systemd 的Afterdocker.service仅保证 Docker daemon 启动不保证存储卷如 NFS mount已就绪。我们遇到过 registry 容器启动时因/var/lib/registry目录不存在而反复崩溃systemd 的RequiresMountsFor参数在 Ubuntu 18.04 的 systemd 237 版本中存在 bug无法正确等待远程挂载完成。第三个是配置热更新困难。当需要修改 registry 的storage配置如切换从本地磁盘到 S3时systemd 需要重新加载 unit 文件并重启整个服务期间所有推送请求失败。而 docker-compose 的docker-compose up -d命令会智能对比新旧配置仅重启变更的服务且支持--no-deps参数跳过依赖服务重启实现零停机配置更新。Docker Compose 的v2.1格式Ubuntu 18.04 apt 源提供还隐藏了一个关键优势healthcheck指令。我们配置了curl -f http://localhost:5000/v2/ || exit 1作为健康检查配合restart: on-failure当 registry 因内存溢出崩溃时compose 会在 5 秒内自动重启而 systemd 的RestartSec5会因StartLimitInterval限制在 10 分钟内最多重启 5 次之后进入failed状态需人工干预。3. 核心组件安装与配置详解3.1 Ubuntu 18.04 系统预配置绕过经典陷阱在开始安装前必须修正 Ubuntu 18.04 的两个默认配置否则后续步骤必然失败。这不是过度谨慎而是血泪教训——我在三台不同品牌服务器上都复现了这些问题。第一个是APT 源的 HTTPS 证书信任问题。Ubuntu 18.04 默认安装的ca-certificates包版本为 20180409而某些企业内网镜像源如 Nexus Repository Manager使用较新的 Lets Encrypt R3 证书该证书的根 CA 在旧版 ca-certificates 中不存在。执行apt update时会出现The following signatures couldnt be verified because the public key is not available错误。解决方案不是升级整个 ca-certificates可能影响其他服务而是精准导入缺失证书# 下载 Lets Encrypt R3 根证书PEM 格式 wget -O /tmp/letsencrypt-r3.pem https://letsencrypt.org/certs/lets-encrypt-r3.pem # 将证书添加到系统信任库 sudo cp /tmp/letsencrypt-r3.pem /usr/local/share/ca-certificates/ sudo update-ca-certificates第二个是Docker 存储驱动兼容性。Ubuntu 18.04 默认使用overlay2存储驱动但某些老旧硬件特别是使用 Intel Atom 处理器的工控机的内核 4.15.0-xx-generic 存在 overlay2 的 race condition bug表现为 registry 容器启动后立即退出docker logs registry显示fatal error: concurrent map read and map write。此时必须强制切换为vfs驱动性能略低但绝对稳定# 创建 Docker daemon 配置文件 sudo mkdir -p /etc/docker echo {storage-driver: vfs} | sudo tee /etc/docker/daemon.json # 重启 Docker 服务 sudo systemctl restart docker # 验证驱动已切换 sudo docker info | grep Storage Driver提示vfs驱动会占用更多磁盘空间每个镜像层单独存储但对私有仓库场景影响极小。我们实测 100 个平均大小为 500MB 的镜像vfs比overlay2多占用约 12% 空间但避免了 90% 的随机崩溃。第三个是时区与时间同步。registry 的 token 认证严重依赖系统时间精度误差超过 15 分钟会导致token expired错误。Ubuntu 18.04 默认的systemd-timesyncd服务在某些虚拟化环境中同步不准。必须改用ntpd并配置企业内网 NTP 服务器# 卸载 timesyncd sudo systemctl stop systemd-timesyncd sudo systemctl disable systemd-timesyncd # 安装 ntp sudo apt install -y ntp # 编辑 NTP 配置替换为你的内网 NTP 地址 echo server 192.168.1.10 iburst | sudo tee -a /etc/ntp.conf # 重启 NTP 服务 sudo systemctl restart ntp # 验证时间同步状态 ntpq -p3.2 Docker Engine 与 Docker Compose 的精准安装Ubuntu 18.04 的 apt 源中 Docker 版本为 18.09.7这是经过充分验证的稳定版本。切勿使用snap install docker因为 snap 包在 Ubuntu 18.04 上存在 cgroup v1/v2 混用问题会导致 registry 容器内存限制失效。安装步骤必须严格遵循官方文档的 GPG 密钥验证流程任何跳过apt-key add的操作都可能导致中间人攻击# 更新包索引 sudo apt update # 安装必要依赖 sudo apt install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common # 添加 Docker 官方 GPG 密钥注意必须使用 curl -fsSL不能用 wget curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - # 验证密钥指纹应为 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88 sudo apt-key fingerprint 0EBFCD88 # 添加 stable 仓库注意xenial 对应 Ubuntu 16.04bionic 对应 18.04 echo deb [archamd64] https://download.docker.com/linux/ubuntu bionic stable | sudo tee /etc/apt/sources.list.d/docker.list # 更新包索引 sudo apt update # 安装指定版本的 Docker Engine sudo apt install -y docker-ce5:18.09.7~3-0~ubuntu-bionic docker-ce-cli5:18.09.7~3-0~ubuntu-bionic containerd.io # 验证安装 sudo docker --version # 输出应为 Docker version 18.09.7, build 2d0083dDocker Compose 的安装必须使用官方二进制包因为 apt 源中的版本1.17.1不支持v2.1compose 文件格式的关键特性如healthcheck# 下载最新稳定版截至 2024 年1.29.2 是 Ubuntu 18.04 兼容性最佳版本 sudo curl -L https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose # 添加执行权限 sudo chmod x /usr/local/bin/docker-compose # 创建软链接兼容旧脚本 sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose # 验证 docker-compose --version # 输出应为 docker-compose version 1.29.2, build 5becea4c注意不要使用pip install docker-compose。Ubuntu 18.04 的 pip3 默认版本为 18.1其依赖的 setuptools 版本与 docker-compose 1.29.2 冲突安装后执行docker-compose up会报ImportError: cannot import name main。这是社区公认的坑官方文档已明确警告。3.3 Nginx 的最小化安全配置Nginx 在此架构中不是 Web 服务器而是 API 网关。因此必须禁用所有与静态文件服务相关的模块只保留核心代理能力。我们删除了默认配置中 87% 的指令最终配置文件不足 50 行但覆盖了全部安全需求。首先创建专用用户和目录结构# 创建 nginx-proxy 用户无 shell无 home 目录 sudo useradd --shell /bin/false --no-create-home nginx-proxy # 创建配置目录 sudo mkdir -p /etc/nginx/conf.d /var/log/nginx-proxy # 设置日志目录权限 sudo chown nginx-proxy:adm /var/log/nginx-proxy sudo chmod 750 /var/log/nginx-proxy核心配置文件/etc/nginx/conf.d/docker-registry.conf如下# 全局设置禁用所有不必要的模块 user nginx-proxy; worker_processes auto; pid /run/nginx-proxy.pid; events { worker_connections 1024; use epoll; # Ubuntu 18.04 内核优化 } http { # 日志格式包含 Docker 客户端关键信息 log_format docker_registry $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent rt$request_time uct$upstream_connect_time uht$upstream_header_time urt$upstream_response_time docker_version$http_user_agent; access_log /var/log/nginx-proxy/access.log docker_registry; error_log /var/log/nginx-proxy/error.log warn; # 关键安全头 add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection 1; modeblock; # 禁用不安全的 HTTP 方法 if ($request_method !~ ^(GET|HEAD|POST|PUT|DELETE|OPTIONS|PATCH)$ ) { return 405; } # 代理核心配置 upstream registry_backend { server 127.0.0.1:5000; keepalive 32; } server { listen 443 ssl http2; server_name registry.example.com; # 替换为你的域名 # SSL 配置使用 Lets Encrypt ssl_certificate /etc/letsencrypt/live/registry.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/registry.example.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers off; # Docker registry 特定优化 client_max_body_size 0; # 允许任意大小镜像上传 client_body_timeout 600; # 上传超时设为 10 分钟 proxy_set_header Host $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_set_header X-Original-URI $request_uri; # 关键透传 Docker 必需的 header proxy_pass_request_headers on; proxy_pass_request_body on; proxy_http_version 1.1; proxy_set_header Connection ; # 路由到 registry 后端 location / { proxy_pass http://registry_backend; proxy_redirect off; } } # HTTP 到 HTTPS 重定向 server { listen 80; server_name registry.example.com; return 301 https://$server_name$request_uri; } }提示SSL 证书必须使用 Lets Encrypt 的fullchain.pem不能只用cert.pem。因为 Docker 客户端验证证书链时需要完整的中间证书。我们曾用自签名证书测试发现 macOS 客户端能连接而 Ubuntu 18.04 客户端报x509: certificate signed by unknown authority根源就是证书链不完整。3.4 Docker Registry 的定制化配置registry 的配置文件config.yml是整个方案的灵魂它决定了镜像如何存储、如何认证、如何缓存。我们摒弃了官方示例中复杂的 token 认证采用 Nginx 层面的 Basic Auth让 registry 专注存储逻辑。创建/opt/registry/config.ymlversion: 0.1 log: level: debug fields: service: registry hooks: - type: mail disabled: true storage: # 使用 filesystem driver路径指向 NFS 挂载点如 /mnt/nfs/registry filesystem: rootdirectory: /var/lib/registry # 启用 delete 功能默认关闭 delete: enabled: true # 启用 maintenance 模式便于离线备份 maintenance: uploadpurging: enabled: false http: addr: :5000 # 禁用 TLS由 Nginx 处理 tls: enabled: false # 启用 health check endpoint headers: X-Content-Type-Options: [nosniff] # 认证完全交给 Nginxregistry 不处理 auth: htpasswd: realm: basic-realm path: /dev/null # 指向空设备强制禁用 registry 自身认证 # 健康检查配置 health: storagedriver: enabled: true interval: 10s threshold: 3关键参数解释rootdirectory: /var/lib/registry必须使用绝对路径相对路径会导致 registry 启动失败。delete: enabled: true允许docker image rm命令删除镜像这是生产环境必需功能。maintenance.uploadpurging.enabled: false禁用自动清理避免备份期间误删上传中的镜像。auth.htpassw.path: /dev/null这是技巧所在。registry 启动时会尝试读取该文件/dev/null总是可读但内容为空从而跳过认证初始化把认证压力完全交给 Nginx。4. Docker Compose 编排与一键部署4.1 docker-compose.yml 文件深度解析docker-compose.yml不是简单的服务定义而是整个系统的运行契约。我们采用version: 2.1格式因为它支持healthcheck和depends_on.condition等关键特性而version: 3.x在 Ubuntu 18.04 的 docker-compose 1.29.2 中存在兼容性问题。完整配置文件/opt/registry/docker-compose.ymlversion: 2.1 services: registry: image: registry:2.7.1 restart: on-failure # 关键使用 host 网络模式避免 bridge 网络的 NAT 开销 network_mode: host # 挂载配置和存储卷 volumes: - /opt/registry/config.yml:/etc/docker/registry/config.yml:ro - /var/lib/registry:/var/lib/registry # 健康检查每 30 秒检查一次超时 3 秒失败 3 次后标记为 unhealthy healthcheck: test: [CMD, curl, -f, http://localhost:5000/v2/] interval: 30s timeout: 3s retries: 3 start_period: 40s # 环境变量禁用 registry 自身的认证 environment: - REGISTRY_AUTHhtpasswd - REGISTRY_AUTH_HTPASSWD_PATH/dev/null - REGISTRY_AUTH_HTPASSWD_REALMRegistry Realm nginx: image: nginx:1.18.0 restart: unless-stopped # 关键映射宿主机的 443/80 端口且必须使用 host 网络 network_mode: host volumes: - /etc/nginx/conf.d:/etc/nginx/conf.d:ro - /etc/letsencrypt:/etc/letsencrypt:ro - /var/log/nginx-proxy:/var/log/nginx-proxy # 依赖 registry 服务健康 depends_on: registry: condition: service_healthy # 健康检查确保 Nginx 进程存活且端口可访问 healthcheck: test: [CMD, curl, -f, http://localhost:443/healthz] interval: 20s timeout: 5s retries: 3 start_period: 30s # 全局配置 volumes: registry-data: driver: local注意network_mode: host是性能关键。在 Ubuntu 18.04 的 kernel 4.15 上bridge 网络的 iptables 规则会导致 registry 推送大镜像时出现 15-20% 的吞吐量下降。host 模式让容器直接使用宿主机网络栈实测 1GB 镜像推送时间从 217 秒降至 183 秒。4.2 一键部署脚本消除人为操作误差手动执行docker-compose up -d容易遗漏步骤。我们编写了deploy.sh脚本它自动完成 7 个关键动作#!/bin/bash # deploy.sh - Ubuntu 18.04 Docker Private Registry Deployment Script set -e # 任何命令失败立即退出 echo 正在执行 Docker 私有仓库部署 # 步骤 1创建必要目录 echo 1. 创建目录结构... sudo mkdir -p /opt/registry /var/lib/registry /etc/nginx/conf.d /var/log/nginx-proxy # 步骤 2复制配置文件假设已准备好 config.yml 和 docker-compose.yml echo 2. 复制配置文件... sudo cp ./config.yml /opt/registry/ sudo cp ./docker-compose.yml /opt/registry/ sudo cp ./docker-registry.conf /etc/nginx/conf.d/ # 步骤 3生成 Basic Auth 密码文件使用 htpasswd echo 3. 生成管理员密码... sudo apt install -y apache2-utils # 创建密码文件用户名 admin密码从环境变量读取或提示输入 if [ -z $REGISTRY_PASSWORD ]; then echo 请输入管理员密码 read -s REGISTRY_PASSWORD echo fi echo $REGISTRY_PASSWORD | sudo htpasswd -i -Bc /etc/nginx/.htpasswd admin # 步骤 4申请 SSL 证书使用 certbot echo 4. 申请 SSL 证书... sudo apt install -y python3-certbot-nginx sudo certbot --nginx -d registry.example.com --non-interactive --agree-tos -m adminexample.com # 步骤 5启动服务 echo 5. 启动 Docker Compose 服务... cd /opt/registry sudo docker-compose up -d # 步骤 6验证服务状态 echo 6. 验证服务状态... sudo docker-compose ps sudo docker-compose logs -f registry 21 | head -20 # 步骤 7测试连接 echo 7. 测试连接... curl -I https://registry.example.com/v2/ if [ $? -eq 0 ]; then echo ✅ 部署成功请使用 docker login https://registry.example.com 登录 else echo ❌ 部署失败请检查 /var/log/nginx-proxy/error.log exit 1 fi脚本执行逻辑set -e确保任何步骤失败立即终止避免半成品状态。htpasswd -i -Bc使用 bcrypt 加密-B并强制创建新文件-c避免密码明文泄露。certbot --nginx自动修改 Nginx 配置并申请证书比手动配置少出 90% 的错误。最后的curl -I测试使用-I参数只获取响应头不下载内容速度极快。4.3 首次登录与镜像推送实操部署完成后客户端操作必须严格遵循以下顺序任何颠倒都会导致认证失败第一步配置 Docker 客户端信任证书Ubuntu 18.04 客户端需将 Nginx 的 SSL 证书添加到 Docker 的信任库# 从 registry 服务器下载证书 openssl s_client -connect registry.example.com:443 -showcerts /dev/null 2/dev/null|openssl x509 -outform PEM /tmp/registry.crt # 复制到 Docker 证书目录 sudo mkdir -p /etc/docker/certs.d/registry.example.com:443 sudo cp /tmp/registry.crt /etc/docker/certs.d/registry.example.com:443/ca.crt # 重启 Docker 守护进程 sudo systemctl restart docker第二步登录私有仓库# 使用 Basic Auth 登录用户名 admin密码为 deploy.sh 中设置的密码 docker login https://registry.example.com # 输入用户名和密码后凭证会保存在 ~/.docker/config.json 中第三步推送测试镜像# 拉取一个基础镜像 docker pull ubuntu:20.04 # 重新打标签指向私有仓库 docker tag ubuntu:20.04 registry.example.com/myapp/ubuntu:20.04 # 推送到私有仓库 docker push registry.example.com/myapp/ubuntu:20.04 # 验证推送结果 curl -X GET https://registry.example.com/v2/_catalog?n100 -u admin:your_password # 应返回 {repositories:[myapp/ubuntu]}实操心得docker tag命令中的仓库地址必须与docker login的地址完全一致包括端口否则会报unauthorized: authentication required。我们曾因在docker login时用了https://registry.example.com而在docker tag时用了registry.example.com缺 https导致推送失败。这个细节在官方文档中被严重低估。5. 运维监控与故障排查实战5.1 关键监控指标与告警阈值私有仓库不是部署完就高枕无忧必须建立三层监控体系第一层基础设施层docker ps -a | grep registry | grep -c Exitedregistry 容器退出次数1 小时内 3 次即告警。df -h /var/lib/registry | awk NR2 {print $5} | sed s/%//存储空间使用率 85% 触发清理脚本。ss -tlnp | grep :443 | wc -lNginx 监听连接数 1000 表示连接池饱和。第二层服务健康层curl -f http://localhost:5000/v2/ 2/dev/null || echo registry downregistry HTTP 健康检查。curl -I https://registry.example.com/v2/ 2/dev/null | head -1 | grep 200 OK端到端 HTTPS 可达性。sudo tail -n 100 /var/log/nginx-proxy/access.log | awk {print $9} | sort | uniq -c | sort -nr | head -5统计最近 100 条日志中的错误码500出现 5 次需立即排查。第三层业务逻辑层curl -X GET https://registry.example.com/v2/_catalog?n1 -u admin:password 2/dev/null | jq .repositories | length镜像仓库总数24 小时内无增长需检查 CI/CD 流水线。sudo find /var/lib/registry -name manifests -type d -mtime 30 | wc -l30 天未更新的镜像数量 50 个触发自动归档。我们用一个 32 行的 Bash 脚本实现了全自动巡检每天 4 点执行结果邮件发送给运维组#!/bin/bash # health-check.sh REPORT$(mk