aws ecr 使用golang实现的简单镜像转换工具

news2024/12/23 11:01:33

https://pkg.go.dev/github.com/docker/docker/client#section-readme

通过golang实现一个简单的镜像下载工具

总体步骤

  • 启动一台海外区域的ec2实例
  • 安装docker和awscli
  • 配置凭证访问国内ecr仓库
  • 编写web服务实现镜像转换和自动推送

安装docker和awscli

sudo yum remove awscli -y
sudo yum install less -y
sudo yum install unzip -y
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install --update
complete -C '/usr/local/bin/aws_completer' aws
sudo yum install docker -y
sudo systemctl start docker
sudo systemctl enable docker
sudo groupadd docker
sudo usermod -aG docker ec2-user

配置ecr凭证助手

https://github.com/awslabs/amazon-ecr-credential-helper

sudo yum install amazon-ecr-credential-helper
vim ~/.docker/config.json
{
	"credsStore": "ecr-login"
}

或者手动临时配置凭证

aws ecr get-login-password --region cn-north-1 | docker login --username AWS --password-stdin xxxxxx.dkr.ecr.cn-north-1.amazonaws.com.cn

编写web服务

使用golang原生的http包实现,比较简单粗糙,测试用的话足够了

前端页面

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ToImage</title>

    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .container {
            height: 300px;
            width: 100%;
			margin: 100px auto 0 auto;
        }

        .parent {
            position: relative;
			top: 50%;
			left: 30%;
        }

        .search {
            width:  650px;
            height: 50px;
            border-radius: 18px;
            outline: none;
            border: 1px solid #ccc;
            padding-left: 20px;
			padding-right: 100px;
            position: absolute;
			font-size: 20px;
        }

        .btn {
            height: 36px;
            width: 100px;
            position: absolute;
            background: #fff;
            top: 6px;
            left: 650px;
            border: none;
            outline: none;
			font-size: 20px;
        }
    </style>
</head>

<body>
    <div class="container">
        <form class="parent" method="get" action="/myrepo">
            <input type="text" class="search" placeholder="Please Input..." name="iamgename" />
            <input type="submit" class="btn" value="Search" />
        </form>
    </div>
</body>

</html>

后端服务

package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"os/exec"
	"strings"
	"text/template"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ecr"
	"github.com/aws/aws-sdk-go/service/sts"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/client"
)

