Если вы видите что-то необычное, просто сообщите мне. Skip to main content

Docker pull без docker

Команда запуска:

./script dirName “http://localhost:8081/link/to/docker/registry” myAwesomeImage 1.0

Пример кода:

package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

func main() {
	downloadDir := os.Args[1]
	url := os.Args[2]
	imageName := os.Args[3]
	tag := os.Args[4]

	layers := getLayers(url, imageName, tag)

	for _, layer := range layers {
		fmt.Println("Downloading", layer)
		downloadLayer(url, imageName, layer, downloadDir)
	}

	untarLayers(downloadDir)

	fmt.Println("Download completed successfully")
}

func getLayers(url, imageName, tag string) []string {
	resp, err := http.Get(fmt.Sprintf("%s/v2/%s/manifests/%s", url, imageName, tag))
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	var layers []string
	for _, header := range resp.Header.Values("Docker-Content-Digest") {
		if strings.HasPrefix(header, "sha256:") {
			layers = append(layers, header[7:])
		}
	}

	return layers
}

func downloadLayer(url, imageName, layer, downloadDir string) {
	resp, err := http.Get(fmt.Sprintf("%s/v2/%s/blobs/%s", url, imageName, layer))
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	filePath := filepath.Join(downloadDir, layer+".tar")
	file, err := os.Create(filePath)
	if err != nil {
		panic(err)
	}
	defer file.Close()

	_, err = io.Copy(file, resp.Body)
	if err != nil {
		panic(err)
	}
}

func untarLayers(downloadDir string) {
	err := filepath.Walk(downloadDir, func(path string, info os.FileInfo, err error) error {
		if strings.HasSuffix(info.Name(), ".tar") {
			cmd := exec.Command("tar", "xvf", path, "-C", downloadDir)
			err := cmd.Run()
			if err != nil {
				return err
			}
		}
		return nil
	})
	if err != nil {
		panic(err)
	}

	err = filepath.Walk(downloadDir, func(path string, info os.FileInfo, err error) error {
		if strings.HasSuffix(info.Name(), ".tar") {
			err := os.Remove(path)
			if err != nil {
				return err
			}
		}
		return nil
	})
	if err != nil {
		panic(err)
	}
}