通过github的workflow来迁移gcr的镜像

本文实现通过 github 的 workflow 来迁移到 gcr 上的镜像到 dockerhub 的过程记录。

创建仓库

创建一个 go 的项目

Certainly! The error message you’re encountering, “go: go.mod file not found in current directory or any parent directory; see ‘go help modules’”, indicates that Go is unable to locate a go.mod file in the current directory or any of its parent directories. This file is essential for managing Go modules and dependencies.

Here are a few steps you can take to resolve this issue:

  1. Initialize a Go Module:

    • In your project directory, run the following command:
      1
      
      go mod init yourProjectName
      
      Replace yourProjectName with an appropriate name for your project. This command will create a go.mod file in the current directory, allowing Go to manage your project’s dependencies¹².
  2. Check Environment Variables:

    • Ensure that the environment variable GO111MODULE is set correctly. You can set it to one of the following values:
      • auto: Automatically enable Go modules when a go.mod file is present.
      • on: Force Go modules to be enabled.
      • off: Disable Go modules entirely. To set the variable, run:
    1
    
    go env -w GO111MODULE=auto
    

    This will allow Go to automatically enable modules based on the presence of a go.mod file²⁴.

  3. Run go mod tidy:

    • Execute the following command in your project directory:
      1
      
      go mod tidy
      
      This command will synchronize your code’s imports with the dependencies listed in the go.mod file⁴.

Remember that these steps are general guidelines, and you should adapt them to your specific project structure. If you encounter any further issues, feel free to ask for additional assistance! 🚀

源: 与必应的对话, 2024/3/29 (1) go 语言开发时,报“go:go.mod 文件未在当前目录或任何父目录中找到”这个问题怎么解决? - 知乎. https://www.zhihu.com/question/458797990. (2) 如何在 Visual Studio Code 中配置 GO 开发环境 - 知乎 - 知乎专栏. https://zhuanlan.zhihu.com/p/408291483. (3) 请问 vscode 进行 go 调试遇到找不到 mod 文件是什么意思? - 知乎. https://www.zhihu.com/question/514939166. (4) 【Go】エラー「go.mod file not found in current directory or any parent …. https://qiita.com/to3izo/items/f47bbc7b11ef6d2e24cd. (5) Error message “go: go.mod file not found in current directory or any …. https://stackoverflow.com/questions/66894200/error-message-go-go-mod-file-not-found-in-current-directory-or-any-parent-dire.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#main.go
package main

import (
	"context"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"strings"
	"sync"
	"text/template"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/registry"
	"github.com/docker/docker/client"
	"github.com/spf13/pflag"
)

var (
	content    = pflag.StringP("content", "", "", "原始镜像,格式为: {\" hub-mirror\":[\"hub-mirror.cn-hangzhou.aliyuncs.com\")")
	maxContent = pflag.IntP("maxContent", "", 10, "原始镜像个数限制")
	username   = pflag.StringP("username", "", "", "阿里云账号")
	password   = pflag.StringP("password", "", "", "阿里云密码")
	outputPath = pflag.StringP("outputPath", "", "output.sh", "结果输出文件路径")
)

