From 987b40917b20506377aa9993aafccf04906e4da7 Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Fri, 13 Dec 2024 19:58:14 -0800 Subject: [PATCH] dockerfile: fix named context replacement for child stages Fixes bug that didn't allow named context replacement for stages that were inherited from another stage. This is a regression from Dockerfile 1.11 ONBUILD changes where code was changed to call init() later to allow ONBUILD rules to change the dependency list of a stage. Calling this reinit caused the child stage to pick up the its state from the parent stage in Dockerfile again. Signed-off-by: Tonis Tiigi (cherry picked from commit 4c8bd43853833debf271c5582ebb1136e48ea528) --- frontend/dockerfile/dockerfile2llb/convert.go | 1 + frontend/dockerfile/dockerfile_test.go | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/frontend/dockerfile/dockerfile2llb/convert.go b/frontend/dockerfile/dockerfile2llb/convert.go index bf2647ceb0e2..934c3a338e3d 100644 --- a/frontend/dockerfile/dockerfile2llb/convert.go +++ b/frontend/dockerfile/dockerfile2llb/convert.go @@ -376,6 +376,7 @@ func toDispatchState(ctx context.Context, dt []byte, opt ConvertOpt) (*dispatchS } } allDispatchStates.addState(ds) + ds.base = nil // reset base set by addState continue } } diff --git a/frontend/dockerfile/dockerfile_test.go b/frontend/dockerfile/dockerfile_test.go index a36bc3e856b2..d9d70191e65c 100644 --- a/frontend/dockerfile/dockerfile_test.go +++ b/frontend/dockerfile/dockerfile_test.go @@ -7110,6 +7110,44 @@ COPY --from=base /env_foobar / dt, err = os.ReadFile(filepath.Join(destDir, "env_path")) require.NoError(t, err) require.Contains(t, string(dt), "/foobar:") + + // this case checks replacing stage that is based on another stage. + // moby/buildkit#5578-2539397486 + + dockerfile = []byte(` +FROM busybox AS parent +FROM parent AS base +RUN echo base > /out +FROM base +RUN [ -f /etc/alpine-release ] +RUN [ ! -f /out ] +`) + + dir = integration.Tmpdir( + t, + fstest.CreateFile("Dockerfile", dockerfile, 0600), + ) + + f = getFrontend(t, sb) + + destDir = t.TempDir() + + _, err = f.Solve(sb.Context(), c, client.SolveOpt{ + FrontendAttrs: map[string]string{ + "context:base": "docker-image://" + target, + }, + LocalMounts: map[string]fsutil.FS{ + dockerui.DefaultLocalNameDockerfile: dir, + dockerui.DefaultLocalNameContext: dir, + }, + Exports: []client.ExportEntry{ + { + Type: client.ExporterLocal, + OutputDir: destDir, + }, + }, + }, nil) + require.NoError(t, err) } func testNamedImageContextPlatform(t *testing.T, sb integration.Sandbox) {