func main() {
	http.HandleFunc("/", index)
	http.HandleFunc("/myrepo", myrepo)
	log.Println("The server is listening on 0.0.0.0:8089")
	http.ListenAndServe(":8089", nil)
}
func index(w http.ResponseWriter, r *http.Request) {
	t, _ := template.ParseFiles("index.html")
	t.Execute(w, "hi")
}
func myrepo(w http.ResponseWriter, r *http.Request) {
	imagename := r.URL.Query().Get("iamgename")
	if imagename == "" {
		fmt.Fprintln(w, "Please input image name and tag")
		return
	}
	// imagename := "public.ecr.aws/docker/library/busybox:uclibc"

	// get account id
	stssvc := sts.New(session.New(), aws.NewConfig().WithRegion("cn-north-1"))
	input := &sts.GetCallerIdentityInput{}
	stsresult, err := stssvc.GetCallerIdentity(input)
	if err != nil {
		fmt.Fprintln(w, "Can not get account id")
		log.Println("Can not get account id")
		return
	}
	accountid := *stsresult.Account
	log.Println("Your account is", accountid)
	ctx := context.Background()
	cli, err := client.NewClientWithOpts(client.WithVersion("1.41"))
	if err != nil {
		fmt.Fprintln(w, "Unable to create docker client")
		fmt.Println("Unable to create docker client")
		return
	}

	// list images
	images, err := cli.ImageList(ctx, types.ImageListOptions{})
	if err != nil {
		fmt.Fprintln(w, "Unable to list images")
		return
	}

	for _, image := range images {
		if imagename == image.RepoTags[0] {
			fmt.Fprintln(w, "The image has existed on the host!")
			fmt.Fprintln(w, "The image name is", imagename)
		}
	}

	// pull image
	pullReader, err := cli.ImagePull(ctx, imagename, types.ImagePullOptions{})
	if err != nil {
		panic(err)
	}
	defer pullReader.Close()
	io.Copy(w, pullReader)

	//tag image
	arr := strings.Split(imagename, "/")
	arrlen := len(arr)
	tempstr := arr[arrlen-1]
	split := strings.Split(tempstr, ":")
	splen := len(split)
	var tag string
	var shortname string
	if splen == 2 {
		shortname = split[0]
		tag = split[1]
	} else {
		shortname = split[0]
		tag = "latest"
	}
	tagimage := accountid + ".dkr.ecr.cn-north-1.amazonaws.com.cn/" + shortname + ":" + tag
	log.Println("The image name is", tagimage)
	cli.ImageTag(ctx, imagename, tagimage)

	// create repo
	mySession := session.Must(session.NewSession())
	ecrsvc := ecr.New(mySession, aws.NewConfig().WithRegion("cn-north-1"))
	ecrinput := &ecr.CreateRepositoryInput{
		RepositoryName: aws.String(shortname),
	}
	ecrresult, err := ecrsvc.CreateRepository(ecrinput)
	if err != nil {
		if aerr, ok := err.(awserr.Error); ok {
			switch aerr.Code() {
			case ecr.ErrCodeRepositoryAlreadyExistsException:
				log.Println(ecr.ErrCodeRepositoryAlreadyExistsException, aerr.Error())
			default:
				log.Println(aerr.Error())
			}
		} else {
			log.Println(err.Error())
		}
	} else {
		log.Println("Success creating repo", ecrresult.Repository.RepositoryArn)
	}
	log.Println("The repo name is", accountid+".dkr.ecr.cn-north-1.amazonaws.com.cn/"+shortname)

	// push image

	// cmd := exec.Command("docker", "push", tagimage)
	cmd := exec.Command("docker", "push", tagimage)
	cmdout, cmderr := cmd.CombinedOutput()
	if cmderr != nil {
		fmt.Fprint(w, cmderr.Error())
		log.Printf("docker push failed with %s\n", cmderr)
		return
	}
	fmt.Fprint(w, string(cmdout))
	// log.Println(string(cmdout))

	// remove image
	_, removeerr := cli.ImageRemove(ctx, tagimage, types.ImageRemoveOptions{})
	if removeerr != nil {
		log.Println("Failed to remover image", err)
	}
	// return info
	fmt.Fprintln(w, "The image is successful pushed!")
	fmt.Fprintln(w, "The image name is", tagimage)
	fmt.Fprintln(w, "login with")
	fmt.Fprintf(w, "aws ecr get-login-password --region cn-north-1 | docker login --username AWS --password-stdin %s.dkr.ecr.cn-north-1.amazonaws.com.cn", accountid)
}

测试推送镜像,推送到默认凭证所在的账号下,可以通过sts查看

{"status":"Pulling from bitnami/envoy","id":"latest"}
{"status":"Digest: sha256:1848240b060c9bad9c34f76fc87830da317628e6f7809aede6e634afa74913dd"}
{"status":"Status: Image is up to date for public.ecr.aws/bitnami/envoy:latest"}
The push refers to repository [xxxxxxxxx.dkr.ecr.cn-north-1.amazonaws.com.cn/envoy]
afe7743db796: Preparing
afe7743db796: Pushed
latest: digest: sha256:d5199964f061f4c28606f3bc8d867b12cdbb5e67af9a58821a9dacf2abd903d8 size: 529
The image is successful pushed!
The image name is xxxxxxxxx.dkr.ecr.cn-north-1.amazonaws.com.cn/envoy:latest
login with
aws ecr get-login-password --region cn-north-1 | docker login --username AWS --password-stdin xxxxxxxxx.dkr.ecr.cn-north-1.amazonaws.com.cn

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/372189.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

