基于docker push原理进行tar镜像上传至harbor仓库(未分片)

深入解析Harbor镜像推送全流程实现

本文将基于开源Harbor镜像仓库,详细解析如何通过Java代码实现完整的Docker镜像推送流程。通过分析核心代码,揭示镜像推送背后的技术细节。

核心架构设计

HarborPushAllInOne类封装了完整的镜像推送功能:

  • 使用Apache HttpClient处理HTTP请求
  • 通过TarArchiveInputStream解析Docker镜像tar包
  • 采用分步上传策略(Config/Layers/Manifest)

初始化参数说明:

public HarborPushAllInOne(String registry, String user, String pwd, String project, String repo) {
    this.registry = registry.trim().replaceAll("/$", "");
    this.project = project;
    this.repo = repo;
    this.basic = "Basic " + Base64.getEncoder().encodeToString((user + ":" + pwd).getBytes());
}

镜像上传三步曲

tar包解析与文件提取

private Map<String, byte[]> extractTar(String path) throws Exception {
    Map<String, byte[]> map = new HashMap<>();
    try (TarArchiveInputStream tis = new TarArchiveInputStream(Files.newInputStream(Paths.get(path)))) {
        TarArchiveEntry e;
        while ((e = tis.getNextTarEntry()) != null) {
            if (!e.isDirectory()) {
                byte[] buf = new byte[(int)e.getSize()];
                int read = 0, total = 0;
                while (total < buf.length && (read = tis.read(buf, total, buf.length - total)) >= 0) {
                    total += read;
                }
                map.put(e.getName(), buf);
                fileSizes.put(e.getName(), total);
            }
        }
    }
    return map;
}

分层上传策略

  1. 配置文件上传
  2. 镜像层文件上传
  3. 合并生成manifest
public void uploadTarImage(String tarPath, String repo, String tag) throws Exception {
    Map<String, byte[]> files = extractTar(tarPath);
    JSONObject mf = new JSONArray(new String(files.get("manifest.json"))).getJSONObject(0);
    
    // Config文件处理
    String configName = mf.getString("Config");
    String configDigest = pushBlob(files.get(configName));
    
    // Layers处理
    List<String> layerDigests = new ArrayList<>();
    List<Integer> layerSizes = new ArrayList<>();
    for (Object o : mf.getJSONArray("Layers")) {
        String layerName = (String)o;
        String digest = pushBlob(files.get(layerName));
        layerDigests.add(digest);
        layerSizes.add(fileSizes.get(layerName));
    }
    
    // 最终manifest生成
    pushManifest(configDigest, files.get(configName).length, layerDigests, layerSizes, repo, tag);
}

关键技术实现

Blob上传优化
采用检查-上传两步策略避免重复上传:

private String pushBlob(byte[] blob) throws Exception {
    String digest = "sha256:" + sha256(blob);
    String check = registry + "/v2/" + project + "/" + repo + "/blobs/" + digest;
    if (exists(check)) {
        System.out.println("Blob 已存在 " + digest);
        return digest;
    }
    // 分段上传逻辑...
}

安全认证处理
使用Basic认证并自动生成Header:

private final String basic = "Basic " + Base64.getEncoder().encodeToString((user + ":" + pwd).getBytes());

// 在请求中设置
post.setHeader(HttpHeaders.AUTHORIZATION, basic);

实际应用示例

完整的上传调用示例:

public static void main(String[] args) throws Exception {
    HarborPushAllInOne pusher = new HarborPushAllInOne(
        "https://your-harbor.com",
        "admin",
        "password",
        "your-project",
        "demo-repo"
    );
    pusher.uploadTarImage("/path/to/image.tar", "demo-repo", "v1.0");
}

性能优化建议

  1. 增加并行上传层文件功能
  2. 实现断点续传机制
  3. 添加进度监控回调接口
  4. 优化内存管理,处理大文件分块

通过本文的分析可以看出,Docker镜像推送本质上是对分层存储系统和Registry API的精确调用。理解这些底层原理,有助于开发更高效的镜像管理工具。

