🚀 使用 Docker Compose 部署 Docker Registry
🚀 使用 Docker Compose 部署 Docker Registry
Docker Registry 是一个开源、无状态、高度可扩展的服务器端应用程序,用于存储和分发 Docker 镜像。它通过提供资源访问控制来管理您的基础架构,以安全、私有的方式管理整个容器生命周期。
📦 项目简介
Docker Registry 的核心目标是提供一个安全、高效的私有镜像存储和分发解决方案。它与所有官方 Docker 工具完全兼容,让你可以在自己的基础设施上构建完整的容器化工作流。
主要功能特点: * 安全存储:提供安全的私有镜像存储,防止敏感镜像泄露到公网。 * 高效分发:支持局域网内快速镜像分发,大幅提升 CI/CD 流程效率。 * 访问控制:支持基于 htpasswd 的基本身份验证,确保只有授权用户才能访问。 * 镜像管理:支持镜像的推送、拉取和删除操作,并可通过垃圾回收清理无用数据。 * 代理缓存:可作为 Docker Hub 的缓存代理,减少重复下载并提升拉取速度。
⚙️ 部署前准备
-
环境要求
- 已安装 Docker 和 Docker Compose。
- 系统内存:建议 1GB 以上。
- 确保服务器的 5000 端口未被占用。
-
环境检查 在终端中执行以下命令,确认 Docker 环境正常:
docker --version
docker-compose --version
- 创建项目目录 建议创建一个独立的目录来管理 Registry 的所有文件:
#mkdir -p /opt/docker/registry
#cd /opt/docker/registry
#自用专用的路径 '/home/compose' 创建容器目录
mkdir -p /home/compose/docker-registry
cd /home/compose/docker-registry
🛠️ 配置 Docker Compose
基于你提供的配置,这里是对配置文件的优化和完整说明:
1. 创建 docker-compose.yml
#networks:
#registry:
#external: true
services:
registry:
ports:
- 5000:5000 # 端口映射:主机 5000 → 容器 5000(镜像推拉端口)
volumes:
- ./data:/var/lib/registry # 镜像数据存储目录(核心,持久化镜像文件)
- ./config.yml:/etc/docker/registry/config.yml # 挂载自定义配置文件
# 移除 config.yml 挂载 - 使用环境变量配置
# 可选:挂载认证文件
# - ./auth:/auth
container_name: registry # 挂载自定义配置文件
environment:
#- REGISTRY_HTTP_TLS=false # 必须启用
- REGISTRY_HTTP_ADDR=0.0.0.0:5000 # 容器内监听地址(允许外部访问)
- REGISTRY_STORAGE_DELETE_ENABLED=true #- 注册表存储删除已启用 true
# 可选:添加身份验证
# - REGISTRY_AUTH=htpasswd
# - REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm
# - REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd
restart: always # 容器退出后自动重启(确保服务稳定运行)
#image: registry:2
image: registry:2.7.1 # 使用稳定版本(2.7.1 兼容性好,避免最新版bug)
#networks:
#registry:
#ipv4_address: 10.1.1.7
#docker network create registry --subnet 10.1.1.0/24 --gateway 10.1.1.1
关键配置说明:
| 配置项 | 说明与建议 |
|---|---|
image |
使用特定版本 2.7.1 以确保稳定性,避免自动升级带来的兼容性问题。 |
ports |
"5000:5000" 将容器内的 5000 端口映射到主机的 5000 端口。 |
volumes |
./data:/var/lib/registry 用于持久化存储所有镜像数据,务必确保此配置。./config.yml:/etc/docker/registry/config.yml 挂载自定义配置文件。 |
environment |
REGISTRY_STORAGE_DELETE_ENABLED=true 启用镜像删除功能。 |
config.yml |
proxy.remoteurl 上游镜像源:国内用户建议改为 https://docker.mirrors.ustc.edu.cn(中科大镜像),加速公共镜像拉取。 |
config.yml |
storage.delete.enabled: true 必须设为 true,否则无法删除旧镜像,导致磁盘占用越来越大。 |
config.yml |
tls.disabled: true 仅适合本地 / 内网使用,若需公网访问,需开启 TLS 并配置证书(否则 Docker 引擎会拒绝连接)。 |
clean.sh |
脚本路径与权限 需确保路径 /home/compose/docker-registry 与实际部署目录一致,且脚本有执行权限(chmod +x)。 |
2. 创建 config.yml 配置文件
version: 0.1
log:
fields:
service: registry # 日志标识(便于区分其他服务日志)
# 可选:代理缓存配置(作为 Docker Hub 镜像)
proxy: #remoteurl: https://docker.mirrors.ustc.edu.cn
remoteurl: https://registry-1.docker.io # 上游镜像源(默认 Docker Hub,国内可改为 https://docker.mirrors.ustc.edu.cn 加速)
# 缓存所有命名空间
#username: [""]
#password: [""]
#username: ""
#password: ""
storage:
filesystem:
rootdirectory: /var/lib/registry #安全增强 # 镜像存储路径(与容器内路径一致)
cache:
blobdescriptor: inmemory #内存缓存加速元数据访问 # 元数据缓存到内存(加速镜像信息查询)
delete:
enabled: true # 允许删除旧镜像(默认关闭,需手动开启)
http:
addr: :5000 # 监听端口(与 docker-compose.yml 一致)
headers:
X-Content-Type-Options: [nosniff] # 安全头配置(防止 MIME 类型嗅探)
#X-Content-Type-Options: ["nosniff"] # 注意这里的数组格式
tls:
disabled: true # 禁用 TLS(仅本地/内网使用,公网需开启并配置证书)
#health:
#storagedriver:
#enabled: true
#interval: 10s
#threshold: 3
3. 设置身份验证(可选但推荐)
为 Registry 添加基本身份验证:
# 创建认证目录
mkdir -p auth
# 生成用户名和密码文件
docker run --rm --entrypoint htpasswd httpd:2 -Bbn 用户名 密码 > auth/htpasswd
然后在 docker-compose.yml 中取消注释认证相关的环境变量和卷挂载。
3. 步骤 1:编写 clean.sh 清理脚本
在部署主目录创建 clean.sh(用于定时清理镜像缓存,释放磁盘空间):
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# 记录日志(包含时间戳)
echo "[$(date)] 开始执行清理脚本" >> /var/log/clean_script.log 2>&1
echo "缓存删除"
rm -rf /home/compose/docker-registry/data # 删除镜像数据目录(清理所有缓存)
echo "缓存删除完成" >> /var/log/clean_script.log 2>&1
echo "关闭服务"
/usr/local/bin/docker-compose -f /home/compose/docker-registry/docker-compose.yml down >> /var/log/clean_script.log 2>&1
echo "服务已关闭" >> /var/log/clean_script.log 2>&1
echo "启动服务"
/usr/local/bin/docker-compose -f /home/compose/docker-registry/docker-compose.yml up -d >> /var/log/clean_script.log 2>&1
echo "服务已启动" >> /var/log/clean_script.log 2>&1
echo "[$(date)] 脚本执行完毕" >> /var/log/clean_script.log 2>&1
再添加执行权限 chmod +x /home/compose/docker-registry/clean.sh #'上次是/home/compose/docker-registry/1/clean.sh'
**3. 步骤 2. 定时清理缓存(使用 clean.sh)
通过 crontab 设置定时任务,定期执行 clean.sh 清理镜像数据(适合测试环境,生产环境慎用):
1.编辑定时任务:
crontab -e
2.添加以下内容(每周日凌晨 3 点执行清理):
0 3 * * 0 /home/compose/docker-registry/clean.sh
#0 2 * * * /home/compose/docker-registry/1/clean.sh #这是以前的每天凌晨2点清理一次
3.保存退出,定时任务生效(日志保存在 /var/log/clean_script.log)。
🚀 启动与验证
-
启动 Registry 服务 在
docker-compose.yml文件所在目录执行:bash docker-compose up -d此命令会拉取镜像并在后台启动容器。 -
检查服务状态
bash docker-compose ps如果看到registry容器的状态为Up,说明服务已成功启动。 -
查看实时日志
bash docker-compose logs -f registry -
测试服务连通性
bash curl http://localhost:5000/v2/如果返回{},说明 Registry 服务正常运行。
⚙️ 基础配置与使用
-
配置客户端访问 由于我们使用的是 HTTP 而非 HTTPS,需要在客户端 Docker 守护进程配置中注册不安全 Registry:服务端也写上这个文件,以免直接拉取失败。
编辑
/etc/docker/daemon.json:
{
"insecure-registries": ["你的服务器IP:5000"] # 替换为实际服务器IP(如 "192.168.1.100:5000")
}
然后重启 Docker 服务:
sudo systemctl daemon-reload
sudo systemctl restart docker
#sudo systemctl daemon-reload && sudo systemctl restart docker
实测客户端拉取时写入,编辑 /etc/docker/daemon.json:
{
"registry-mirrors": ["http://你的服务器IP:5000"],
"insecure-registries": ["你的服务器IP:5000"]
}
-
推送和拉取镜像
- 登录 Registry(如果设置了身份验证):
bash docker login 你的服务器IP:5000 - 标记现有镜像:
bash docker tag 本地镜像:tag 你的服务器IP:5000/镜像名:tag - 推送镜像到私有仓库:
bash docker push 你的服务器IP:5000/镜像名:tag - 从私有仓库拉取镜像:
bash docker pull 你的服务器IP:5000/镜像名:tag
- 登录 Registry(如果设置了身份验证):
-
查看仓库内容
- 列出所有仓库:
bash curl http://你的服务器IP:5000/v2/_catalog - 列出特定镜像的所有标签:
bash curl http://你的服务器IP:5000/v2/镜像名/tags/list
- 列出所有仓库:
⚙️ 基础配置与使用2
1. 配置 “不安全仓库”(非 TLS 环境必备)
若未启用 TLS(tls.disabled: true),Docker 引擎默认拒绝连接 HTTP 仓库,需手动配置:
- Linux 系统:
编辑
/etc/docker/daemon.json(若不存在则创建):
{
"insecure-registries": ["服务器IP:5000"] # 替换为实际服务器IP(如 "192.168.1.100:5000")
}
重启 Docker 引擎生效:
sudo systemctl daemon-reload && sudo systemctl restart docker
2. 推送自定义镜像到私有仓库
开发自定义镜像后,按以下步骤推送到私有仓库供团队使用:
1.构建自定义镜像(示例):
# 创建 Dockerfile(简单示例)
echo "FROM alpine:latest" > Dockerfile
docker build -t my-app:v1 . # 构建镜像
2.标记为私有仓库格式:
docker tag my-app:v1 服务器IP:5000/my-app:v1
3.推送镜像:
docker push 服务器IP:5000/my-app:v1
3. 删除旧镜像(释放磁盘空间)
当镜像过多时,可删除不再使用的镜像(需 storage.delete.enabled: true):
1.获取镜像的 digest(唯一标识):
# 查看仓库中镜像的标签和 digest
curl http://服务器IP:5000/v2/my-app/tags/list # 查看标签
curl http://服务器IP:5000/v2/my-app/manifests/v1 # 查看 v1 标签对应的 digest(在响应头 "Docker-Content-Digest" 中)
2.删除镜像(替换 digest):
curl -X DELETE http://服务器IP:5000/v2/my-app/manifests/sha256:xxx... # 替换为实际 digest
3.清理未引用的镜像文件(释放磁盘):
# 进入容器执行清理命令
docker exec -it registry /bin/sh
registry garbage-collect /etc/docker/registry/config.yml # 清理无用文件
exit
🔒 维护与管理
-
服务管理:
- 停止服务:
docker-compose down - 重启服务:
docker-compose restart - 查看服务状态:
docker-compose ps
- 停止服务:
-
数据备份:
- 定期备份
./data目录,这里包含了所有镜像数据。 - 备份
config.yml和docker-compose.yml配置文件。
- 定期备份
-
垃圾回收: Registry 不会自动删除未引用的层,需要手动执行垃圾回收:
docker-compose exec registry bin/registry garbage-collect /etc/docker/registry/config.yml
-
日志管理: 配置日志轮转,避免日志文件占用过多磁盘空间。
-
清理脚本优化: 你提供的清理脚本过于激进(会删除整个数据目录)。建议改用以下方式进行清理:
#!/bin/bash
echo "[$(date)] 开始清理操作" >> /var/log/registry_clean.log
# 执行垃圾回收
docker-compose exec registry bin/registry garbage-collect /etc/docker/registry/config.yml >> /var/log/registry_clean.log 2>&1
echo "[$(date)] 清理完成" >> /var/log/registry_clean.log
🐛 常见问题排查
| 问题现象 | 可能原因与解决方法 |
|---|---|
| 无法推送镜像,报 HTTPS 错误 | 客户端未配置不安全 Registry,检查 /etc/docker/daemon.json 中的 insecure-registries 配置。 |
| 推送镜像时提示"权限被拒绝" | 未配置身份验证或认证失败,检查认证文件路径和权限。 |
| 服务启动失败 | 检查端口是否被占用,或配置文件格式是否正确。 |
| 磁盘空间不足 | 定期执行垃圾回收,清理未引用的镜像层。 |
| 性能问题 | 考虑配置 Redis 缓存,或调整存储后端配置。 |
💡 性能优化提示:对于高并发场景,可以考虑配置 Redis 作为缓存后端,并确保 storage.cache.blobdescriptor 设置为 inmemory 以提升元数据访问性能。
希望这份教程能帮助你顺利完成 Docker Registry 的部署,享受安全高效的私有镜像管理体验!
🐛 常见问题排查2
1. 推送镜像提示 “http: server gave HTTP response to HTTPS client”
- 原因:Docker 引擎默认要求仓库使用 HTTPS,未配置 “不安全仓库”。
- 解决:按 “基础配置与使用 - 步骤 1” 添加
insecure-registries,重启 Docker 引擎。
2. 拉取 / 推送镜像提示 “connection refused”
-
原因 1:5000 端口未开放或被占用。解决:检查端口占用
netstat -tuln | grep 5000,释放或修改docker-compose.yml中的端口(如5001:5000),重启容器。 -
原因 2:容器未正常启动。解决:查看容器日志
docker compose logs registry,修复错误(如配置文件格式错误)后重启。
3. 上游缓存不生效(每次拉取都访问公网)
- 原因:
config.yml中proxy.remoteurl配置错误,或拉取命令格式不正确。 - 解决:
- 确认
proxy.remoteurl为有效镜像源(如https://docker.mirrors.ustc.edu.cn); - 拉取命令需带私有仓库前缀:
docker pull 服务器IP:5000/nginx:latest(而非直接docker pull nginx:latest)。
- 确认
4. 无法删除镜像(提示 “method not allowed”)
- 原因:
config.yml中storage.delete.enabled未设为true。 - 解决:修改
config.yml中storage.delete.enabled: true,重启容器后重试。
5. 磁盘占用过大(./data 目录过大)
- 原因:镜像未及时清理,或
garbage-collect未执行(删除镜像后需手动清理无用文件)。 - 解决:执行容器内清理命令:
docker exec -it registry registry garbage-collect /etc/docker/registry/config.yml
通过以上步骤,新手可快速搭建私有 Docker 镜像仓库,实现镜像的本地管理与分发。如需生产环境使用,建议开启 TLS 加密、配置访问权限(如用户名密码),进一步提升安全性。详细高级配置可参考 Docker Registry 官方文档。