超市怎么做微信小程序_线上超市小程序开发可以实现什么功能呢

1。开发超市小程序有什么价值&#xff1f; 1、对于消费者来说&#xff1a;通过超市小程序能够更加直接的购买到想要的产品&#xff0c;消费者无需再到门店寻找商品可以直接通过超市小程序进行在线浏览&#xff1b;通过在线搜索的方式能够更加便捷的搜索到相应的商品&#xff0…

第一篇自我介绍(单片机)

小白的单片机之旅 &#x1f914;自我介绍&#x1f914; &#x1f60a;学习目标&#x1f60a; &#x1f61c;关于单片机&#x1f61c; &#x1f31d;小结&#x1f31d; &#x1f389;博客主页&#xff1a;小智_x0___0x_ &#x1f389;欢迎关注&#xff1a;&#x1f44d;点赞&…

JavaSE学习笔记day14

二、Set Set集合是Collection集合的子接口,该集合中不能有重复元素!! Set集合提供的方法签名,与父接口Collection的方法完全一致!! 即没有关于下标操作的方法 Set接口,它有两个常用的子实现类HashSet,TreeSet 三、HashSet HashSet实现了Set接口,底层是hash表(实际上底层是HashM…

QML 中的 5 大布局

作者: 一去、二三里 个人微信号: iwaleon 微信公众号: 高效程序员 在 QML 中,可以通过多种方式对元素进行布局 - 手动定位、坐标绑定定位、锚定位(anchors)、定位器和布局管理器。 说到 anchors,可能很多人都不太了解,它是 QML 中一个非常重要的概念,主要提供了一种相…

C语言几种判断语句简述

C 判断 判断结构要求程序员指定一个或多个要评估或测试的条件&#xff0c;以及条件为真时要执行的语句&#xff08;必需的&#xff09;和条件为假时要执行的语句&#xff08;可选的&#xff09;。 C 语言把任何非零和非空的值假定为 true&#xff0c;把零或 null 假定为 fals…

Vuex基础语法

Vuex vuex官网 文章目录Vuexvuex的工作原理图2.vuex的环境搭建3.vuex的使用1.actons2. mutations3.getters4.vuex中的map映射属性4.1 mapState和mapGetters4.2 mapMutations和mapActions5.vuex多组件通信1.通过计算属性获得2.通过mapState获得6.vuex模块化和命名空间6.1模块化…

为什么要用线程池?

1.降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。 2.提高响应速度。当任务到达时&#xff0c;任务可以不需要的等到线程创建就能立即执行。 3.提高线程的可管理性。线程是稀缺资源&#xff0c;如果无限制的创建&#xff0c;不仅会消耗系统资源&#…

王道《操作系统》学习(一)——计算机系统概述

1.1 操作系统的概念、功能 1.1.1 操作系统的概念&#xff08;定义&#xff09; &#xff08;1&#xff09;操作系统是系统资源的管理者 &#xff08;2&#xff09;向上层用户、软件提供方便易用的服务 &#xff08;3&#xff09;是最接近硬件的一层软件 1.1.2 操作系统的功能…

Java 输入输出流

应用程序经常需要访问文件和目录&#xff0c;读取文件信息或写入信息到文件&#xff0c;即从外界输入数据或者向外界传输数据&#xff0c;这些数据可以保存在磁盘文件、内存或其他程序中。在Java中&#xff0c;对这些数据的操作是通过 I/O 技术来实现的。所谓 I/O 技术&#xf…

Vue2.0开发之——使用ref引用DOM元素(40)

一 概述 什么是ref引用ref引用示例 二 什么是ref引用 ref用来辅助开发者在不依赖于jQuery的情况下&#xff0c;获取DOM元素或组件的引用每个vue的组件实例上&#xff0c;都包含一个$refs对象&#xff0c;里面存储着对应的DOM元素或组件的应用默认情况下&#xff0c;组件的$re…

Vue3之事件绑定

何为事件绑定 当我们开发完UI界面后&#xff0c;还需要和用户交互&#xff0c;所谓交互也就是用户可以点击界面上的按钮&#xff0c;文字&#xff0c;链接等以及点击键盘上的按钮&#xff0c;我们开发的程序可以做出对应的反应。做出的反应会通过UI界面再反馈给用户&#xff0c…

CSS 之层叠规则(权级、权重、顺序)详解

文章目录参考描述定义层叠层叠与冲突规则权重&#xff08;优先级&#xff09;权重值的叠加顺序权级权级层叠规则的运用顺序尾声参考 项目描述MDN WEB Docs优先级Amily_mo令人烦恼的css选择器权值问题 - Amily_mo深入解析CSS基思J.格兰特 / 黄小、高楠 译MDN WEB Docs:not() 描…

华为OD机试用Python实现 -【字符串重新排序】(2023-Q1 新题)

华为OD机试题 华为OD机试300题大纲字符串重新排序题目描述输入描述输出描述示例一输入输出示例二输入输出Python 代码实现算法思路华为OD机试300题大纲 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查看地址:blog.csdn.…

JavaEE|TCP/IP协议栈之TCP协议工作机制下

文章目录一、滑动窗口二、流量控制三、拥塞控制四、延时应答五、捎带应答六、面向字节流&#xff08;了解&#xff09;七、异常情况&#xff08;了解&#xff09;关于其他传输层协议一、滑动窗口 为什么要引入滑动窗口&#xff1f; 确认应答和超时重传为TCP可靠传输机制提供支持…

FTP中的TCP传输服务(电子科技大学TCP/IP实验五)

目录 一&#xff0e;实验目的 二&#xff0e;预备知识 三&#xff0e;实验原理 四&#xff0e;实验内容 五&#xff0e;实验步骤 八、总结及心得体会 九、对本实验过程及方法、手段的改进建议 一&#xff0e;实验目的 1、掌握 TCP 协议工作原理 2、掌握 TCP 的连接建立…

阿里团队刚发布的重磅图像生成基础模型,多重条件引导+图像合成,SD级别,5B参数...

一个多小时前刚发的论文&#xff0c;Composer: Creative and Controllable Image Synthesis with Composable Conditions。 我读完了快速帮大家概要一下啊。论文地址见文章最后。阿里巴巴团队开发的这个重磅图像生成模型 Compose&#xff0c;支持多重引导条件的图像生成(合成)&…

containerd安装配置

containerd基本使用命令 containerd安装 容器运行时containerd安装配置 https://blog.csdn.net/rendongxingzhe/article/details/124595415 yum list | grep containerd containerd的本地CLI工具ctr命令 containerd的组件 containerd提供包括容器的运行、测试、发布和接口…

improve-1

类型及检测方式 1. JS内置类型 JavaScript 的数据类型有下图所示 其中&#xff0c;前 7 种类型为基础类型&#xff0c;最后 1 种&#xff08;Object&#xff09;为引用类型&#xff0c;也是你需要重点关注的&#xff0c;因为它在日常工作中是使用得最频繁&#xff0c;也是需要…

DevOps是什么?DevOps能够给我们带来什么?

目录专栏导读一、DevOps是什么&#xff1f;二、为什么会出现DevOps&#xff1f;1、容器化技术的发展&#xff0c;微服务架构的发展&#xff0c;直接促进了DevOps的迅速发展2、敏态需求的增加&#xff0c;即探索性工作的增加3、软件开发活动在企业经营活动中占比的不断增加4、企…

【华为OD机试模拟题】用 C++ 实现 - 水仙花数(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 获得完美走位(2023.Q1) 文章目录 最近更新的博客使用说明水仙花数题目输入输出描述示例一输入输出说明示例二输入输出Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。…