func main() {
	pflag.Parse()
	fmt.Println("验证原始镜像内容")
	var hubMirrors struct {
		Content []string `json:"hub-mirror"`
	}
	err := json.Unmarshal([]byte(*content), &hubMirrors)
	if err != nil {
		panic(err)
	}
	if len(hubMirrors.Content) > *maxContent {
		panic("原始镜像个数超过限制")
	}
	fmt.Println("%+v\n", hubMirrors)
	fmt.Println("连接docker")
	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
	if err != nil {
		panic(err)
	}
	fmt.Println("验证 Docker 用户名和密码")

	if *username == "" || *password == "" {
		panic("用户名和密码不能为空")
	}

	autoConfig := registry.AuthConfig{
		Username: *username,
		Password: *password,
	}

	encodedJSON, err := json.Marshal(autoConfig)
	if err != nil {
		panic(err)
	}
	authStr := base64.URLEncoding.EncodeToString(encodedJSON)
	_, err = cli.RegistryLogin(context.Background(), autoConfig)
	if err != nil {
		panic(err)
	}
	fmt.Println("开始转换镜像")

	output := make([]struct {
		Source string
		Target string
	}, 0)
	wg := sync.WaitGroup{}
	for _, source := range hubMirrors.Content {
		if source == "" {
			continue
		}
		target := *username + "/" + strings.ReplaceAll(source, "/", ".")
		wg.Add(1)
		go func(source, target string) {
			defer wg.Done()
			fmt.Printf("开始转换镜像 %s -> %s\n", source, "=>", target)
			ctx := context.Background()

			// pull image
			pullOut, err := cli.ImagePull(ctx, source, types.ImagePullOptions{})
			if err != nil {
				panic(err)
			}
			defer pullOut.Close()
			io.Copy(os.Stdout, pullOut)
			//重新打标签
			err = cli.ImageTag(ctx, source, target)
			if err != nil {
				panic(err)
			}
			// push image
			pushOut, err := cli.ImagePush(ctx, target, types.ImagePushOptions{RegistryAuth: authStr})
			if err != nil {
				panic(err)
			}
			defer pushOut.Close()
			io.Copy(os.Stdout, pushOut)
			output = append(output, struct {
				Source string
				Target string
			}{Source: source, Target: target})
			fmt.Printf("转换镜像 %s -> %s 完成\n", source, target)
		}(source, target)
	}
	wg.Wait()
	if len(output) == 0 {
		panic("没有镜像需要转换")
	}

	tmpl, err := template.New("pull_images").Parse(`{{- range . -}}
    docker pull {{.Target}}
    docker tag {{.Target}} {{.Source}}
    {{- end -}}`)
	if err != nil {
		panic(err)
	}
	outputFile, err := os.Create(*outputPath)
	if err != nil {
		panic(err)
	}
	defer outputFile.Close()
	err = tmpl.Execute(outputFile, output)
	if err != nil {
		panic(err)
	}
	fmt.Println(output)
}

接下来测试一下迁移镜像

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 go run main.go --username=huangxiaofenglogin --password=Hxf-10047 --content='{"hub-mirror":["gcr.io/google-samples/microservices-demo/emailservice:v0.3.5"
]}'
验证原始镜像内容
%+v
 {[gcr.io/google-samples/microservices-demo/emailservice:v0.3.5]}
连接docker
验证 Docker 用户名和密码
开始转换镜像
开始转换镜像 gcr.io/google-samples/microservices-demo/emailservice:v0.3.5 -> =>
%!(EXTRA string=huangxiaofenglogin/gcr.io.google-samples.microservices-demo.emailservice:v0.3.5){"status":"Pulling from google-samples/microservices-demo/emailservice","id":"v0.3.5"}
{"status":"Pulling fs layer","progressDetail":{},"id":"a2abf6c4d29d"}
{"status":"Pulling fs layer","progressDetail":{},"id":"625294dad115"}
{"status":"Pulling fs layer","progressDetail":{},"id":"2d55109ef858"}
{"status":"Pulling fs layer","progressDetail":{},"id":"8f7394e7143f"}
{"status":"Pulling fs layer","progressDetail":{},"id":"8571408494af"}
{"status":"Pulling fs layer","progressDetail":{},"id":"f95c0b27aef9"}
{"status":"Pulling fs layer","progressDetail":{},"id":"2393ef3b74ff"}
{"status":"Waiting","progressDetail":{},"id":"8571408494af"}
{"status":"Pulling fs layer","progressDetail":{},"id":"4eecd96b4cb1"}
{"status":"Pulling fs layer","progressDetail":{},"id":"2d143e67efa5"}
{"status":"Waiting","progressDetail":{},"id":"f95c0b27aef9"}
{"status":"Waiting","progressDetail":{},"id":"2393ef3b74ff"}
{"status":"Pulling fs layer","progressDetail":{},"id":"86bac8e09f85"}

接下来把仓库推送到 github 上操作

Licensed under CC BY-NC-SA 4.0
最后更新于 Jan 06, 2025 05:52 UTC
comments powered by Disqus
Built with Hugo
主题 StackJimmy 设计
Caret Up