<think>我们已知用户想要将一个tar格式的Docker镜像推送到Harbor镜像仓库。根据Docker的操作流程,通常需要先将tar文件加载到本地Docker镜像库,然后打标签(tag)以符合Harbor仓库的命名规范,最后推送(push)到Harbor。 步骤分解: 1. 加载tar文件为本地镜像:使用`docker load`命令。 2. 为镜像打标签:使用`docker tag`命令,将镜像标签改为符合Harbor仓库地址的格式。 3. 登录Harbor:使用`docker login`命令登录到Harbor仓库。 4. 推送镜像:使用`docker push`命令将镜像推送到Harbor。 具体操作如下: ### 步骤1: 加载Docker镜像tar文件加载到本地Docker镜像库: ```bash docker load -i /path/to/your/image.tar ``` 加载完成后,使用`docker images`查看加载的镜像,记下镜像的名称和标签(或IMAGE ID)。 ### 步骤2: 为镜像打标签 假设Harbor仓库地址为`harbor.example.com`,项目名称为`myproject`,则镜像需要被打上类似`harbor.example.com/myproject/image-name:tag`的标签。 例如,如果加载的镜像名称为`my-image`,标签为`v1.0`,则打标签命令为: ```bash docker tag my-image:v1.0 harbor.example.com/myproject/my-image:v1.0 ``` ### 步骤3: 登录Harbor仓库 在推送镜像之前,需要先登录Harbor仓库: ```bash docker login harbor.example.com ``` 输入用户名和密码(Harbor仓库的管理员提供的账号密码)。 ### 步骤4: 推送镜像Harbor 使用`docker push`命令推送打标签后的镜像: ```bash docker push harbor.example.com/myproject/my-image:v1.0 ``` ### 注意事项 - 确保Harbor仓库地址正确,并且网络可达。 - 确保Harbor仓库中已经创建了对应的项目(如`myproject`),如果没有,需要先在Harbor中创建项目。 - 如果Harbor使用的是HTTP而不是HTTPS,需要在Docker的配置文件中(如`/etc/docker/daemon.json`)添加`insecure-registries`配置,然后重启Docker服务。例如: ```json { "insecure-registries": ["harbor.example.com"] } ``` 重启Docker服务:`sudo systemctl restart docker`(Linux系统)。 ### 示例 假设有一个镜像文件`nginx.tar`,Harbor地址为`192.168.1.100`,项目名为`public`,操作如下: ```bash # 加载镜像 docker load -i nginx.tar # 查看加载的镜像,假设为nginx:latest docker images # 打标签 docker tag nginx:latest 192.168.1.100/public/nginx:latest # 登录Harbor(如果Harbor使用HTTP,需要先配置insecure-registries) docker login 192.168.1.100 # 推送 docker push 192.168.1.100/public/nginx:latest ``` ### 引用说明 以上步骤参考了Docker官方文档中关于镜像操作的基本命令[^2][^3]。 §§相关问题§§ 1. 如何解决在推送镜像Harbor时出现的“http: server gave HTTP response to HTTPS client”错误? 2. 如何在Harbor中创建项目并设置访问权限? 3. 如何从Harbor中拉取(pull)镜像?</think>要将一个 Docker 镜像的 `.tar` 文件推送到 Harbor 私有仓库,需要完成以下步骤: ### 🛠 操作步骤 1. **加载镜像到本地 Docker** ```bash docker load -i /path/to/your-image.tar ``` 加载后使用 `docker images` 查看镜像名称和 TAG(如 `my-image:v1`)[^3]。 2. **为镜像Harbor 标签** ```bash docker tag my-image:v1 harbor.your-domain.com/your-project/my-image:v1 ``` - `harbor.your-domain.com`: Harbor 仓库地址 - `your-project`: Harbor 中创建的项目名称 - `my-image:v1`: 镜像名称和标签[^2] 3. **登录 Harbor 仓库** ```bash docker login harbor.your-domain.com ``` 输入 Harbor 用户名和密码(首次需先在 Harbor Web 界面创建用户)。 4. **推送镜像Harbor** ```bash docker push harbor.your-domain.com/your-project/my-image:v1 ``` ### ⚠️ 关键注意事项 1. **Harbor 项目必须存在** 需提前在 Harbor Web 界面创建项目(如 `your-project`),否则推送失败。 2. **HTTP 仓库的安全配置** 如果 Harbor 使用 HTTP(非 HTTPS),需修改 Docker 配置: ```json // /etc/docker/daemon.json { "insecure-registries": ["harbor.your-domain.com"] } ``` 修改后重启 Docker:`sudo systemctl restart docker`[^2]。 3. **认证问题处理** 推送失败时尝试重新登录: ```bash docker logout harbor.your-domain.com docker login harbor.your-domain.com ``` ### 🌰 完整示例 ```bash # 加载镜像 docker load -i nginx-latest.tar # 查看镜像 docker images # 得到镜像名 nginx:latest # 打标签 (假设 Harbor 地址为 192.168.1.100,项目名为 public) docker tag nginx:latest 192.168.1.100/public/nginx:latest # 登录 Harbor docker login 192.168.1.100 # 推送镜像 docker push 192.168.1.100/public/nginx:latest ``` ### 🔍 验证结果 1. 登录 Harbor Web 界面 2. 进入 `public` 项目 3. 检查是否存在 `nginx:latest` 镜像 > 💡 提示:使用 `docker save` 导出的镜像(`.tar` 文件)本质是镜像快照,需通过 `docker load` 恢复为本地镜像后才能推送[^2][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A little sea pig

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值