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