diff --git a/frontend/dockerfile/builder/build.go b/frontend/dockerfile/builder/build.go index c27590b7..76777eea 100644 --- a/frontend/dockerfile/builder/build.go +++ b/frontend/dockerfile/builder/build.go @@ -62,8 +62,10 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) { localNameContext = v } + forceLocalDockerfile := false localNameDockerfile := DefaultLocalNameDockerfile if v, ok := opts[keyNameDockerfile]; ok { + forceLocalDockerfile = true localNameDockerfile = v } @@ -119,11 +121,14 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) { llb.SharedKeyHint(localNameDockerfile), dockerfile2llb.WithInternalName(name), ) + var buildContext *llb.State isScratchContext := false if st, ok := detectGitContext(opts[localNameContext]); ok { - src = *st - buildContext = &src + if !forceLocalDockerfile { + src = *st + } + buildContext = st } else if httpPrefix.MatchString(opts[localNameContext]) { httpContext := llb.HTTP(opts[localNameContext], llb.Filename("context"), dockerfile2llb.WithInternalName("load remote build context")) def, err := httpContext.Marshal(marshalOpts...) @@ -154,10 +159,13 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) { if isArchive(dt) { fileop := useFileOp(opts, &caps) if fileop { - src = llb.Scratch().File(llb.Copy(httpContext, "/context", "/", &llb.CopyInfo{ + bc := llb.Scratch().File(llb.Copy(httpContext, "/context", "/", &llb.CopyInfo{ AttemptUnpack: true, })) - buildContext = &src + if !forceLocalDockerfile { + src = bc + } + buildContext = &bc } else { copyImage := opts[keyOverrideCopyImage] if copyImage == "" { @@ -166,13 +174,18 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) { unpack := llb.Image(copyImage, dockerfile2llb.WithInternalName("helper image for file operations")). Run(llb.Shlex("copy --unpack /src/context /out/"), llb.ReadonlyRootFS(), dockerfile2llb.WithInternalName("extracting build context")) unpack.AddMount("/src", httpContext, llb.Readonly) - src = unpack.AddMount("/out", llb.Scratch()) - buildContext = &src + bc := unpack.AddMount("/out", llb.Scratch()) + if !forceLocalDockerfile { + src = bc + } + buildContext = &bc } } else { filename = "context" - src = httpContext - buildContext = &src + if !forceLocalDockerfile { + src = httpContext + } + buildContext = &httpContext isScratchContext = true } } diff --git a/frontend/dockerfile/dockerfile_test.go b/frontend/dockerfile/dockerfile_test.go index 337b5f46..cf261a9e 100644 --- a/frontend/dockerfile/dockerfile_test.go +++ b/frontend/dockerfile/dockerfile_test.go @@ -105,6 +105,7 @@ var fileOpTests = []integration.Test{ testCopyWildcards, testCopyRelative, testTarContext, + testTarContextExternalDockerfile, } var opts []integration.TestOpt @@ -3834,6 +3835,72 @@ COPY foo / require.NoError(t, err) } +func testTarContextExternalDockerfile(t *testing.T, sb integration.Sandbox) { + f := getFrontend(t, sb) + isFileOp := getFileOp(t, sb) + + foo := []byte("contents") + + buf := bytes.NewBuffer(nil) + tw := tar.NewWriter(buf) + err := tw.WriteHeader(&tar.Header{ + Name: "foo", + Typeflag: tar.TypeReg, + Size: int64(len(foo)), + Mode: 0644, + }) + require.NoError(t, err) + _, err = tw.Write(foo) + require.NoError(t, err) + err = tw.Close() + require.NoError(t, err) + + dockerfile := []byte(` +FROM scratch +COPY foo bar +`) + dir, err := tmpdir( + fstest.CreateFile("Dockerfile", dockerfile, 0600), + ) + require.NoError(t, err) + defer os.RemoveAll(dir) + + c, err := client.New(context.TODO(), sb.Address()) + require.NoError(t, err) + defer c.Close() + + up := uploadprovider.New() + url := up.Add(buf) + + // repeat with changed default args should match the old cache + destDir, err := ioutil.TempDir("", "buildkit") + require.NoError(t, err) + defer os.RemoveAll(destDir) + + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ + FrontendAttrs: map[string]string{ + "build-arg:BUILDKIT_DISABLE_FILEOP": strconv.FormatBool(!isFileOp), + "context": url, + "dockerfilekey": builder.DefaultLocalNameDockerfile, + }, + Session: []session.Attachable{up}, + LocalDirs: map[string]string{ + builder.DefaultLocalNameDockerfile: dir, + }, + Exports: []client.ExportEntry{ + { + Type: client.ExporterLocal, + OutputDir: destDir, + }, + }, + }, nil) + require.NoError(t, err) + + dt, err := ioutil.ReadFile(filepath.Join(destDir, "bar")) + require.NoError(t, err) + require.Equal(t, string(dt), "contents") +} + func tmpdir(appliers ...fstest.Applier) (string, error) { tmpdir, err := ioutil.TempDir("", "buildkit-dockerfile") if err != nil {