php-Editor Strawberry kann bei der Verwendung von Docker auf ein häufiges Problem stoßen, nämlich „Laden des Docker-Image fehlgeschlagen“. Dieses Problem hindert uns möglicherweise daran, Docker zum normalen Erstellen und Ausführen von Containern zu verwenden. Aber keine Sorge, für dieses Problem gibt es meist mehrere Lösungen. In diesem Artikel werden einige gängige Lösungen vorgestellt, die Ihnen dabei helfen, das Docker-Image erfolgreich zu laden und dieses lästige Problem zu lösen. Egal, ob Sie Anfänger oder erfahrener Docker-Benutzer sind, ich hoffe, dass dieser Artikel für Sie hilfreich ist.
Ich verwende das golang
、docker 客户端
加载 .tar
Docker-Image-Format.
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 }
// Funktion: 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)
.
Außerdem sehe ich beim Ausführen von docker images
nicht, dass das Bild geladen wird. Es sieht so aus, als ob das Laden des Bildes noch nicht abgeschlossen ist.
In meinem anderen Code fügt der Docker-Client cli.imageload
立即返回,但 docker 映像加载通常需要一些时间。我通常会在检查 getimageidbyrepotag
jedoch etwa 30 Sekunden Wartezeit hinzu. Auch das Hinzufügen einer Wartezeit hilft in diesem Fall nicht.
Danke
Ein paar Fragen:
err
, sodass möglicherweise ein Teil der Fehlerbehandlung verloren geht
wg.wait()
tar
阅读器中读取内容以查找清单文件并提取标签信息 - 这很好 - 但找到后,您将字节流的其余部分复制到管道中。因此,您将丢失一块永远不会到达 docker
ClientUm zu vermeiden, dass der TAR-Byte-Stream zweimal gelesen wird, können Sie io.teereader verwenden.
Dadurch können Sie TAR-Archive lesen (Scan manifest
文件 - 但也可以将此流完整写入其他地方(即写入 docker
Client).
Erstellen teereader
:
tr := io.teereader(tarfile, pw) // reading `tr` will read the tarfile - but simultaneously write to `pw`
Das Laden von Bildern liest jetzt von hier aus (anstelle von Pipe):
//imageloadresponse, err = cli.imageload(context.background(), pr, false) imageloadresponse, err = cli.imageload(context.background(), tr, false)
Dann ändern Sie Ihr archive/tar
-Lesegerät, um aus der Pfeife zu lesen:
//tarreader := tar.newreader(tarfile) // direct from file tarreader := tar.newreader(pr) // read from pipe (indirectly from the file)
Sie können dann den io.copy
-Block löschen:
// no longer needed: // // _, err = io.copy(pw, tarreader) //
Weil der Tar-Inspektionscode den gesamten Stream in eof einliest.
P.S. Möglicherweise müssen Sie io.eof
重置为 nil
以避免在检查来自任一 goroutine 的任何潜在错误时认为 eof
in einen schwerwiegenderen Fehler umwandeln:
header, err = tarReader.Next() if err == io.EOF { err = nil // EOF is a non-fatal error here break }
Das obige ist der detaillierte Inhalt vonDocker-Image konnte nicht geladen werden. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!