瀏覽代碼

Fix cache for dockerfiles with multiple FROM

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Tonis Tiigi 8 年之前
父節點
當前提交
acad599210
共有 3 個文件被更改,包括 33 次插入4 次删除
  1. 8 3
      builder/dockerfile/builder.go
  2. 1 1
      builder/dockerfile/dispatchers.go
  3. 24 0
      integration-cli/docker_cli_build_test.go

+ 8 - 3
builder/dockerfile/builder.go

@@ -147,9 +147,6 @@ func NewBuilder(clientCtx context.Context, config *types.ImageBuildOptions, back
 			LookingForDirectives: true,
 		},
 	}
-	if icb, ok := backend.(builder.ImageCacheBuilder); ok {
-		b.imageCache = icb.MakeImageCache(config.CacheFrom)
-	}
 
 	parser.SetEscapeToken(parser.DefaultEscapeToken, &b.directive) // Assume the default token for escape
 
@@ -163,6 +160,14 @@ func NewBuilder(clientCtx context.Context, config *types.ImageBuildOptions, back
 	return b, nil
 }
 
+func (b *Builder) resetImageCache() {
+	if icb, ok := b.docker.(builder.ImageCacheBuilder); ok {
+		b.imageCache = icb.MakeImageCache(b.options.CacheFrom)
+	}
+	b.noBaseImage = false
+	b.cacheBusted = false
+}
+
 // sanitizeRepoAndTags parses the raw "t" parameter received from the client
 // to a slice of repoAndTag.
 // It also validates each repoName and tag.

+ 1 - 1
builder/dockerfile/dispatchers.go

@@ -205,7 +205,7 @@ func from(b *Builder, args []string, attributes map[string]bool, original string
 
 	var image builder.Image
 
-	b.noBaseImage = false
+	b.resetImageCache()
 
 	// Windows cannot support a container with no base image.
 	if name == api.NoBaseImageSpecifier {

+ 24 - 0
integration-cli/docker_cli_build_test.go

@@ -5594,6 +5594,30 @@ func (s *DockerSuite) TestBuildCacheFrom(c *check.C) {
 	c.Assert(layers1[len(layers1)-1], checker.Not(checker.Equals), layers2[len(layers1)-1])
 }
 
+func (s *DockerSuite) TestBuildCacheMultipleFrom(c *check.C) {
+	testRequires(c, DaemonIsLinux) // All tests that do save are skipped in windows
+	dockerfile := `
+		FROM busybox
+		ADD baz /
+		FROM busybox
+    ADD baz /`
+	ctx := fakeContext(c, dockerfile, map[string]string{
+		"Dockerfile": dockerfile,
+		"baz":        "baz",
+	})
+	defer ctx.Close()
+
+	result := buildImage("build1", withExternalBuildContext(ctx))
+	result.Assert(c, icmd.Success)
+	// second part of dockerfile was a repeat of first so should be cached
+	c.Assert(strings.Count(result.Combined(), "Using cache"), checker.Equals, 1)
+
+	result = buildImage("build2", withBuildFlags("--cache-from=build1"), withExternalBuildContext(ctx))
+	result.Assert(c, icmd.Success)
+	// now both parts of dockerfile should be cached
+	c.Assert(strings.Count(result.Combined(), "Using cache"), checker.Equals, 2)
+}
+
 func (s *DockerSuite) TestBuildNetNone(c *check.C) {
 	testRequires(c, DaemonIsLinux)
 	name := "testbuildnetnone"