Sign inSign up

zunshen/registry-sync

By zunshen

•Updated 10 months ago

Registry Sync - Docker Image Synchronization Tool

Image
0

1.1K

zunshen/registry-sync repository overview

⁠Registry Sync

Version Go Version License Docker

企业级 Docker/Harbor 镜像同步管理平台

轻松实现跨 Registry 镜像同步,支持多架构镜像、定时任务、实时通知

快速开始⁠ • 功能特性⁠ • 部署指南⁠ • 用户手册⁠ • API 文档⁠


⁠✨ 功能特性

⁠🚀 核心能力
  • 镜像同步 - 基于 Docker Registry V2 API,直接操作 Blob 和 Manifest,无需 Docker Daemon
  • 多架构支持 - 自动识别并同步 Manifest List(multi-arch),支持 amd64/arm64/arm 等
  • 智能过滤 - 正则表达式匹配 Tag、黑名单过滤、保留最新 N 个版本
  • 定时任务 - 友好的 Cron 表达式配置,支持预设(每天、每周、每月等)
  • 实时通知 - 企业微信、钉钉通知,任务执行结果及时推送
  • 进度追踪 - WebSocket 实时推送同步进度和日志
  • Web 管理 - 现代化 React UI,操作简单直观
⁠🎯 企业级特性
  • 数据持久化 - SQLite 存储任务配置和执行历史
  • 容器化部署 - 提供 Docker 镜像和 Docker Compose 配置
  • Kubernetes 支持 - 完整的 K8s 部署 YAML
  • 健康检查 - 内置健康检查接口,便于监控
  • 并发控制 - 支持并发同步多个 Blob,提升效率
  • 增量同步 - 只传输新增或变更的 Blob,节省带宽

⁠📦 快速开始

⁠方式一:Docker Compose(推荐)
# 1. 下载 docker-compose.yml
curl -O https://raw.githubusercontent.com/yunzck8s/registry-sync/main/docker-compose.yml

# 2. 启动服务
docker-compose up -d

# 3. 访问 Web 界面
open http://localhost:8080
⁠方式二:Docker 命令
# 拉取镜像
docker pull zunshen/registry-sync:latest

# 运行容器
docker run -d \
  --name registry-sync \
  -p 8080:8080 \
  -v ./data:/app/data \
  -e TZ=Asia/Shanghai \
  zunshen/registry-sync:latest

# 访问 Web 界面
open http://localhost:8080
⁠方式三:Kubernetes
# 部署到 K8s 集群
kubectl apply -k https://github.com/yunzck8s/registry-sync/k8s

# 查看服务状态
kubectl get pods -n registry-sync

⁠🎨 界面预览

⁠仪表盘
  • 实时统计:任务数、执行记录、成功/失败率
  • 最近执行记录列表
  • 快速操作入口
⁠Registry 管理
  • 添加/编辑 Docker Hub、Harbor、ACR 等 Registry
  • 测试连接功能
  • 浏览项目和仓库列表
⁠任务管理
  • 可视化创建同步任务
  • 源/目标 Registry 选择
  • Tag 过滤规则配置(支持正则)
  • 架构选择(amd64/arm64)
  • Cron 定时任务设置(预设 + 自定义)
  • 立即运行/停止/编辑/删除
⁠执行历史
  • 查看所有执行记录
  • 实时进度展示(进度条 + 百分比)
  • 详细日志查看
  • 执行时间和耗时统计
  • 状态过滤和搜索
⁠通知管理
  • 企业微信/钉钉 Webhook 配置
  • 通知条件设置(全部/仅失败)
  • 测试发送功能
  • 多渠道管理

⁠🚀 部署方式

⁠Docker Compose 部署

docker-compose.yml

version: '3.8'
services:
  registry-sync:
    image: zunshen/registry-sync:latest
    container_name: registry-sync
    restart: unless-stopped
    ports:
      - "8080:8080"
    volumes:
      - ./data:/app/data
    environment:
      - TZ=Asia/Shanghai
    healthcheck:
      test: ["CMD", "wget", "--spider", "http://localhost:8080/api/v1/health"]
      interval: 30s
      timeout: 3s
      retries: 3
docker-compose up -d
⁠Kubernetes 部署

