diff --git a/frontend/dockerfile/builder/build.go b/frontend/dockerfile/builder/build.go index 47f7ab5f..95929ce5 100644 --- a/frontend/dockerfile/builder/build.go +++ b/frontend/dockerfile/builder/build.go @@ -16,6 +16,7 @@ import ( "github.com/moby/buildkit/exporter/containerimage/exptypes" "github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb" "github.com/moby/buildkit/frontend/gateway/client" + "github.com/moby/buildkit/solver/pb" specs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" "golang.org/x/sync/errgroup" @@ -34,6 +35,7 @@ const ( keyNoCache = "no-cache" keyTargetPlatform = "platform" keyMultiPlatform = "multi-platform" + keyImageResolveMode = "image-resolve-mode" ) var httpPrefix = regexp.MustCompile("^https?://") @@ -57,6 +59,11 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) { } } + resolveMode, err := parseResolveMode(opts[keyImageResolveMode]) + if err != nil { + return nil, err + } + filename := opts[keyFilename] if filename == "" { filename = defaultDockerfileName @@ -224,16 +231,17 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) { func(i int, tp *specs.Platform) { eg.Go(func() error { st, img, err := dockerfile2llb.Dockerfile2LLB(ctx, dtDockerfile, dockerfile2llb.ConvertOpt{ - Target: opts[keyTarget], - MetaResolver: c, - BuildArgs: filter(opts, buildArgPrefix), - Labels: filter(opts, labelPrefix), - SessionID: c.BuildOpts().SessionID, - BuildContext: buildContext, - Excludes: excludes, - IgnoreCache: ignoreCache, - TargetPlatform: tp, - BuildPlatforms: buildPlatforms, + Target: opts[keyTarget], + MetaResolver: c, + BuildArgs: filter(opts, buildArgPrefix), + Labels: filter(opts, labelPrefix), + SessionID: c.BuildOpts().SessionID, + BuildContext: buildContext, + Excludes: excludes, + IgnoreCache: ignoreCache, + TargetPlatform: tp, + BuildPlatforms: buildPlatforms, + ImageResolveMode: resolveMode, }) if err != nil { @@ -384,3 +392,16 @@ func parsePlatforms(v string) ([]*specs.Platform, error) { } return pp, nil } + +func parseResolveMode(v string) (llb.ResolveMode, error) { + switch v { + case pb.AttrImageResolveModeDefault, "": + return llb.ResolveModeDefault, nil + case pb.AttrImageResolveModeForcePull: + return llb.ResolveModeForcePull, nil + case pb.AttrImageResolveModePreferLocal: + return llb.ResolveModePreferLocal, nil + default: + return 0, errors.Errorf("invalid image-resolve-mode: %s", v) + } +} diff --git a/frontend/dockerfile/dockerfile2llb/convert.go b/frontend/dockerfile/dockerfile2llb/convert.go index 961e254a..59721498 100644 --- a/frontend/dockerfile/dockerfile2llb/convert.go +++ b/frontend/dockerfile/dockerfile2llb/convert.go @@ -48,6 +48,7 @@ type ConvertOpt struct { IgnoreCache []string // CacheIDNamespace scopes the IDs for different cache mounts CacheIDNamespace string + ImageResolveMode llb.ResolveMode TargetPlatform *specs.Platform BuildPlatforms []specs.Platform } @@ -188,7 +189,8 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, var isScratch bool if metaResolver != nil && reachable { dgst, dt, err := metaResolver.ResolveImageConfig(ctx, d.stage.BaseName, gw.ResolveImageConfigOpt{ - Platform: platform, + Platform: platform, + ResolveMode: opt.ImageResolveMode.String(), }) if err == nil { // handle the error while builder is actually running var img Image @@ -218,7 +220,7 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, if isScratch { d.state = llb.Scratch() } else { - d.state = llb.Image(d.stage.BaseName, dfCmd(d.stage.SourceCode), llb.Platform(*platform)) + d.state = llb.Image(d.stage.BaseName, dfCmd(d.stage.SourceCode), llb.Platform(*platform), opt.ImageResolveMode) } d.platform = platform return nil