Rumah >pembangunan bahagian belakang >Golang >Gagal memuatkan imej buruh pelabuhan

Gagal memuatkan imej buruh pelabuhan

WBOY
WBOYke hadapan
2024-02-13 08:20:091111semak imbas

Gagal memuatkan imej buruh pelabuhan

editor php Strawberry mungkin menghadapi masalah biasa apabila menggunakan Docker, iaitu "gagal memuatkan imej Docker". Masalah ini mungkin menghalang kami daripada menggunakan Docker untuk membina dan menjalankan bekas seperti biasa. Tetapi jangan risau, biasanya terdapat pelbagai penyelesaian untuk masalah ini. Artikel ini akan memperkenalkan anda kepada beberapa penyelesaian biasa untuk membantu anda berjaya memuatkan imej Docker dan menyelesaikan masalah yang menjengkelkan ini. Sama ada anda seorang pemula atau pengguna Docker yang berpengalaman, saya harap artikel ini akan membantu anda.

Kandungan soalan

Saya menggunakan golangdocker 客户端 加载 .tar format imej docker.

func loadimagefromtar(cli *client.client, tarfilepath string) (string, error) {
    // read tar file
    tarfile, err := os.open(tarfilepath)
    if err != nil {
        return "", fmt.errorf("failed to open tar file: %w", err)
    }
    defer tarfile.close()

    // create a pipe to stream data between tar reader and docker client
    pr, pw := io.pipe()

    // set up a waitgroup for synchronization
    var wg sync.waitgroup
    wg.add(2)

    // load the docker image in a separate goroutine
    var imageloadresponse types.imageloadresponse
    go func() {
        defer wg.done()
        imageloadresponse, err = cli.imageload(context.background(), pr, false)
        if err != nil {
            err = fmt.errorf("failed to load docker image: %w", err)
        }
    }()

    // read tar file metadata and copy the tar file to the pipe writer in a separate goroutine
    var repotag string
    go func() {
        defer wg.done()
        defer pw.close()

        tarreader := tar.newreader(tarfile)

        for {
            header, err := tarreader.next()
            if err == io.eof {
                break
            }
            if err != nil {
                err = fmt.errorf("failed to read tar header: %w", err)
                fmt.printf("error: %v", err)
                return
            }

            // extract the repository and tag from the manifest file
            if header.name == "manifest.json" {
                data, err := io.readall(tarreader)
                if err != nil {
                    err = fmt.errorf("failed to read manifest file: %w", err)
                    fmt.printf("error: %v", err)
                    return
                }

                var manifest []map[string]interface{}
                err = json.unmarshal(data, &manifest)
                if err != nil {
                    err = fmt.errorf("failed to unmarshal manifest: %w", err)
                    fmt.printf("error: %v", err)
                    return
                }

                repotag = manifest[0]["repotags"].([]interface{})[0].(string)
            }

            // copy the tar file data to the pipe writer
            _, err = io.copy(pw, tarreader)
            if err != nil {
                err = fmt.errorf("failed to copy tar data: %w", err)
                fmt.printf("error: %v", err)
                return
            }
        }
    }()

    // wait for both goroutines to finish
    wg.wait()

    // check if any error occurred in the goroutines
    if err != nil {
        return "", err
    }

    // close the image load response body
    defer imageloadresponse.body.close()

    // get the image id
    imageid, err := getimageidbyrepotag(cli, repotag)
    if err != nil {
        return "", fmt.errorf("failed to get image id: %w", err)
    }

    return imageid, nil
}

// Fungsi: getimageidbyrepotag

func getImageIDByRepoTag(cli *client.Client, repoTag string) (string, error) {
    images, err := cli.ImageList(context.Background(), types.ImageListOptions{})
    if err != nil {
        return "", fmt.Errorf("failed to list images: %w", err)
    }

    for _, image := range images {
        for _, tag := range image.RepoTags {
            if tag == repoTag {
                return image.ID, nil
            }
        }
    }

    return "", fmt.Errorf("image ID not found for repo tag: %s", repoTag)
}

getimageidbyrepotag 始终返回 fmt.errorf("未找到存储库标记的图像 id: %s", repotag). Selain itu, apabila saya berlari docker images saya tidak nampak imej sedang dimuatkan. Nampaknya pemuatan imej belum selesai lagi.

Dalam kod saya yang lain walaupun klien docker cli.imageload 立即返回,但 docker 映像加载通常需要一些时间。我通常会在检查 getimageidbyrepotag menambah kira-kira 30 saat masa menunggu sebelum ini. Menambah masa menunggu juga tidak membantu dalam kes ini.

Terima kasih

Penyelesaian

Beberapa soalan:

  • Dua goroutine ini dikongsi err jadi beberapa pengendalian ralat mungkin hilang
    • Anda harus menggunakan pembolehubah ralat unik untuk setiap goroutine di sini dan semak kedua-dua ralat selepas wg.wait()
  • Masalah utama: Anda mendapat aliran bait daripada tar 阅读器中读取内容以查找清单文件并提取标签信息 - 这很好 - 但找到后,您将字节流的其余部分复制到管道中。因此,您将丢失一块永远不会到达 docker pelanggan

Untuk mengelakkan membaca strim tar byte dua kali, anda boleh menggunakan io.teereader. Ini membolehkan anda membaca arkib tar - imbas manifest 文件 - 但也可以将此流完整写入其他地方(即写入 docker klien).

Buat teereader:

tr := io.teereader(tarfile, pw)  // reading `tr` will read the tarfile - but simultaneously write to `pw`

Pemuatan imej kini akan dibaca dari sini (bukan paip):

//imageloadresponse, err = cli.imageload(context.background(), pr, false)
imageloadresponse, err = cli.imageload(context.background(), tr, false)

Kemudian tukar archive/tar pembaca anda untuk membaca dari paip:

//tarreader := tar.newreader(tarfile) // direct from file
tarreader := tar.newreader(pr) // read from pipe (indirectly from the file)

Anda kemudian boleh memadamkan blok io.copy:

// no longer needed:
//
// _, err = io.copy(pw, tarreader)
//

Kerana kod pemeriksaan tar akan membaca keseluruhan aliran ke dalam eof.

P.S. Anda mungkin perlu menukar io.eof 重置为 nil 以避免在检查来自任一 goroutine 的任何潜在错误时认为 eof kepada ralat yang lebih serius:

header, err = tarReader.Next()
if err == io.EOF {
    err = nil  //  EOF is a non-fatal error here
    break
}

Atas ialah kandungan terperinci Gagal memuatkan imej buruh pelabuhan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam