builder/digest_docker.go (79 lines of code) (raw):

// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. package builder import ( "bytes" "context" "encoding/json" "log" "strings" "github.com/Azure/acr-builder/pkg/image" "github.com/Azure/acr-builder/pkg/procmanager" "github.com/Azure/acr-builder/util" "github.com/pkg/errors" ) type dockerStoreDigest struct { procManager *procmanager.ProcManager debug bool } func newDockerStoreDigest(procManager *procmanager.ProcManager, debug bool) *dockerStoreDigest { return &dockerStoreDigest{ procManager: procManager, debug: debug, } } var _ DigestHelper = &dockerStoreDigest{} func (d *dockerStoreDigest) PopulateDigest(ctx context.Context, reference *image.Reference) error { if reference == nil { return nil } if reference.Digest != "" { return nil } // refString will always have the tag specified at this point. // For "scratch", we have to compare it against "scratch:latest" even though // scratch:latest isn't valid in a FROM clause. if reference.Reference == NoBaseImageSpecifierLatest { return nil } args := []string{ "docker", "run", "--rm", // Mount home "--volume", util.DockerSocketVolumeMapping, "--volume", homeVol + ":" + homeWorkDir, "--env", homeEnv, "docker", "inspect", "--format", "\"{{json .RepoDigests}}\"", reference.Reference, } if d.debug { log.Printf("query digest args: %v\n", args) } var buf bytes.Buffer if err := d.procManager.Run(ctx, args, nil, &buf, &buf, ""); err != nil { return errors.Wrapf(err, "failed to query digests, msg: %s", buf.String()) } trimCharPredicate := func(c rune) bool { return c == '\n' || c == '\r' || c == '"' || c == '\t' } reference.Digest = getRepoDigest(strings.TrimFunc(buf.String(), trimCharPredicate), reference) return nil } func getRepoDigest(jsonContent string, reference *image.Reference) string { prefix := reference.Repository + "@" // If the reference is in DockerHub library image format (eg, nginx:latest, library/node:16), we have to remove "/library" fix - otherwise // we'll fail to query the digest, since image names aren't prefixed with "library/" if reference.Registry == DockerHubRegistry && !strings.HasPrefix(reference.Reference, DockerHubRegistry) { if strings.HasPrefix(prefix, "library/") { prefix = prefix[8:] } } else if len(reference.Registry) > 0 { prefix = reference.Registry + "/" + prefix } var digestList []string if err := json.Unmarshal([]byte(jsonContent), &digestList); err != nil { log.Printf("Error deserializing %s to json, error: %v\n", jsonContent, err) } for _, digest := range digestList { if strings.HasPrefix(digest, prefix) { return digest[len(prefix):] } } return "" }