同步docker镜像到harbor

155 阅读1分钟

创建builder

docker buildx create \
	--use --name mybuilder \
	--driver-opt env.https_proxy="socks5://192.168.1.128:1080" \
	--driver-opt env.no_proxy="harbor.local"
        
docker buildx inspect mybuilder --bootstrap
docker buildx use mybuilder

安装证书

若未使用自签名证书跳过这一步

BUILDER=$(docker ps | grep buildkitd  | awk '{print $1}')
docker cp ./harbor.crt $BUILDER:/usr/local/share/ca-certificates/ 
sudo docker exec $BUILDER update-ca-certificates
sudo docker restart $BUILDER 

同步镜像

docker-utils sync \
    -p linux/amd64,linux/arm64 \
    -r harbor.local/library/alpine:latest

编译命令行工具

package main

import (
   "bufio"
   "fmt"
   "github.com/urfave/cli/v2"
   "log"
   "os"
   "os/exec"
   "strings"
)

const commandTpl = `
docker buildx build \
   --platform=%s \
   -f Dockerfile.tmp \
   -t %s . \
   --push
`

func Sync(ctx *cli.Context) error {
   repo := ctx.String("repo")
   args := strings.SplitN(repo, "/", 2)

   content := []byte("FROM " + args[1])
   if err := os.WriteFile("Dockerfile.tmp", content, 0644); err != nil {
      return err
   }

   cmd := fmt.Sprintf(commandTpl, ctx.String("platform"), repo)
   executor := exec.Command("sh", "-c", cmd)

   // 创建一个管道用于读取标准输出
   stdoutPipe, err := executor.StdoutPipe()
   if err != nil {
      log.Fatalf("Failed to create stdout pipe: %v", err)
   }

   // 创建一个管道用于读取标准错误
   stderrPipe, err := executor.StderrPipe()
   if err != nil {
      log.Fatalf("Failed to create stderr pipe: %v", err)
   }

   // 启动命令
   if err := executor.Start(); err != nil {
      log.Fatalf("Failed to start command: %v", err)
   }

   // 读取标准输出
   go func() {
      scanner := bufio.NewScanner(stdoutPipe)
      for scanner.Scan() {
         fmt.Println(scanner.Text())
      }
      if err := scanner.Err(); err != nil {
         log.Printf("Error reading stdout: %v", err)
      }
   }()

   // 读取标准错误
   go func() {
      scanner := bufio.NewScanner(stderrPipe)
      for scanner.Scan() {
         fmt.Println(scanner.Text())
      }
      if err := scanner.Err(); err != nil {
         log.Printf("Error reading stderr: %v", err)
      }
   }()

   // 等待命令执行完成
   if err := executor.Wait(); err != nil {
      return err
   }

   return os.Remove("Dockerfile.tmp")
}

func main() {
   app := cli.App{
      Name:  "docker-utils",
      Usage: "docker工具箱",
      Commands: []*cli.Command{
         {
            Name:  "sync",
            Usage: "同步镜像仓库",
            Flags: []cli.Flag{
               &cli.StringFlag{
                  Name:    "r",
                  Aliases: []string{"repo"},
                  Usage:   "镜像仓库地址, 例如 harbor.com/library/alpine:latest",
               },
               &cli.StringFlag{
                  Name:        "p",
                  Aliases:     []string{"platform"},
                  DefaultText: "linux/amd64",
                  Usage:       "平台架构, 例如 linux/amd64, 如有多个用逗号分隔",
               },
            },
            Action: Sync,
         },
      },
   }
   if err := app.Run(os.Args); err != nil {
      log.Println(err.Error())
   }
}