完整部署配置

# 1. 克隆仓库
git clone https://github.com/yunzck8s/registry-sync.git
cd registry-sync/k8s

# 2. 修改配置(可选)
# - 修改 ingress.yaml 中的域名
# - 修改 pvc.yaml 中的存储大小

# 3. 部署
kubectl apply -k .

# 4. 查看状态
kubectl get all -n registry-sync

# 5. 访问服务
# - ClusterIP: kubectl port-forward -n registry-sync svc/registry-sync 8080:8080
# - Ingress: https://your-domain.com

K8s 资源说明

  • Namespace: registry-sync(独立命名空间)
  • Deployment: 单副本部署
  • PVC: 10Gi 持久化存储(可调整)
  • Service: ClusterIP 类型
  • Ingress: 可选,需配置域名和 TLS

资源限制

resources:
  requests:
    memory: "256Mi"
    cpu: "250m"
  limits:
    memory: "512Mi"
    cpu: "500m"
⁠从源码构建

前置要求

  • Go 1.25+
  • Node.js 18+
  • npm 或 yarn

步骤

# 1. 克隆代码
git clone https://github.com/yunzck8s/registry-sync.git
cd registry-sync

# 2. 构建前端
cd web
npm install
npm run build

# 3. 构建后端
cd ..
go build -o registry-sync-server ./cmd/server

# 4. 运行
./registry-sync-server --port 8080 --db data/registry-sync.db

Docker 镜像构建

# 构建镜像
docker build -t registry-sync:latest .

# 运行
docker run -d -p 8080:8080 -v ./data:/app/data registry-sync:latest

⁠📖 用户手册

⁠1. 添加 Registry
  1. 点击左侧菜单 Registry 管理
  2. 点击右上角 添加 Registry 按钮
  3. 填写配置信息:
    • 名称:自定义名称(如:Docker Hub、Harbor 生产)
    • URL:Registry 地址
      • Docker Hub: https://registry-1.docker.io
      • Harbor: https://harbor.example.com
      • 阿里云 ACR: https://registry.cn-hangzhou.aliyuncs.com
    • 用户名/密码:认证凭据
    • 启用:是否立即启用
  4. 点击 测试连接 验证配置
  5. 点击 确定 保存

提示:

  • 密码字段不会回显,重新编辑时留空表示不修改
  • Docker Hub 需要使用个人 Token 而非密码
⁠2. 创建同步任务
  1. 点击左侧菜单 任务管理
  2. 点击右上角 创建任务 按钮
  3. 配置任务信息:

基础配置

  • 任务名称:描述性名称(如:同步 Nginx 到生产)
  • 启用:是否立即启用任务

源配置

  • 源 Registry:选择源镜像仓库
  • 项目:选择项目(Harbor)或命名空间(Docker Hub)
  • 仓库:
    • 留空:同步整个项目的所有仓库
    • 指定:只同步指定仓库

目标配置

  • 目标 Registry:选择目标镜像仓库
  • 项目:选择或输入新项目名
  • 仓库:
    • 留空:自动使用源仓库名
    • 指定:使用自定义仓库名

Tag 过滤规则

  • 包含 Tag(正则):匹配要同步的 Tag
    • 示例:^1\.2[0-9]\..* 匹配 1.2x 版本
    • 多个规则用逗号分隔
    • 留空:同步所有 Tag
  • 排除 Tag(正则):排除不需要的 Tag
    • 示例:.*-alpine,.*-debug 排除 alpine 和 debug 版本
  • 保留最新 N 个:只同步最新的 N 个 Tag
    • 0 表示不限制

架构选择

  • 多选:amd64、arm64、arm/v7、386
  • 留空:同步所有架构

定时任务设置

  • 不启用定时任务:手动执行
  • 每小时执行:0 * * * *
  • 每天凌晨2点:0 2 * * *
  • 每天中午12点:0 12 * * *
  • 每周一凌晨2点:0 2 * * 1
  • 每月1号凌晨2点:0 2 1 * *
  • 每6小时执行:0 */6 * * *
  • 每12小时执行:0 */12 * * *
  • 自定义:手动输入 Cron 表达式

