Browse code

Fix cache for dockerfiles with multiple FROM

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>

Tonis Tiigi authored on 2017/03/17 08:17:49
Showing 3 changed files
... ...
@@ -147,9 +147,6 @@ func NewBuilder(clientCtx context.Context, config *types.ImageBuildOptions, back
147 147
 			LookingForDirectives: true,
148 148
 		},
149 149
 	}
150
-	if icb, ok := backend.(builder.ImageCacheBuilder); ok {
151
-		b.imageCache = icb.MakeImageCache(config.CacheFrom)
152
-	}
153 150
 
154 151
 	parser.SetEscapeToken(parser.DefaultEscapeToken, &b.directive) // Assume the default token for escape
155 152
 
... ...
@@ -163,6 +160,14 @@ func NewBuilder(clientCtx context.Context, config *types.ImageBuildOptions, back
163 163
 	return b, nil
164 164
 }
165 165
 
166
+func (b *Builder) resetImageCache() {
167
+	if icb, ok := b.docker.(builder.ImageCacheBuilder); ok {
168
+		b.imageCache = icb.MakeImageCache(b.options.CacheFrom)
169
+	}
170
+	b.noBaseImage = false
171
+	b.cacheBusted = false
172
+}
173
+
166 174
 // sanitizeRepoAndTags parses the raw "t" parameter received from the client
167 175
 // to a slice of repoAndTag.
168 176
 // It also validates each repoName and tag.
... ...
@@ -205,7 +205,7 @@ func from(b *Builder, args []string, attributes map[string]bool, original string
205 205
 
206 206
 	var image builder.Image
207 207
 
208
-	b.noBaseImage = false
208
+	b.resetImageCache()
209 209
 
210 210
 	// Windows cannot support a container with no base image.
211 211
 	if name == api.NoBaseImageSpecifier {
... ...
@@ -5594,6 +5594,30 @@ func (s *DockerSuite) TestBuildCacheFrom(c *check.C) {
5594 5594
 	c.Assert(layers1[len(layers1)-1], checker.Not(checker.Equals), layers2[len(layers1)-1])
5595 5595
 }
5596 5596
 
5597
+func (s *DockerSuite) TestBuildCacheMultipleFrom(c *check.C) {
5598
+	testRequires(c, DaemonIsLinux) // All tests that do save are skipped in windows
5599
+	dockerfile := `
5600
+		FROM busybox
5601
+		ADD baz /
5602
+		FROM busybox
5603
+    ADD baz /`
5604
+	ctx := fakeContext(c, dockerfile, map[string]string{
5605
+		"Dockerfile": dockerfile,
5606
+		"baz":        "baz",
5607
+	})
5608
+	defer ctx.Close()
5609
+
5610
+	result := buildImage("build1", withExternalBuildContext(ctx))
5611
+	result.Assert(c, icmd.Success)
5612
+	// second part of dockerfile was a repeat of first so should be cached
5613
+	c.Assert(strings.Count(result.Combined(), "Using cache"), checker.Equals, 1)
5614
+
5615
+	result = buildImage("build2", withBuildFlags("--cache-from=build1"), withExternalBuildContext(ctx))
5616
+	result.Assert(c, icmd.Success)
5617
+	// now both parts of dockerfile should be cached
5618
+	c.Assert(strings.Count(result.Combined(), "Using cache"), checker.Equals, 2)
5619
+}
5620
+
5597 5621
 func (s *DockerSuite) TestBuildNetNone(c *check.C) {
5598 5622
 	testRequires(c, DaemonIsLinux)
5599 5623
 	name := "testbuildnetnone"