Skip to content

🚀 使用 Docker Compose 部署 Docker Registry

🚀 使用 Docker Compose 部署 Docker Registry

Docker Registry 是一个开源、无状态、高度可扩展的服务器端应用程序,用于存储和分发 Docker 镜像。它通过提供资源访问控制来管理您的基础架构,以安全、私有的方式管理整个容器生命周期。

📦 项目简介

Docker Registry 的核心目标是提供一个安全、高效的私有镜像存储和分发解决方案。它与所有官方 Docker 工具完全兼容,让你可以在自己的基础设施上构建完整的容器化工作流。

主要功能特点: * 安全存储:提供安全的私有镜像存储,防止敏感镜像泄露到公网。 * 高效分发:支持局域网内快速镜像分发,大幅提升 CI/CD 流程效率。 * 访问控制:支持基于 htpasswd 的基本身份验证,确保只有授权用户才能访问。 * 镜像管理:支持镜像的推送、拉取和删除操作,并可通过垃圾回收清理无用数据。 * 代理缓存:可作为 Docker Hub 的缓存代理,减少重复下载并提升拉取速度。

⚙️ 部署前准备

  1. 环境要求

    • 已安装 DockerDocker Compose
    • 系统内存:建议 1GB 以上。
    • 确保服务器的 5000 端口未被占用。
  2. 环境检查 在终端中执行以下命令,确认 Docker 环境正常:

docker --version
docker-compose --version
  1. 创建项目目录 建议创建一个独立的目录来管理 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)。

🚀 启动与验证

  1. 启动 Registry 服务docker-compose.yml 文件所在目录执行: bash docker-compose up -d 此命令会拉取镜像并在后台启动容器。

  2. 检查服务状态 bash docker-compose ps 如果看到 registry 容器的状态为 Up,说明服务已成功启动。

  3. 查看实时日志 bash docker-compose logs -f registry

  4. 测试服务连通性 bash curl http://localhost:5000/v2/ 如果返回 {},说明 Registry 服务正常运行。

⚙️ 基础配置与使用

  1. 配置客户端访问 由于我们使用的是 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"]
}
  1. 推送和拉取镜像

    • 登录 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
  2. 查看仓库内容

    • 列出所有仓库: 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.ymldocker-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 配置错误,或拉取命令格式不正确。
  • 解决
    1. 确认 proxy.remoteurl 为有效镜像源(如 https://docker.mirrors.ustc.edu.cn);
    2. 拉取命令需带私有仓库前缀: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 官方文档