Shell脚本如何配置私有镜像仓库:企业级自动化部署实战指南
目录导读
- 私有镜像仓库的核心价值 – 为什么你需要自建镜像仓库?
- 环境准备与仓库选型 – Harbor、Registry、Nexus对比
- Shell脚本实现仓库配置 – 从Docker守护进程到认证交互
- 自动化推送与拉取镜像 – 脚本中的HTTPS与安全策略
- 常见故障与问答 – 403错误、证书问题、Cgroup驱动冲突
私有镜像仓库的核心价值
在容器化开发流程中,私有镜像仓库是连接CI/CD流水线的枢纽,通过Shell脚本配置私有镜像仓库,你可以实现以下目标:

- 加速镜像拉取:公网仓库可能因限流、地域延迟影响部署效率。
- 安全合规:敏感业务镜像无需上传至公网,规避数据泄露风险。
- 版本控制:结合Git标签自动生成镜像版本,避免“latest”混乱。
关键场景:某金融科技公司通过内网Harbor仓库,将镜像部署时间从25秒降至2秒(基于1Gbps内网带宽测试)。
环境准备与仓库选型
主流方案对比
| 仓库类型 | 推荐场景 | 资源占用 | 认证方式 | 脚本友好度 |
|---|---|---|---|---|
| Harbor | 企业级,需要UI、多租户 | 2C4G起步 | LDAP/OAuth/基础认证 | 中(API复杂) |
| Registry 2.0 | 轻量级、测试环境 | 256MB内存足够 | 基础认证 | 高(纯命令行) |
| Nexus Repository | Java生态、通用制品 | 4C8G起步 | 集成LDAP | 低(XML配置) |
推荐选择:如果你需要Shell脚本自动化配置,Registry 2.0 结合 nginx 反向代理是最灵活的方式,以下脚本示例默认使用Registry v2。
Shell脚本实现仓库配置
1 基础配置脚本(一键搭建)
#!/bin/bash
# 文件名: setup-private-registry.sh
# 用途: 在 CentOS 7.9+/Ubuntu 20.04 上部署私有镜像仓库
REGISTRY_NAME="myregistry.internal"
REGISTRY_PORT="5000"
DATA_DIR="/data/registry"
CERT_DIR="/etc/ssl/registry"
# 第1步:创建目录与自签名证书(生产环境请使用CA签发)
mkdir -p ${DATA_DIR} ${CERT_DIR}
openssl req -newkey rsa:4096 -nodes -sha256 -keyout ${CERT_DIR}/domain.key \
-x509 -days 3650 -out ${CERT_DIR}/domain.crt \
-subj "/C=CN/ST=Beijing/L=Beijing/O=DevOps/CN=${REGISTRY_NAME}"
# 第2步:配置Docker守护进程信任私仓证书
if [ -d /etc/docker/certs.d ]; then
mkdir -p /etc/docker/certs.d/${REGISTRY_NAME}:${REGISTRY_PORT}
cp ${CERT_DIR}/domain.crt /etc/docker/certs.d/${REGISTRY_NAME}:${REGISTRY_PORT}/ca.crt
fi
# 第3步:启动Registry容器(内置基本认证)
docker run -d --restart=always --name registry \
-v ${DATA_DIR}:/var/lib/registry \
-v ${CERT_DIR}:/certs \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
-e REGISTRY_AUTH=htpasswd \
-e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-v ${DATA_DIR}/auth:/auth \
-p ${REGISTRY_PORT}:5000 \
registry:2.8.3
# 第4步:创建初始用户(admin/密码:Admin123!)
docker exec registry htpasswd -Bbn admin Admin123! > ${DATA_DIR}/auth/htpasswd
echo "私有仓库已就绪:https://${REGISTRY_NAME}:${REGISTRY_PORT}"
echo "用户:admin / 密码:Admin123!"
2 客户端登录脚本(自动交互)
#!/bin/bash
# login-private-registry.sh
REGISTRY_URL="myregistry.internal:5000"
USER="admin"
PASS="Admin123!"
CERT_FILE="/etc/docker/certs.d/${REGISTRY_URL}/ca.crt"
# 首次登录前先将证书加入系统信任
if [ ! -f "${CERT_FILE}" ]; then
echo "错误:未找到证书文件,请先执行 setup-private-registry.sh"
exit 1
fi
# 使用 expect 或 docker login 结合变量(非交互式)
echo "${PASS}" | docker login ${REGISTRY_URL} -u ${USER} --password-stdin
if [ $? -eq 0 ]; then
echo "登录成功!可通过 ${REGISTRY_URL} 推送/拉取镜像。"
else
echo "登录失败,请检查用户名密码或HTTPS证书。"
fi
自动化推送与拉取镜像
批量推送脚本(支持多镜像)
#!/bin/bash
# push-images.sh - 将本地镜像批量推送至私有仓库
PRIVATE_REGISTRY="myregistry.internal:5000"
IMAGE_LIST=("nginx:1.25" "postgres:16" "alpine:3.19")
DEST_PREFIX="${PRIVATE_REGISTRY}/myteam"
for img in "${IMAGE_LIST[@]}"; do
echo "正在处理:${img}..."
# 步骤1:拉取公网镜像(若本地不存在)
docker pull ${img} 2>/dev/null || echo "本地已有:${img}"
# 步骤2:打标签并推送
docker tag ${img} ${DEST_PREFIX}/${img}
docker push ${DEST_PREFIX}/${img}
# 步骤3:清理临时标签(保留原始镜像)
docker rmi ${DEST_PREFIX}/${img}
done
echo "所有镜像推送完成!"
echo "可以通过以下命令验证:"
echo "curl -k https://${PRIVATE_REGISTRY}/v2/_catalog | jq ."
常见故障与问答
Q1:为什么 docker push 返回 “403 Forbidden”?
A:最常见的原因是认证失效或令牌(Token)过期。
解决:
- 重新执行
docker login脚本。 - 检查htpasswd文件是否生成正确:
docker exec registry cat /auth/htpasswd。 - 若使用 Harbor,需检查用户是否有“推送”角色。
Q2:配置后仍提示“x509: certificate signed by unknown authority”?
A:Docker守护进程未信任自签名证书。
解决:
- 确保
/etc/docker/certs.d/仓库地址/目录下ca.crt存在。 - 重启Docker服务:
systemctl restart docker。 - 如果使用Rootless模式,证书路径需改为
~/.config/docker/certs.d/。
Q3:脚本执行后 curl 访问能通过,但 docker pull 失败?
A:检查是否使用了私有仓库的内部域名,Docker会跳过DNS解析,直接尝试IP连接。
验证:在 /etc/hosts 添加映射:
echo "192.168.1.100 myregistry.internal" >> /etc/hosts
Q4:如何从脚本中更新已有镜像的标签?
A:使用 docker tag 配合循环:
for tag in v1.0 v1.1; do
docker tag myapp:${tag} ${PRIVATE_REGISTRY}/myapp:${tag}
docker push ${PRIVATE_REGISTRY}/myapp:${tag}
done
最佳实践要点
通过以上Shell脚本,你可以快速配置一个生产级私有镜像仓库,记住三个核心原则:
- 证书先行 – 无论是否生产环境,永远使用HTTPS(自签名至少比明文安全)。
- 认证隔离 – 每个团队应使用独立htpasswd或集成LDAP,避免“超级管理员”通行所有仓库。
- 垃圾回收 – 定期执行
docker exec registry /bin/registry garbage-collect /etc/docker/registry/config.yml清理废弃层。
扩展建议:在CI/CD流水线中,将 setup-private-registry.sh 作为初始化步骤,配合Ansible管理多节点证书分发,可实现5分钟部署一套完整的私有仓库集群。