From c2500ea2d81f0afafa132bb5b32452b4e06272b7 Mon Sep 17 00:00:00 2001 From: CrazyMax Date: Wed, 21 Jun 2023 00:13:44 +0200 Subject: [PATCH] build: prefer local image resolution for docker driver Signed-off-by: CrazyMax --- build/build.go | 5 ++++- tests/build.go | 48 ++++++++++++++++++++++++++++++++++++++++++++ tests/integration.go | 18 +++++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) diff --git a/build/build.go b/build/build.go index 21b502a0..b480187a 100644 --- a/build/build.go +++ b/build/build.go @@ -593,7 +593,10 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt Op } if opt.Pull { - so.FrontendAttrs["image-resolve-mode"] = "pull" + so.FrontendAttrs["image-resolve-mode"] = pb.AttrImageResolveModeForcePull + } else if nodeDriver.IsMobyDriver() { + // moby driver always resolves local images by default + so.FrontendAttrs["image-resolve-mode"] = pb.AttrImageResolveModePreferLocal } if opt.Target != "" { so.FrontendAttrs["target"] = opt.Target diff --git a/tests/build.go b/tests/build.go index b380071c..8b7140d7 100644 --- a/tests/build.go +++ b/tests/build.go @@ -32,6 +32,7 @@ var buildTests = []func(t *testing.T, sb integration.Sandbox){ testBuildLocalExport, testBuildRegistryExport, testBuildTarExport, + testBuildMobyFromLocalImage, } func testBuild(t *testing.T, sb integration.Sandbox) { @@ -139,6 +140,53 @@ func testImageIDOutput(t *testing.T, sb integration.Sandbox) { require.Equal(t, dgst, digest.Digest(md.ConfigDigest)) } +func testBuildMobyFromLocalImage(t *testing.T, sb integration.Sandbox) { + if !isDockerWorker(sb) { + t.Skip("skipping test for non-docker workers") + } + + // pull image + cmd := dockerCmd(sb, withArgs("pull", "-q", "busybox:latest")) + stdout := bytes.NewBuffer(nil) + cmd.Stdout = stdout + cmd.Stderr = os.Stderr + require.NoError(t, cmd.Run()) + require.Equal(t, "docker.io/library/busybox:latest", strings.TrimSpace(stdout.String())) + + // create local tag + cmd = dockerCmd(sb, withArgs("tag", "busybox:latest", "buildx-test:busybox")) + cmd.Stderr = os.Stderr + require.NoError(t, cmd.Run()) + + // build image + dockerfile := []byte(`FROM buildx-test:busybox`) + dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0600)) + cmd = buildxCmd( + sb, + withArgs("build", "-q", "--output=type=cacheonly", dir), + ) + cmd.Stderr = os.Stderr + require.NoError(t, cmd.Run()) + + // create local tag matching a remote one + cmd = dockerCmd(sb, withArgs("tag", "busybox:latest", "busybox:1.36")) + cmd.Stderr = os.Stderr + require.NoError(t, cmd.Run()) + + // build image and check that it uses the local tag + dockerfile = []byte(` +FROM busybox:1.36 +RUN busybox | head -1 | grep v1.35.0 +`) + dir = tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0600)) + cmd = buildxCmd( + sb, + withArgs("build", "-q", "--output=type=cacheonly", dir), + ) + cmd.Stderr = os.Stderr + require.NoError(t, cmd.Run()) +} + func createTestProject(t *testing.T) string { dockerfile := []byte(` FROM busybox:latest AS base diff --git a/tests/integration.go b/tests/integration.go index bbb59c35..239e9b4f 100644 --- a/tests/integration.go +++ b/tests/integration.go @@ -3,6 +3,7 @@ package tests import ( "os" "os/exec" + "strings" "testing" "github.com/containerd/continuity/fs/fstest" @@ -55,3 +56,20 @@ func buildxCmd(sb integration.Sandbox, opts ...cmdOpt) *exec.Cmd { return cmd } + +func dockerCmd(sb integration.Sandbox, opts ...cmdOpt) *exec.Cmd { + cmd := exec.Command("docker") + cmd.Env = append([]string{}, os.Environ()...) + for _, opt := range opts { + opt(cmd) + } + if context := sb.DockerAddress(); context != "" { + cmd.Env = append(cmd.Env, "DOCKER_CONTEXT="+context) + } + return cmd +} + +func isDockerWorker(sb integration.Sandbox) bool { + sbDriver, _, _ := strings.Cut(sb.Name(), "+") + return sbDriver == "docker" +}