Browse code

Add default PATH to 'scratch' images

Closes #19012

Signed-off-by: Doug Davis <dug@us.ibm.com>

Doug Davis authored on 2016/01/04 12:45:06
Showing 3 changed files
... ...
@@ -193,6 +193,11 @@ func from(b *Builder, args []string, attributes map[string]bool, original string
193 193
 
194 194
 	name := args[0]
195 195
 
196
+	var (
197
+		image builder.Image
198
+		err   error
199
+	)
200
+
196 201
 	// Windows cannot support a container with no base image.
197 202
 	if name == api.NoBaseImageSpecifier {
198 203
 		if runtime.GOOS == "windows" {
... ...
@@ -200,24 +205,20 @@ func from(b *Builder, args []string, attributes map[string]bool, original string
200 200
 		}
201 201
 		b.image = ""
202 202
 		b.noBaseImage = true
203
-		return nil
204
-	}
205
-
206
-	var (
207
-		image builder.Image
208
-		err   error
209
-	)
210
-	// TODO: don't use `name`, instead resolve it to a digest
211
-	if !b.options.PullParent {
212
-		image, err = b.docker.GetImage(name)
213
-		// TODO: shouldn't we error out if error is different from "not found" ?
214
-	}
215
-	if image == nil {
216
-		image, err = b.docker.Pull(name)
217
-		if err != nil {
218
-			return err
203
+	} else {
204
+		// TODO: don't use `name`, instead resolve it to a digest
205
+		if !b.options.PullParent {
206
+			image, err = b.docker.GetImage(name)
207
+			// TODO: shouldn't we error out if error is different from "not found" ?
208
+		}
209
+		if image == nil {
210
+			image, err = b.docker.Pull(name)
211
+			if err != nil {
212
+				return err
213
+			}
219 214
 		}
220 215
 	}
216
+
221 217
 	return b.processImageFrom(image)
222 218
 }
223 219
 
... ...
@@ -35,6 +35,7 @@ import (
35 35
 	"github.com/docker/docker/pkg/system"
36 36
 	"github.com/docker/docker/pkg/tarsum"
37 37
 	"github.com/docker/docker/pkg/urlutil"
38
+	"github.com/docker/docker/runconfig/opts"
38 39
 )
39 40
 
40 41
 func (b *Builder) commit(id string, autoCmd *strslice.StrSlice, comment string) error {
... ...
@@ -394,15 +395,30 @@ func containsWildcards(name string) bool {
394 394
 }
395 395
 
396 396
 func (b *Builder) processImageFrom(img builder.Image) error {
397
-	b.image = img.ID()
397
+	if img != nil {
398
+		b.image = img.ID()
398 399
 
399
-	if img.Config() != nil {
400
-		b.runConfig = img.Config()
400
+		if img.Config() != nil {
401
+			b.runConfig = img.Config()
402
+		}
401 403
 	}
402 404
 
403
-	// The default path will be blank on Windows (set by HCS)
404
-	if len(b.runConfig.Env) == 0 && system.DefaultPathEnv != "" {
405
-		b.runConfig.Env = append(b.runConfig.Env, "PATH="+system.DefaultPathEnv)
405
+	// Check to see if we have a default PATH, note that windows won't
406
+	// have one as its set by HCS
407
+	if system.DefaultPathEnv != "" {
408
+		// Convert the slice of strings that represent the current list
409
+		// of env vars into a map so we can see if PATH is already set.
410
+		// If its not set then go ahead and give it our default value
411
+		configEnv := opts.ConvertKVStringsToMap(b.runConfig.Env)
412
+		if _, ok := configEnv["PATH"]; !ok {
413
+			b.runConfig.Env = append(b.runConfig.Env,
414
+				"PATH="+system.DefaultPathEnv)
415
+		}
416
+	}
417
+
418
+	if img == nil {
419
+		// Typically this means they used "FROM scratch"
420
+		return nil
406 421
 	}
407 422
 
408 423
 	// Process ONBUILD triggers if they exist
... ...
@@ -2143,6 +2143,39 @@ func (s *DockerSuite) TestBuildEnv(c *check.C) {
2143 2143
 	}
2144 2144
 }
2145 2145
 
2146
+func (s *DockerSuite) TestBuildPATH(c *check.C) {
2147
+	testRequires(c, DaemonIsLinux)
2148
+
2149
+	defPath := "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
2150
+
2151
+	fn := func(dockerfile string, exp string) {
2152
+		_, err := buildImage("testbldpath", dockerfile, true)
2153
+		c.Assert(err, check.IsNil)
2154
+
2155
+		res, err := inspectField("testbldpath", "Config.Env")
2156
+		c.Assert(err, check.IsNil)
2157
+
2158
+		if res != exp {
2159
+			c.Fatalf("Env %q, expected %q for dockerfile:%q", res, exp, dockerfile)
2160
+		}
2161
+	}
2162
+
2163
+	tests := []struct{ dockerfile, exp string }{
2164
+		{"FROM scratch\nMAINTAINER me", "[PATH=" + defPath + "]"},
2165
+		{"FROM busybox\nMAINTAINER me", "[PATH=" + defPath + "]"},
2166
+		{"FROM scratch\nENV FOO=bar", "[PATH=" + defPath + " FOO=bar]"},
2167
+		{"FROM busybox\nENV FOO=bar", "[PATH=" + defPath + " FOO=bar]"},
2168
+		{"FROM scratch\nENV PATH=/test", "[PATH=/test]"},
2169
+		{"FROM busybox\nENV PATH=/test", "[PATH=/test]"},
2170
+		{"FROM scratch\nENV PATH=''", "[PATH=]"},
2171
+		{"FROM busybox\nENV PATH=''", "[PATH=]"},
2172
+	}
2173
+
2174
+	for _, test := range tests {
2175
+		fn(test.dockerfile, test.exp)
2176
+	}
2177
+}
2178
+
2146 2179
 func (s *DockerSuite) TestBuildContextCleanup(c *check.C) {
2147 2180
 	testRequires(c, DaemonIsLinux)
2148 2181
 	testRequires(c, SameHostDaemon)