通知配置

  • 启用通知:开关
  • 通知条件:
    • 全部发送(成功+失败)
    • 仅失败时发送
  • 通知渠道:选择已配置的通知渠道(可多选)
  • 定时任务提示:频繁执行的任务会产生大量通知
  1. 点击 确定 创建任务
⁠3. 执行任务

手动执行

  1. 在任务列表找到目标任务
  2. 点击 立即运行 按钮
  3. 跳转到执行历史页面查看进度

停止执行

  1. 在任务列表或执行历史页面
  2. 点击 停止 按钮(只能停止运行中的任务)

查看执行日志

  1. 点击左侧菜单 执行历史
  2. 点击任务的 查看日志 按钮
  3. 实时查看同步进度和详细日志
⁠4. 通知配置

添加企业微信通知

  1. 在企业微信中创建群机器人
  2. 获取 Webhook URL
  3. 在系统中点击 通知管理 → 添加通知渠道
  4. 填写:
    • 名称:企业微信-运维群
    • 类型:企业微信
    • Webhook URL:粘贴获取的 URL
    • 启用:是
  5. 点击 测试发送 验证配置
  6. 点击 确定 保存

添加钉钉通知

  1. 在钉钉群中添加自定义机器人
  2. 获取 Webhook URL(可选:加签密钥)
  3. 在系统中添加通知渠道
  4. 类型选择 钉钉
  5. 填写 Webhook URL
  6. 测试并保存

通知消息格式

### 镜像同步任务通知

> 任务名称:同步 Nginx
> 执行状态:成功 / 失败
> 执行耗时:2分30秒
>
> 数据统计
> - 总计:16 个 blob
> - 成功:16 个
> - 跳过:0 个

2025-11-27 18:00:00
⁠5. 高级功能

Tag 过滤示例

# 只同步 latest 和 stable 标签
包含:^(latest|stable)$

# 同步所有 1.x 版本
包含:^1\..*

# 排除所有 beta 和 rc 版本
排除:.*(beta|rc).*

# 只同步最新 10 个版本
保留最新:10

多架构镜像同步

系统会自动识别多架构镜像(Manifest List),并同步所有选中的架构:

  1. 检测到 Manifest List 时会在日志中提示
  2. 依次同步每个架构的 manifest 和 blobs
  3. 只有所有架构都成功后才上传 Manifest List

整个项目同步

不填写源仓库名,系统会自动:

  1. 列出项目下的所有仓库
  2. 对每个仓库应用 Tag 过滤规则
  3. 依次同步到目标项目

⁠📡 API 文档

⁠基础信息
  • Base URL: http://localhost:8080/api/v1
  • 认证: 当前版本无需认证
  • Content-Type: application/json
⁠Registry 管理
# 创建 Registry
POST /api/v1/registries
{
  "name": "Harbor Prod",
  "url": "https://harbor.example.com",
  "username": "admin",
  "password": "password",
  "enabled": true
}

# 列出所有 Registry
GET /api/v1/registries

# 获取单个 Registry
GET /api/v1/registries/:id

# 更新 Registry
PUT /api/v1/registries/:id

# 删除 Registry
DELETE /api/v1/registries/:id

# 测试连接
POST /api/v1/registries/:id/test

# 列出项目
GET /api/v1/registries/:id/projects

# 列出仓库
GET /api/v1/registries/:id/projects/:project/repositories
⁠任务管理
# 创建任务
POST /api/v1/tasks

# 列出所有任务
GET /api/v1/tasks

# 获取任务详情
GET /api/v1/tasks/:id

# 更新任务
PUT /api/v1/tasks/:id

# 删除任务
DELETE /api/v1/tasks/:id

# 立即运行
POST /api/v1/tasks/:id/run

# 停止任务
POST /api/v1/tasks/:id/stop
⁠执行历史
# 列出执行记录
GET /api/v1/executions?limit=20&offset=0

# 获取执行详情
GET /api/v1/executions/:id

# 获取执行日志
GET /api/v1/executions/:id/logs

# 统计信息
GET /api/v1/stats
⁠通知管理
# 创建通知渠道
POST /api/v1/notifications

# 列出所有渠道
GET /api/v1/notifications

# 更新渠道
PUT /api/v1/notifications/:id

# 删除渠道
DELETE /api/v1/notifications/:id

