diff --git a/frontend/dockerfile/cmd/dockerfile-frontend/main.go b/frontend/dockerfile/cmd/dockerfile-frontend/main.go index 8e997566..c1a8b016 100644 --- a/frontend/dockerfile/cmd/dockerfile-frontend/main.go +++ b/frontend/dockerfile/cmd/dockerfile-frontend/main.go @@ -20,6 +20,8 @@ const ( defaultDockerfileName = "Dockerfile" localNameDockerfile = "dockerfile" buildArgPrefix = "build-arg:" + localNameContext = "context" + gitPrefix = "git://" ) func main() { @@ -51,6 +53,11 @@ func run() error { llb.IncludePatterns([]string{filename}), llb.SessionID(c.SessionID()), ) + var buildContext *llb.State + if strings.HasPrefix(opts[localNameContext], gitPrefix) { + src = parseGitSource(opts[localNameContext]) + buildContext = &src + } def, err := src.Marshal() if err != nil { return err @@ -71,6 +78,7 @@ func run() error { MetaResolver: c, BuildArgs: filterBuildArgs(opts), SessionID: c.SessionID(), + BuildContext: buildContext, }) if err != nil { @@ -105,3 +113,13 @@ func filterBuildArgs(opt map[string]string) map[string]string { } return m } + +func parseGitSource(ref string) llb.State { + ref = strings.TrimPrefix(ref, gitPrefix) + parts := strings.SplitN(ref, "#", 2) + branch := "" + if len(parts) > 1 { + branch = parts[1] + } + return llb.Git(parts[0], branch) +} diff --git a/frontend/dockerfile/dockerfile.go b/frontend/dockerfile/dockerfile.go index fd68c5bf..30f0b2e6 100644 --- a/frontend/dockerfile/dockerfile.go +++ b/frontend/dockerfile/dockerfile.go @@ -24,6 +24,8 @@ const ( defaultDockerfileName = "Dockerfile" localNameDockerfile = "dockerfile" buildArgPrefix = "build-arg:" + localNameContext = "context" + gitPrefix = "git://" ) func NewDockerfileFrontend() frontend.Frontend { @@ -33,7 +35,6 @@ func NewDockerfileFrontend() frontend.Frontend { type dfFrontend struct{} func (f *dfFrontend) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBridge, opts map[string]string) (retRef cache.ImmutableRef, exporterAttr map[string][]byte, retErr error) { - filename := opts[keyFilename] if filename == "" { filename = defaultDockerfileName @@ -48,6 +49,13 @@ func (f *dfFrontend) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBr llb.IncludePatterns([]string{filename}), llb.SessionID(sid), ) + + var buildContext *llb.State + if strings.HasPrefix(opts[localNameContext], gitPrefix) { + src = parseGitSource(opts[localNameContext]) + buildContext = &src + } + def, err := src.Marshal() if err != nil { return nil, nil, err @@ -104,6 +112,7 @@ func (f *dfFrontend) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBr MetaResolver: llbBridge, BuildArgs: filterBuildArgs(opts), SessionID: sid, + BuildContext: buildContext, }) if err != nil { @@ -140,3 +149,13 @@ func filterBuildArgs(opt map[string]string) map[string]string { } return m } + +func parseGitSource(ref string) llb.State { + ref = strings.TrimPrefix(ref, gitPrefix) + parts := strings.SplitN(ref, "#", 2) + branch := "" + if len(parts) > 1 { + branch = parts[1] + } + return llb.Git(parts[0], branch) +} diff --git a/frontend/dockerfile/dockerfile2llb/convert.go b/frontend/dockerfile/dockerfile2llb/convert.go index 38cdcb99..4bf13abc 100644 --- a/frontend/dockerfile/dockerfile2llb/convert.go +++ b/frontend/dockerfile/dockerfile2llb/convert.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "path" + "path/filepath" "strconv" "strings" @@ -29,6 +30,7 @@ type ConvertOpt struct { MetaResolver llb.ImageMetaResolver BuildArgs map[string]string SessionID string + BuildContext *llb.State } func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, *Image, error) { @@ -124,6 +126,11 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, return nil, nil, err } + buildContext := llb.Local(localNameContext, llb.SessionID(opt.SessionID)) + if opt.BuildContext != nil { + buildContext = *opt.BuildContext + } + for _, d := range allDispatchStates { if d.base != nil { d.state = d.base.state @@ -159,6 +166,7 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, buildArgValues: opt.BuildArgs, shlex: shlex, sessionID: opt.SessionID, + buildContext: buildContext, } if err = dispatchOnBuild(d, d.image.Config.OnBuild, opt); err != nil { @@ -190,6 +198,7 @@ type dispatchOpt struct { buildArgValues map[string]string shlex *ShellLex sessionID string + buildContext llb.State } func dispatch(d *dispatchState, cmd instructions.Command, opt dispatchOpt) error { @@ -211,7 +220,7 @@ func dispatch(d *dispatchState, cmd instructions.Command, opt dispatchOpt) error case *instructions.WorkdirCommand: err = dispatchWorkdir(d, c) case *instructions.AddCommand: - err = dispatchCopy(d, c.SourcesAndDest, llb.Local(localNameContext, llb.SessionID(opt.sessionID))) + err = dispatchCopy(d, c.SourcesAndDest, opt.buildContext) case *instructions.LabelCommand: err = dispatchLabel(d, c) case *instructions.OnbuildCommand: @@ -235,7 +244,7 @@ func dispatch(d *dispatchState, cmd instructions.Command, opt dispatchOpt) error case *instructions.ArgCommand: err = dispatchArg(d, c, opt.metaArgs, opt.buildArgValues) case *instructions.CopyCommand: - l := llb.Local(localNameContext, llb.SessionID(opt.sessionID)) + l := opt.buildContext if c.From != "" { index, err := strconv.Atoi(c.From) if err != nil {