# 测试发送
POST /api/v1/notifications/:id/test
⁠WebSocket
# 连接 WebSocket(实时进度)
WS /api/v1/ws

# 消息格式
{
  "type": "progress",
  "execution_id": 1,
  "data": {
    "total_blobs": 100,
    "synced_blobs": 50,
    "progress": 50.0
  }
}
⁠健康检查
# 健康检查
GET /api/v1/health

# 响应
{
  "status": "ok",
  "version": "1.0.0"
}

⁠🛠️ 技术栈

⁠后端
  • 语言: Go 1.25+
  • 框架: Gin (HTTP Router)
  • 数据库: SQLite + GORM
  • 调度: robfig/cron (Cron 表达式)
  • WebSocket: gorilla/websocket
  • HTTP: net/http
⁠前端
  • 框架: React 18 + TypeScript
  • UI 库: Ant Design 5
  • 构建工具: Vite 5
  • HTTP 客户端: Axios
  • 路由: React Router 6
  • 状态管理: React Hooks
⁠基础设施
  • 容器: Docker + Docker Compose
  • 编排: Kubernetes
  • 存储: SQLite(持久化卷)
  • 健康检查: HTTP + WebSocket

⁠📂 项目结构

registry-sync/
├── cmd/
│   └── server/main.go              # Web 服务器入口
├── internal/                       # 内部包(Web 服务专用)
│   ├── api/handlers/               # REST API 处理器
│   ├── api/middleware/             # 中间件(CORS 等)
│   ├── db/models/                  # 数据模型
│   ├── db/store/                   # 数据访问层
│   ├── scheduler/                  # 任务调度器
│   └── websocket/                  # WebSocket Hub
├── pkg/                           # 公共包
│   ├── registry/                  # Registry API V2 客户端
│   ├── filter/                    # Tag 过滤器
│   └── notification/              # 通知发送
├── web/                           # React 前端
│   ├── src/
│   │   ├── api/                   # API 客户端
│   │   ├── components/            # 通用组件
│   │   ├── pages/                 # 页面组件
│   │   ├── hooks/                 # 自定义 Hooks
│   │   └── types/                 # TypeScript 类型
│   └── vite.config.ts
├── k8s/                           # Kubernetes 部署配置
│   ├── namespace.yaml
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   ├── pvc.yaml
│   └── kustomization.yaml
├── Dockerfile                     # Docker 镜像构建
├── docker-compose.yml             # Docker Compose 配置
├── .github/workflows/             # GitHub Actions CI/CD
│   └── docker-build.yml
└── README.md

⁠🎯 使用场景

⁠场景 1:跨云迁移

需求: 从 Docker Hub 迁移镜像到阿里云 ACR

配置:

  • 源 Registry: Docker Hub
  • 目标 Registry: 阿里云 ACR
  • Tag 过滤: 只同步 stable 和 latest
  • 架构: amd64 + arm64
⁠场景 2:内网镜像同步

需求: 从公网 Harbor 同步到内网 Harbor

配置:

  • 源 Registry: 公网 Harbor
  • 目标 Registry: 内网 Harbor
  • 定时任务: 每天凌晨 2 点
  • 通知: 失败时发送钉钉通知
⁠场景 3:灾备同步

需求: 生产镜像定期备份到备用 Registry

配置:

  • 源 Registry: 生产 Harbor
  • 目标 Registry: 备份 Harbor
  • 定时任务: 每 12 小时执行
  • 保留: 最新 10 个版本
⁠场景 4:多架构镜像分发

需求: 同步多架构镜像到多个区域

配置:

  • 源 Registry: Docker Hub
  • 目标 Registry: 各区域 Harbor
  • 架构选择: amd64, arm64, arm/v7
  • 过滤: 排除 debug 和 alpine 版本

⁠❓ 常见问题

⁠Q1: Docker Hub 拉取失败,报 429 错误?

A: Docker Hub 有限流限制(免费用户 100次/6小时)

  • 解决方案 1: 使用 Docker Hub 登录凭据
  • 解决方案 2: 错峰执行,避开高峰期
  • 解决方案 3: 考虑升级 Docker Hub 账户
⁠Q2: Harbor 项目不存在怎么办?

A: 系统不会自动创建项目

  • 手动在 Harbor 中创建目标项目
  • 或在任务配置中使用已存在的项目
⁠Q3: 多架构镜像同步失败?

A: 检查以下几点:

  • 源镜像是否真的是多架构(Manifest List)
  • 目标 Registry 是否支持 Manifest List
  • 网络是否稳定,是否有超时
⁠Q4: 定时任务没有执行?

A: 检查:

  • 任务是否已启用
  • Cron 表达式是否正确
  • 查看执行历史是否有错误日志
  • 重启服务后 Cron 会重新加载
⁠Q5: WebSocket 连接失败?

A:

  • 检查防火墙是否允许 WebSocket
  • 如果使用反向代理,需要配置 WebSocket 支持
  • Nginx 示例:proxy_set_header Upgrade $http_upgrade;
⁠Q6: 如何加速同步?

A:

  • 确保网络带宽充足
  • 源和目标 Registry 网络延迟低
  • 大多数情况下瓶颈在网络,而非系统
⁠Q7: 密码会泄露吗?

A:

  • 密码存储在 SQLite 数据库中(明文)
  • 建议:
    • 限制数据库文件访问权限
    • 使用专用的同步账户
    • 定期轮换密码
    • 后续版本会支持加密存储

⁠🔒 安全建议

  1. 最小权限原则

    • 为同步任务创建专用账户
    • 只授予必要的仓库权限(读/写)
  2. 网络隔离

    • 在内网环境部署时使用防火墙
    • 限制只有必要的服务器可以访问
  3. 数据保护

    • 定期备份 SQLite 数据库
    • 限制数据库文件访问权限(chmod 600)
  4. 密码管理

    • 使用强密码
    • 定期轮换密码
    • 不要在日志中暴露密码
  5. HTTPS

    • 生产环境使用 HTTPS
    • 配置 Ingress TLS 证书

⁠📊 性能指标

⁠资源消耗
  • 内存: 128-256MB(空闲)/ 256-512MB(同步中)
  • CPU: 0.1-0.5 核(空闲)/ 0.5-2 核(同步中)
  • 磁盘: 仅存储数据库,不缓存镜像
  • 网络: 取决于镜像大小和并发数
⁠同步速度
  • 小镜像 (< 100MB): 1-3 分钟
  • 中等镜像 (100MB-1GB): 3-10 分钟
  • 大镜像 (> 1GB): 10+ 分钟

实际速度取决于网络带宽和 Registry 性能

⁠并发能力
  • 单任务: 自动并发传输多个 Blob
  • 多任务: 支持多个任务并发执行
  • WebSocket: 支持多个客户端同时连接

⁠🗺️ Roadmap

⁠v0.1.0(计划中)
  • 用户认证和权限管理
  • 更多通知渠道(邮件、Slack)
  • 数据库密码加密
  • 任务执行历史保留策略
  • Prometheus metrics
⁠v0.2.0(规划中)
  • 任务创建向导
  • 批量操作(批量暂停/启动/删除)
  • 镜像扫描集成
  • 多语言支持(English)
  • Swagger API 文档
⁠v0.3.0(规划中)
  • 分布式部署支持
  • Redis 作为消息队列
  • 高可用架构
  • 性能监控面板

⁠🤝 贡献指南

欢迎提交 Issue 和 Pull Request!

开发流程:

  1. Fork 本仓库
  2. 创建特性分支 (git checkout -b feature/AmazingFeature)
  3. 提交更改 (git commit -m 'Add some AmazingFeature')
  4. 推送到分支 (git push origin feature/AmazingFeature)
  5. 提交 Pull Request

开发规范:

  • Go 代码遵循 gofmt 格式
  • 前端代码遵循 ESLint 规则
  • 提交信息使用英文,遵循 Conventional Commits
  • 添加必要的注释和文档

⁠📄 许可证

本项目采用 MIT License⁠ 开源协议


⁠🙏 致谢

感谢以下开源项目:


⁠📞 联系方式


Made with ❤️ for DevOps Engineers

⭐ 如果这个项目对你有帮助,请给个 Star!

Tag summary

Content type

Image

Digest

sha256:669ed0c0c…

Size

22.6 MB

Last updated

10 months ago

docker pull zunshen/registry-sync