github.com/fabiokung/docker@v0.11.2-0.20170222101415-4534dcd49497/integration-cli/docker_cli_build_test.go (about)

     1  package main
     2  
     3  import (
     4  	"archive/tar"
     5  	"bytes"
     6  	"encoding/json"
     7  	"fmt"
     8  	"io/ioutil"
     9  	"os"
    10  	"path/filepath"
    11  	"reflect"
    12  	"regexp"
    13  	"runtime"
    14  	"strconv"
    15  	"strings"
    16  	"text/template"
    17  	"time"
    18  
    19  	"github.com/docker/docker/builder/dockerfile/command"
    20  	"github.com/docker/docker/integration-cli/checker"
    21  	"github.com/docker/docker/pkg/archive"
    22  	"github.com/docker/docker/pkg/stringutils"
    23  	"github.com/docker/docker/pkg/testutil"
    24  	icmd "github.com/docker/docker/pkg/testutil/cmd"
    25  	"github.com/go-check/check"
    26  )
    27  
    28  func (s *DockerSuite) TestBuildJSONEmptyRun(c *check.C) {
    29  	buildImageSuccessfully(c, "testbuildjsonemptyrun", withDockerfile(`
    30      FROM busybox
    31      RUN []
    32      `))
    33  }
    34  
    35  func (s *DockerSuite) TestBuildShCmdJSONEntrypoint(c *check.C) {
    36  	name := "testbuildshcmdjsonentrypoint"
    37  	expected := "/bin/sh -c echo test"
    38  	if testEnv.DaemonPlatform() == "windows" {
    39  		expected = "cmd /S /C echo test"
    40  	}
    41  
    42  	buildImageSuccessfully(c, name, withDockerfile(`
    43      FROM busybox
    44      ENTRYPOINT ["echo"]
    45      CMD echo test
    46      `))
    47  	out, _ := dockerCmd(c, "run", "--rm", name)
    48  
    49  	if strings.TrimSpace(out) != expected {
    50  		c.Fatalf("CMD did not contain %q : %q", expected, out)
    51  	}
    52  }
    53  
    54  func (s *DockerSuite) TestBuildEnvironmentReplacementUser(c *check.C) {
    55  	// Windows does not support FROM scratch or the USER command
    56  	testRequires(c, DaemonIsLinux)
    57  	name := "testbuildenvironmentreplacement"
    58  
    59  	buildImageSuccessfully(c, name, withDockerfile(`
    60    FROM scratch
    61    ENV user foo
    62    USER ${user}
    63    `))
    64  	res := inspectFieldJSON(c, name, "Config.User")
    65  
    66  	if res != `"foo"` {
    67  		c.Fatal("User foo from environment not in Config.User on image")
    68  	}
    69  }
    70  
    71  func (s *DockerSuite) TestBuildEnvironmentReplacementVolume(c *check.C) {
    72  	name := "testbuildenvironmentreplacement"
    73  
    74  	var volumePath string
    75  
    76  	if testEnv.DaemonPlatform() == "windows" {
    77  		volumePath = "c:/quux"
    78  	} else {
    79  		volumePath = "/quux"
    80  	}
    81  
    82  	buildImageSuccessfully(c, name, withDockerfile(`
    83    FROM `+minimalBaseImage()+`
    84    ENV volume `+volumePath+`
    85    VOLUME ${volume}
    86    `))
    87  
    88  	var volumes map[string]interface{}
    89  	inspectFieldAndUnmarshall(c, name, "Config.Volumes", &volumes)
    90  	if _, ok := volumes[volumePath]; !ok {
    91  		c.Fatal("Volume " + volumePath + " from environment not in Config.Volumes on image")
    92  	}
    93  
    94  }
    95  
    96  func (s *DockerSuite) TestBuildEnvironmentReplacementExpose(c *check.C) {
    97  	// Windows does not support FROM scratch or the EXPOSE command
    98  	testRequires(c, DaemonIsLinux)
    99  	name := "testbuildenvironmentreplacement"
   100  
   101  	buildImageSuccessfully(c, name, withDockerfile(`
   102    FROM scratch
   103    ENV port 80
   104    EXPOSE ${port}
   105    ENV ports "  99   100 "
   106    EXPOSE ${ports}
   107    `))
   108  
   109  	var exposedPorts map[string]interface{}
   110  	inspectFieldAndUnmarshall(c, name, "Config.ExposedPorts", &exposedPorts)
   111  	exp := []int{80, 99, 100}
   112  	for _, p := range exp {
   113  		tmp := fmt.Sprintf("%d/tcp", p)
   114  		if _, ok := exposedPorts[tmp]; !ok {
   115  			c.Fatalf("Exposed port %d from environment not in Config.ExposedPorts on image", p)
   116  		}
   117  	}
   118  
   119  }
   120  
   121  func (s *DockerSuite) TestBuildEnvironmentReplacementWorkdir(c *check.C) {
   122  	name := "testbuildenvironmentreplacement"
   123  
   124  	buildImageSuccessfully(c, name, withDockerfile(`
   125    FROM busybox
   126    ENV MYWORKDIR /work
   127    RUN mkdir ${MYWORKDIR}
   128    WORKDIR ${MYWORKDIR}
   129    `))
   130  	res := inspectFieldJSON(c, name, "Config.WorkingDir")
   131  
   132  	expected := `"/work"`
   133  	if testEnv.DaemonPlatform() == "windows" {
   134  		expected = `"C:\\work"`
   135  	}
   136  	if res != expected {
   137  		c.Fatalf("Workdir /workdir from environment not in Config.WorkingDir on image: %s", res)
   138  	}
   139  }
   140  
   141  func (s *DockerSuite) TestBuildEnvironmentReplacementAddCopy(c *check.C) {
   142  	name := "testbuildenvironmentreplacement"
   143  
   144  	buildImageSuccessfully(c, name, withBuildContext(c,
   145  		withFile("Dockerfile", `
   146    FROM `+minimalBaseImage()+`
   147    ENV baz foo
   148    ENV quux bar
   149    ENV dot .
   150    ENV fee fff
   151    ENV gee ggg
   152  
   153    ADD ${baz} ${dot}
   154    COPY ${quux} ${dot}
   155    ADD ${zzz:-${fee}} ${dot}
   156    COPY ${zzz:-${gee}} ${dot}
   157    `),
   158  		withFile("foo", "test1"),
   159  		withFile("bar", "test2"),
   160  		withFile("fff", "test3"),
   161  		withFile("ggg", "test4"),
   162  	))
   163  }
   164  
   165  func (s *DockerSuite) TestBuildEnvironmentReplacementEnv(c *check.C) {
   166  	// ENV expansions work differently in Windows
   167  	testRequires(c, DaemonIsLinux)
   168  	name := "testbuildenvironmentreplacement"
   169  
   170  	buildImageSuccessfully(c, name, withDockerfile(`
   171    FROM busybox
   172    ENV foo zzz
   173    ENV bar ${foo}
   174    ENV abc1='$foo'
   175    ENV env1=$foo env2=${foo} env3="$foo" env4="${foo}"
   176    RUN [ "$abc1" = '$foo' ] && (echo "$abc1" | grep -q foo)
   177    ENV abc2="\$foo"
   178    RUN [ "$abc2" = '$foo' ] && (echo "$abc2" | grep -q foo)
   179    ENV abc3 '$foo'
   180    RUN [ "$abc3" = '$foo' ] && (echo "$abc3" | grep -q foo)
   181    ENV abc4 "\$foo"
   182    RUN [ "$abc4" = '$foo' ] && (echo "$abc4" | grep -q foo)
   183    `))
   184  
   185  	envResult := []string{}
   186  	inspectFieldAndUnmarshall(c, name, "Config.Env", &envResult)
   187  	found := false
   188  	envCount := 0
   189  
   190  	for _, env := range envResult {
   191  		parts := strings.SplitN(env, "=", 2)
   192  		if parts[0] == "bar" {
   193  			found = true
   194  			if parts[1] != "zzz" {
   195  				c.Fatalf("Could not find replaced var for env `bar`: got %q instead of `zzz`", parts[1])
   196  			}
   197  		} else if strings.HasPrefix(parts[0], "env") {
   198  			envCount++
   199  			if parts[1] != "zzz" {
   200  				c.Fatalf("%s should be 'foo' but instead its %q", parts[0], parts[1])
   201  			}
   202  		} else if strings.HasPrefix(parts[0], "env") {
   203  			envCount++
   204  			if parts[1] != "foo" {
   205  				c.Fatalf("%s should be 'foo' but instead its %q", parts[0], parts[1])
   206  			}
   207  		}
   208  	}
   209  
   210  	if !found {
   211  		c.Fatal("Never found the `bar` env variable")
   212  	}
   213  
   214  	if envCount != 4 {
   215  		c.Fatalf("Didn't find all env vars - only saw %d\n%s", envCount, envResult)
   216  	}
   217  
   218  }
   219  
   220  func (s *DockerSuite) TestBuildHandleEscapesInVolume(c *check.C) {
   221  	// The volume paths used in this test are invalid on Windows
   222  	testRequires(c, DaemonIsLinux)
   223  	name := "testbuildhandleescapes"
   224  
   225  	testCases := []struct {
   226  		volumeValue string
   227  		expected    string
   228  	}{
   229  		{
   230  			volumeValue: "${FOO}",
   231  			expected:    "bar",
   232  		},
   233  		{
   234  			volumeValue: `\${FOO}`,
   235  			expected:    "${FOO}",
   236  		},
   237  		// this test in particular provides *7* backslashes and expects 6 to come back.
   238  		// Like above, the first escape is swallowed and the rest are treated as
   239  		// literals, this one is just less obvious because of all the character noise.
   240  		{
   241  			volumeValue: `\\\\\\\${FOO}`,
   242  			expected:    `\\\${FOO}`,
   243  		},
   244  	}
   245  
   246  	for _, tc := range testCases {
   247  		buildImageSuccessfully(c, name, withDockerfile(fmt.Sprintf(`
   248    FROM scratch
   249    ENV FOO bar
   250    VOLUME %s
   251    `, tc.volumeValue)))
   252  
   253  		var result map[string]map[string]struct{}
   254  		inspectFieldAndUnmarshall(c, name, "Config.Volumes", &result)
   255  		if _, ok := result[tc.expected]; !ok {
   256  			c.Fatalf("Could not find volume %s set from env foo in volumes table, got %q", tc.expected, result)
   257  		}
   258  
   259  		// Remove the image for the next iteration
   260  		dockerCmd(c, "rmi", name)
   261  	}
   262  }
   263  
   264  func (s *DockerSuite) TestBuildOnBuildLowercase(c *check.C) {
   265  	name := "testbuildonbuildlowercase"
   266  	name2 := "testbuildonbuildlowercase2"
   267  
   268  	buildImageSuccessfully(c, name, withDockerfile(`
   269    FROM busybox
   270    onbuild run echo quux
   271    `))
   272  
   273  	result := buildImage(name2, withDockerfile(fmt.Sprintf(`
   274    FROM %s
   275    `, name)))
   276  	result.Assert(c, icmd.Success)
   277  
   278  	if !strings.Contains(result.Combined(), "quux") {
   279  		c.Fatalf("Did not receive the expected echo text, got %s", result.Combined())
   280  	}
   281  
   282  	if strings.Contains(result.Combined(), "ONBUILD ONBUILD") {
   283  		c.Fatalf("Got an ONBUILD ONBUILD error with no error: got %s", result.Combined())
   284  	}
   285  
   286  }
   287  
   288  func (s *DockerSuite) TestBuildEnvEscapes(c *check.C) {
   289  	// ENV expansions work differently in Windows
   290  	testRequires(c, DaemonIsLinux)
   291  	name := "testbuildenvescapes"
   292  	buildImageSuccessfully(c, name, withDockerfile(`
   293      FROM busybox
   294      ENV TEST foo
   295      CMD echo \$
   296      `))
   297  
   298  	out, _ := dockerCmd(c, "run", "-t", name)
   299  	if strings.TrimSpace(out) != "$" {
   300  		c.Fatalf("Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q", strings.TrimSpace(out))
   301  	}
   302  
   303  }
   304  
   305  func (s *DockerSuite) TestBuildEnvOverwrite(c *check.C) {
   306  	// ENV expansions work differently in Windows
   307  	testRequires(c, DaemonIsLinux)
   308  	name := "testbuildenvoverwrite"
   309  	buildImageSuccessfully(c, name, withDockerfile(`
   310      FROM busybox
   311      ENV TEST foo
   312      CMD echo ${TEST}
   313      `))
   314  
   315  	out, _ := dockerCmd(c, "run", "-e", "TEST=bar", "-t", name)
   316  	if strings.TrimSpace(out) != "bar" {
   317  		c.Fatalf("Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q", strings.TrimSpace(out))
   318  	}
   319  
   320  }
   321  
   322  // FIXME(vdemeester) why we disabled cache here ?
   323  func (s *DockerSuite) TestBuildOnBuildCmdEntrypointJSON(c *check.C) {
   324  	name1 := "onbuildcmd"
   325  	name2 := "onbuildgenerated"
   326  
   327  	buildImageSuccessfully(c, name1, withDockerfile(`
   328  FROM busybox
   329  ONBUILD CMD ["hello world"]
   330  ONBUILD ENTRYPOINT ["echo"]
   331  ONBUILD RUN ["true"]`))
   332  
   333  	buildImageSuccessfully(c, name2, withDockerfile(fmt.Sprintf(`FROM %s`, name1)))
   334  
   335  	out, _ := dockerCmd(c, "run", name2)
   336  	if !regexp.MustCompile(`(?m)^hello world`).MatchString(out) {
   337  		c.Fatalf("did not get echo output from onbuild. Got: %q", out)
   338  	}
   339  
   340  }
   341  
   342  // FIXME(vdemeester) why we disabled cache here ?
   343  func (s *DockerSuite) TestBuildOnBuildEntrypointJSON(c *check.C) {
   344  	name1 := "onbuildcmd"
   345  	name2 := "onbuildgenerated"
   346  
   347  	buildImageSuccessfully(c, name1, withDockerfile(`
   348  FROM busybox
   349  ONBUILD ENTRYPOINT ["echo"]`))
   350  
   351  	buildImageSuccessfully(c, name2, withDockerfile(fmt.Sprintf("FROM %s\nCMD [\"hello world\"]\n", name1)))
   352  
   353  	out, _ := dockerCmd(c, "run", name2)
   354  	if !regexp.MustCompile(`(?m)^hello world`).MatchString(out) {
   355  		c.Fatal("got malformed output from onbuild", out)
   356  	}
   357  
   358  }
   359  
   360  func (s *DockerSuite) TestBuildCacheAdd(c *check.C) {
   361  	testRequires(c, DaemonIsLinux) // Windows doesn't have httpserver image yet
   362  	name := "testbuildtwoimageswithadd"
   363  	server := fakeStorage(c, map[string]string{
   364  		"robots.txt": "hello",
   365  		"index.html": "world",
   366  	})
   367  	defer server.Close()
   368  
   369  	buildImageSuccessfully(c, name, withDockerfile(fmt.Sprintf(`FROM scratch
   370  		ADD %s/robots.txt /`, server.URL())))
   371  
   372  	result := buildImage(name, withDockerfile(fmt.Sprintf(`FROM scratch
   373  		ADD %s/index.html /`, server.URL())))
   374  	result.Assert(c, icmd.Success)
   375  	if strings.Contains(result.Combined(), "Using cache") {
   376  		c.Fatal("2nd build used cache on ADD, it shouldn't")
   377  	}
   378  }
   379  
   380  func (s *DockerSuite) TestBuildLastModified(c *check.C) {
   381  	// Temporary fix for #30890. TODO @jhowardmsft figure out what
   382  	// has changed in the master busybox image.
   383  	testRequires(c, DaemonIsLinux)
   384  
   385  	name := "testbuildlastmodified"
   386  
   387  	server := fakeStorage(c, map[string]string{
   388  		"file": "hello",
   389  	})
   390  	defer server.Close()
   391  
   392  	var out, out2 string
   393  
   394  	dFmt := `FROM busybox
   395  ADD %s/file /`
   396  	dockerfile := fmt.Sprintf(dFmt, server.URL())
   397  
   398  	buildImageSuccessfully(c, name, withoutCache, withDockerfile(dockerfile))
   399  	out, _ = dockerCmd(c, "run", name, "ls", "-le", "/file")
   400  
   401  	// Build it again and make sure the mtime of the file didn't change.
   402  	// Wait a few seconds to make sure the time changed enough to notice
   403  	time.Sleep(2 * time.Second)
   404  
   405  	buildImageSuccessfully(c, name, withoutCache, withDockerfile(dockerfile))
   406  	out2, _ = dockerCmd(c, "run", name, "ls", "-le", "/file")
   407  
   408  	if out != out2 {
   409  		c.Fatalf("MTime changed:\nOrigin:%s\nNew:%s", out, out2)
   410  	}
   411  
   412  	// Now 'touch' the file and make sure the timestamp DID change this time
   413  	// Create a new fakeStorage instead of just using Add() to help windows
   414  	server = fakeStorage(c, map[string]string{
   415  		"file": "hello",
   416  	})
   417  	defer server.Close()
   418  
   419  	dockerfile = fmt.Sprintf(dFmt, server.URL())
   420  	buildImageSuccessfully(c, name, withoutCache, withDockerfile(dockerfile))
   421  	out2, _ = dockerCmd(c, "run", name, "ls", "-le", "/file")
   422  
   423  	if out == out2 {
   424  		c.Fatalf("MTime didn't change:\nOrigin:%s\nNew:%s", out, out2)
   425  	}
   426  
   427  }
   428  
   429  // Regression for https://github.com/docker/docker/pull/27805
   430  // Makes sure that we don't use the cache if the contents of
   431  // a file in a subfolder of the context is modified and we re-build.
   432  func (s *DockerSuite) TestBuildModifyFileInFolder(c *check.C) {
   433  	name := "testbuildmodifyfileinfolder"
   434  
   435  	ctx := fakeContext(c, `FROM busybox
   436  RUN ["mkdir", "/test"]
   437  ADD folder/file /test/changetarget`,
   438  		map[string]string{})
   439  	defer ctx.Close()
   440  	if err := ctx.Add("folder/file", "first"); err != nil {
   441  		c.Fatal(err)
   442  	}
   443  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
   444  	id1 := getIDByName(c, name)
   445  	if err := ctx.Add("folder/file", "second"); err != nil {
   446  		c.Fatal(err)
   447  	}
   448  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
   449  	id2 := getIDByName(c, name)
   450  	if id1 == id2 {
   451  		c.Fatal("cache was used even though file contents in folder was changed")
   452  	}
   453  }
   454  
   455  func (s *DockerSuite) TestBuildAddSingleFileToRoot(c *check.C) {
   456  	testRequires(c, DaemonIsLinux) // Linux specific test
   457  	buildImageSuccessfully(c, "testaddimg", withBuildContext(c,
   458  		withFile("Dockerfile", fmt.Sprintf(`FROM busybox
   459  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   460  RUN echo 'dockerio:x:1001:' >> /etc/group
   461  RUN touch /exists
   462  RUN chown dockerio.dockerio /exists
   463  ADD test_file /
   464  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
   465  RUN [ $(ls -l /test_file | awk '{print $1}') = '%s' ]
   466  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod)),
   467  		withFile("test_file", "test1")))
   468  }
   469  
   470  // Issue #3960: "ADD src ." hangs
   471  func (s *DockerSuite) TestBuildAddSingleFileToWorkdir(c *check.C) {
   472  	name := "testaddsinglefiletoworkdir"
   473  	ctx := fakeContext(c, `FROM busybox
   474  ADD test_file .`,
   475  		map[string]string{
   476  			"test_file": "test1",
   477  		})
   478  	defer ctx.Close()
   479  
   480  	errChan := make(chan error)
   481  	go func() {
   482  		errChan <- buildImage(name, withExternalBuildContext(ctx)).Error
   483  		close(errChan)
   484  	}()
   485  	select {
   486  	case <-time.After(15 * time.Second):
   487  		c.Fatal("Build with adding to workdir timed out")
   488  	case err := <-errChan:
   489  		c.Assert(err, check.IsNil)
   490  	}
   491  }
   492  
   493  func (s *DockerSuite) TestBuildAddSingleFileToExistDir(c *check.C) {
   494  	testRequires(c, DaemonIsLinux) // Linux specific test
   495  	buildImageSuccessfully(c, "testaddsinglefiletoexistdir", withBuildContext(c,
   496  		withFile("Dockerfile", `FROM busybox
   497  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   498  RUN echo 'dockerio:x:1001:' >> /etc/group
   499  RUN mkdir /exists
   500  RUN touch /exists/exists_file
   501  RUN chown -R dockerio.dockerio /exists
   502  ADD test_file /exists/
   503  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   504  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]
   505  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`),
   506  		withFile("test_file", "test1")))
   507  }
   508  
   509  func (s *DockerSuite) TestBuildCopyAddMultipleFiles(c *check.C) {
   510  	testRequires(c, DaemonIsLinux) // Linux specific test
   511  	server := fakeStorage(c, map[string]string{
   512  		"robots.txt": "hello",
   513  	})
   514  	defer server.Close()
   515  
   516  	buildImageSuccessfully(c, "testcopymultiplefilestofile", withBuildContext(c,
   517  		withFile("Dockerfile", fmt.Sprintf(`FROM busybox
   518  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   519  RUN echo 'dockerio:x:1001:' >> /etc/group
   520  RUN mkdir /exists
   521  RUN touch /exists/exists_file
   522  RUN chown -R dockerio.dockerio /exists
   523  COPY test_file1 test_file2 /exists/
   524  ADD test_file3 test_file4 %s/robots.txt /exists/
   525  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   526  RUN [ $(ls -l /exists/test_file1 | awk '{print $3":"$4}') = 'root:root' ]
   527  RUN [ $(ls -l /exists/test_file2 | awk '{print $3":"$4}') = 'root:root' ]
   528  RUN [ $(ls -l /exists/test_file3 | awk '{print $3":"$4}') = 'root:root' ]
   529  RUN [ $(ls -l /exists/test_file4 | awk '{print $3":"$4}') = 'root:root' ]
   530  RUN [ $(ls -l /exists/robots.txt | awk '{print $3":"$4}') = 'root:root' ]
   531  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   532  `, server.URL())),
   533  		withFile("test_file1", "test1"),
   534  		withFile("test_file2", "test2"),
   535  		withFile("test_file3", "test3"),
   536  		withFile("test_file3", "test3"),
   537  		withFile("test_file4", "test4")))
   538  }
   539  
   540  // These tests are mainly for user namespaces to verify that new directories
   541  // are created as the remapped root uid/gid pair
   542  func (s *DockerSuite) TestBuildUsernamespaceValidateRemappedRoot(c *check.C) {
   543  	testRequires(c, DaemonIsLinux)
   544  	testCases := []string{
   545  		"ADD . /new_dir",
   546  		"COPY test_dir /new_dir",
   547  		"WORKDIR /new_dir",
   548  	}
   549  	name := "testbuildusernamespacevalidateremappedroot"
   550  	for _, tc := range testCases {
   551  		buildImageSuccessfully(c, name, withBuildContext(c,
   552  			withFile("Dockerfile", fmt.Sprintf(`FROM busybox
   553  %s
   554  RUN [ $(ls -l / | grep new_dir | awk '{print $3":"$4}') = 'root:root' ]`, tc)),
   555  			withFile("test_dir/test_file", "test file")))
   556  
   557  		dockerCmd(c, "rmi", name)
   558  	}
   559  }
   560  
   561  func (s *DockerSuite) TestBuildAddAndCopyFileWithWhitespace(c *check.C) {
   562  	testRequires(c, DaemonIsLinux) // Not currently passing on Windows
   563  	name := "testaddfilewithwhitespace"
   564  
   565  	for _, command := range []string{"ADD", "COPY"} {
   566  		buildImageSuccessfully(c, name, withBuildContext(c,
   567  			withFile("Dockerfile", fmt.Sprintf(`FROM busybox
   568  RUN mkdir "/test dir"
   569  RUN mkdir "/test_dir"
   570  %s [ "test file1", "/test_file1" ]
   571  %s [ "test_file2", "/test file2" ]
   572  %s [ "test file3", "/test file3" ]
   573  %s [ "test dir/test_file4", "/test_dir/test_file4" ]
   574  %s [ "test_dir/test_file5", "/test dir/test_file5" ]
   575  %s [ "test dir/test_file6", "/test dir/test_file6" ]
   576  RUN [ $(cat "/test_file1") = 'test1' ]
   577  RUN [ $(cat "/test file2") = 'test2' ]
   578  RUN [ $(cat "/test file3") = 'test3' ]
   579  RUN [ $(cat "/test_dir/test_file4") = 'test4' ]
   580  RUN [ $(cat "/test dir/test_file5") = 'test5' ]
   581  RUN [ $(cat "/test dir/test_file6") = 'test6' ]`, command, command, command, command, command, command)),
   582  			withFile("test file1", "test1"),
   583  			withFile("test_file2", "test2"),
   584  			withFile("test file3", "test3"),
   585  			withFile("test dir/test_file4", "test4"),
   586  			withFile("test_dir/test_file5", "test5"),
   587  			withFile("test dir/test_file6", "test6"),
   588  		))
   589  
   590  		dockerCmd(c, "rmi", name)
   591  	}
   592  }
   593  
   594  func (s *DockerSuite) TestBuildCopyFileWithWhitespaceOnWindows(c *check.C) {
   595  	testRequires(c, DaemonIsWindows)
   596  	dockerfile := `FROM ` + testEnv.MinimalBaseImage() + `
   597  RUN mkdir "C:/test dir"
   598  RUN mkdir "C:/test_dir"
   599  COPY [ "test file1", "/test_file1" ]
   600  COPY [ "test_file2", "/test file2" ]
   601  COPY [ "test file3", "/test file3" ]
   602  COPY [ "test dir/test_file4", "/test_dir/test_file4" ]
   603  COPY [ "test_dir/test_file5", "/test dir/test_file5" ]
   604  COPY [ "test dir/test_file6", "/test dir/test_file6" ]
   605  RUN find "test1" "C:/test_file1"
   606  RUN find "test2" "C:/test file2"
   607  RUN find "test3" "C:/test file3"
   608  RUN find "test4" "C:/test_dir/test_file4"
   609  RUN find "test5" "C:/test dir/test_file5"
   610  RUN find "test6" "C:/test dir/test_file6"`
   611  
   612  	name := "testcopyfilewithwhitespace"
   613  	buildImageSuccessfully(c, name, withBuildContext(c,
   614  		withFile("Dockerfile", dockerfile),
   615  		withFile("test file1", "test1"),
   616  		withFile("test_file2", "test2"),
   617  		withFile("test file3", "test3"),
   618  		withFile("test dir/test_file4", "test4"),
   619  		withFile("test_dir/test_file5", "test5"),
   620  		withFile("test dir/test_file6", "test6"),
   621  	))
   622  }
   623  
   624  func (s *DockerSuite) TestBuildCopyWildcard(c *check.C) {
   625  	name := "testcopywildcard"
   626  	server := fakeStorage(c, map[string]string{
   627  		"robots.txt": "hello",
   628  		"index.html": "world",
   629  	})
   630  	defer server.Close()
   631  
   632  	ctx := fakeContext(c, fmt.Sprintf(`FROM busybox
   633  	COPY file*.txt /tmp/
   634  	RUN ls /tmp/file1.txt /tmp/file2.txt
   635  	RUN [ "mkdir",  "/tmp1" ]
   636  	COPY dir* /tmp1/
   637  	RUN ls /tmp1/dirt /tmp1/nested_file /tmp1/nested_dir/nest_nest_file
   638  	RUN [ "mkdir",  "/tmp2" ]
   639          ADD dir/*dir %s/robots.txt /tmp2/
   640  	RUN ls /tmp2/nest_nest_file /tmp2/robots.txt
   641  	`, server.URL()),
   642  		map[string]string{
   643  			"file1.txt":                     "test1",
   644  			"file2.txt":                     "test2",
   645  			"dir/nested_file":               "nested file",
   646  			"dir/nested_dir/nest_nest_file": "2 times nested",
   647  			"dirt": "dirty",
   648  		})
   649  	defer ctx.Close()
   650  
   651  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
   652  	id1 := getIDByName(c, name)
   653  
   654  	// Now make sure we use a cache the 2nd time
   655  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
   656  	id2 := getIDByName(c, name)
   657  
   658  	if id1 != id2 {
   659  		c.Fatal("didn't use the cache")
   660  	}
   661  
   662  }
   663  
   664  func (s *DockerSuite) TestBuildCopyWildcardInName(c *check.C) {
   665  	// Run this only on Linux
   666  	// Below is the original comment (that I don't agree with — vdemeester)
   667  	// Normally we would do c.Fatal(err) here but given that
   668  	// the odds of this failing are so rare, it must be because
   669  	// the OS we're running the client on doesn't support * in
   670  	// filenames (like windows).  So, instead of failing the test
   671  	// just let it pass. Then we don't need to explicitly
   672  	// say which OSs this works on or not.
   673  	testRequires(c, DaemonIsLinux, UnixCli)
   674  
   675  	buildImageSuccessfully(c, "testcopywildcardinname", withBuildContext(c,
   676  		withFile("Dockerfile", `FROM busybox
   677  	COPY *.txt /tmp/
   678  	RUN [ "$(cat /tmp/\*.txt)" = 'hi there' ]
   679  	`),
   680  		withFile("*.txt", "hi there"),
   681  	))
   682  }
   683  
   684  func (s *DockerSuite) TestBuildCopyWildcardCache(c *check.C) {
   685  	name := "testcopywildcardcache"
   686  	ctx := fakeContext(c, `FROM busybox
   687  	COPY file1.txt /tmp/`,
   688  		map[string]string{
   689  			"file1.txt": "test1",
   690  		})
   691  	defer ctx.Close()
   692  
   693  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
   694  	id1 := getIDByName(c, name)
   695  
   696  	// Now make sure we use a cache the 2nd time even with wild cards.
   697  	// Use the same context so the file is the same and the checksum will match
   698  	ctx.Add("Dockerfile", `FROM busybox
   699  	COPY file*.txt /tmp/`)
   700  
   701  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
   702  	id2 := getIDByName(c, name)
   703  
   704  	if id1 != id2 {
   705  		c.Fatal("didn't use the cache")
   706  	}
   707  
   708  }
   709  
   710  func (s *DockerSuite) TestBuildAddSingleFileToNonExistingDir(c *check.C) {
   711  	testRequires(c, DaemonIsLinux) // Linux specific test
   712  	buildImageSuccessfully(c, "testaddsinglefiletononexistingdir", withBuildContext(c,
   713  		withFile("Dockerfile", `FROM busybox
   714  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   715  RUN echo 'dockerio:x:1001:' >> /etc/group
   716  RUN touch /exists
   717  RUN chown dockerio.dockerio /exists
   718  ADD test_file /test_dir/
   719  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
   720  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
   721  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`),
   722  		withFile("test_file", "test1")))
   723  }
   724  
   725  func (s *DockerSuite) TestBuildAddDirContentToRoot(c *check.C) {
   726  	testRequires(c, DaemonIsLinux) // Linux specific test
   727  	buildImageSuccessfully(c, "testadddircontenttoroot", withBuildContext(c,
   728  		withFile("Dockerfile", `FROM busybox
   729  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   730  RUN echo 'dockerio:x:1001:' >> /etc/group
   731  RUN touch /exists
   732  RUN chown dockerio.dockerio exists
   733  ADD test_dir /
   734  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
   735  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`),
   736  		withFile("test_dir/test_file", "test1")))
   737  }
   738  
   739  func (s *DockerSuite) TestBuildAddDirContentToExistingDir(c *check.C) {
   740  	testRequires(c, DaemonIsLinux) // Linux specific test
   741  	buildImageSuccessfully(c, "testadddircontenttoexistingdir", withBuildContext(c,
   742  		withFile("Dockerfile", `FROM busybox
   743  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   744  RUN echo 'dockerio:x:1001:' >> /etc/group
   745  RUN mkdir /exists
   746  RUN touch /exists/exists_file
   747  RUN chown -R dockerio.dockerio /exists
   748  ADD test_dir/ /exists/
   749  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   750  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   751  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]`),
   752  		withFile("test_dir/test_file", "test1")))
   753  }
   754  
   755  func (s *DockerSuite) TestBuildAddWholeDirToRoot(c *check.C) {
   756  	testRequires(c, DaemonIsLinux) // Linux specific test
   757  	buildImageSuccessfully(c, "testaddwholedirtoroot", withBuildContext(c,
   758  		withFile("Dockerfile", fmt.Sprintf(`FROM busybox
   759  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   760  RUN echo 'dockerio:x:1001:' >> /etc/group
   761  RUN touch /exists
   762  RUN chown dockerio.dockerio exists
   763  ADD test_dir /test_dir
   764  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
   765  RUN [ $(ls -l / | grep test_dir | awk '{print $1}') = 'drwxr-xr-x' ]
   766  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
   767  RUN [ $(ls -l /test_dir/test_file | awk '{print $1}') = '%s' ]
   768  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod)),
   769  		withFile("test_dir/test_file", "test1")))
   770  }
   771  
   772  // Testing #5941 : Having an etc directory in context conflicts with the /etc/mtab
   773  func (s *DockerSuite) TestBuildAddOrCopyEtcToRootShouldNotConflict(c *check.C) {
   774  	buildImageSuccessfully(c, "testaddetctoroot", withBuildContext(c,
   775  		withFile("Dockerfile", `FROM `+minimalBaseImage()+`
   776  ADD . /`),
   777  		withFile("etc/test_file", "test1")))
   778  	buildImageSuccessfully(c, "testcopyetctoroot", withBuildContext(c,
   779  		withFile("Dockerfile", `FROM `+minimalBaseImage()+`
   780  COPY . /`),
   781  		withFile("etc/test_file", "test1")))
   782  }
   783  
   784  // Testing #9401 : Losing setuid flag after a ADD
   785  func (s *DockerSuite) TestBuildAddPreservesFilesSpecialBits(c *check.C) {
   786  	testRequires(c, DaemonIsLinux) // Linux specific test
   787  	buildImageSuccessfully(c, "testaddetctoroot", withBuildContext(c,
   788  		withFile("Dockerfile", `FROM busybox
   789  ADD suidbin /usr/bin/suidbin
   790  RUN chmod 4755 /usr/bin/suidbin
   791  RUN [ $(ls -l /usr/bin/suidbin | awk '{print $1}') = '-rwsr-xr-x' ]
   792  ADD ./data/ /
   793  RUN [ $(ls -l /usr/bin/suidbin | awk '{print $1}') = '-rwsr-xr-x' ]`),
   794  		withFile("suidbin", "suidbin"),
   795  		withFile("/data/usr/test_file", "test1")))
   796  }
   797  
   798  func (s *DockerSuite) TestBuildCopySingleFileToRoot(c *check.C) {
   799  	testRequires(c, DaemonIsLinux) // Linux specific test
   800  	buildImageSuccessfully(c, "testcopysinglefiletoroot", withBuildContext(c,
   801  		withFile("Dockerfile", fmt.Sprintf(`FROM busybox
   802  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   803  RUN echo 'dockerio:x:1001:' >> /etc/group
   804  RUN touch /exists
   805  RUN chown dockerio.dockerio /exists
   806  COPY test_file /
   807  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
   808  RUN [ $(ls -l /test_file | awk '{print $1}') = '%s' ]
   809  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod)),
   810  		withFile("test_file", "test1")))
   811  }
   812  
   813  // Issue #3960: "ADD src ." hangs - adapted for COPY
   814  func (s *DockerSuite) TestBuildCopySingleFileToWorkdir(c *check.C) {
   815  	name := "testcopysinglefiletoworkdir"
   816  	ctx := fakeContext(c, `FROM busybox
   817  COPY test_file .`,
   818  		map[string]string{
   819  			"test_file": "test1",
   820  		})
   821  	defer ctx.Close()
   822  
   823  	errChan := make(chan error)
   824  	go func() {
   825  		errChan <- buildImage(name, withExternalBuildContext(ctx)).Error
   826  		close(errChan)
   827  	}()
   828  	select {
   829  	case <-time.After(15 * time.Second):
   830  		c.Fatal("Build with adding to workdir timed out")
   831  	case err := <-errChan:
   832  		c.Assert(err, check.IsNil)
   833  	}
   834  }
   835  
   836  func (s *DockerSuite) TestBuildCopySingleFileToExistDir(c *check.C) {
   837  	testRequires(c, DaemonIsLinux) // Linux specific test
   838  	buildImageSuccessfully(c, "testcopysinglefiletoexistdir", withBuildContext(c,
   839  		withFile("Dockerfile", `FROM busybox
   840  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   841  RUN echo 'dockerio:x:1001:' >> /etc/group
   842  RUN mkdir /exists
   843  RUN touch /exists/exists_file
   844  RUN chown -R dockerio.dockerio /exists
   845  COPY test_file /exists/
   846  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   847  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]
   848  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`),
   849  		withFile("test_file", "test1")))
   850  }
   851  
   852  func (s *DockerSuite) TestBuildCopySingleFileToNonExistDir(c *check.C) {
   853  	testRequires(c, DaemonIsLinux) // Linux specific
   854  	buildImageSuccessfully(c, "testcopysinglefiletononexistdir", withBuildContext(c,
   855  		withFile("Dockerfile", `FROM busybox
   856  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   857  RUN echo 'dockerio:x:1001:' >> /etc/group
   858  RUN touch /exists
   859  RUN chown dockerio.dockerio /exists
   860  COPY test_file /test_dir/
   861  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
   862  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
   863  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`),
   864  		withFile("test_file", "test1")))
   865  }
   866  
   867  func (s *DockerSuite) TestBuildCopyDirContentToRoot(c *check.C) {
   868  	testRequires(c, DaemonIsLinux) // Linux specific test
   869  	buildImageSuccessfully(c, "testcopydircontenttoroot", withBuildContext(c,
   870  		withFile("Dockerfile", `FROM busybox
   871  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   872  RUN echo 'dockerio:x:1001:' >> /etc/group
   873  RUN touch /exists
   874  RUN chown dockerio.dockerio exists
   875  COPY test_dir /
   876  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
   877  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`),
   878  		withFile("test_dir/test_file", "test1")))
   879  }
   880  
   881  func (s *DockerSuite) TestBuildCopyDirContentToExistDir(c *check.C) {
   882  	testRequires(c, DaemonIsLinux) // Linux specific test
   883  	buildImageSuccessfully(c, "testcopydircontenttoexistdir", withBuildContext(c,
   884  		withFile("Dockerfile", `FROM busybox
   885  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   886  RUN echo 'dockerio:x:1001:' >> /etc/group
   887  RUN mkdir /exists
   888  RUN touch /exists/exists_file
   889  RUN chown -R dockerio.dockerio /exists
   890  COPY test_dir/ /exists/
   891  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   892  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   893  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]`),
   894  		withFile("test_dir/test_file", "test1")))
   895  }
   896  
   897  func (s *DockerSuite) TestBuildCopyWholeDirToRoot(c *check.C) {
   898  	testRequires(c, DaemonIsLinux) // Linux specific test
   899  	buildImageSuccessfully(c, "testcopywholedirtoroot", withBuildContext(c,
   900  		withFile("Dockerfile", fmt.Sprintf(`FROM busybox
   901  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   902  RUN echo 'dockerio:x:1001:' >> /etc/group
   903  RUN touch /exists
   904  RUN chown dockerio.dockerio exists
   905  COPY test_dir /test_dir
   906  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
   907  RUN [ $(ls -l / | grep test_dir | awk '{print $1}') = 'drwxr-xr-x' ]
   908  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
   909  RUN [ $(ls -l /test_dir/test_file | awk '{print $1}') = '%s' ]
   910  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod)),
   911  		withFile("test_dir/test_file", "test1")))
   912  }
   913  
   914  func (s *DockerSuite) TestBuildAddBadLinks(c *check.C) {
   915  	testRequires(c, DaemonIsLinux) // Not currently working on Windows
   916  
   917  	dockerfile := `
   918  		FROM scratch
   919  		ADD links.tar /
   920  		ADD foo.txt /symlink/
   921  		`
   922  	targetFile := "foo.txt"
   923  	var (
   924  		name = "test-link-absolute"
   925  	)
   926  	ctx := fakeContext(c, dockerfile, nil)
   927  	defer ctx.Close()
   928  
   929  	tempDir, err := ioutil.TempDir("", "test-link-absolute-temp-")
   930  	if err != nil {
   931  		c.Fatalf("failed to create temporary directory: %s", tempDir)
   932  	}
   933  	defer os.RemoveAll(tempDir)
   934  
   935  	var symlinkTarget string
   936  	if runtime.GOOS == "windows" {
   937  		var driveLetter string
   938  		if abs, err := filepath.Abs(tempDir); err != nil {
   939  			c.Fatal(err)
   940  		} else {
   941  			driveLetter = abs[:1]
   942  		}
   943  		tempDirWithoutDrive := tempDir[2:]
   944  		symlinkTarget = fmt.Sprintf(`%s:\..\..\..\..\..\..\..\..\..\..\..\..%s`, driveLetter, tempDirWithoutDrive)
   945  	} else {
   946  		symlinkTarget = fmt.Sprintf("/../../../../../../../../../../../..%s", tempDir)
   947  	}
   948  
   949  	tarPath := filepath.Join(ctx.Dir, "links.tar")
   950  	nonExistingFile := filepath.Join(tempDir, targetFile)
   951  	fooPath := filepath.Join(ctx.Dir, targetFile)
   952  
   953  	tarOut, err := os.Create(tarPath)
   954  	if err != nil {
   955  		c.Fatal(err)
   956  	}
   957  
   958  	tarWriter := tar.NewWriter(tarOut)
   959  
   960  	header := &tar.Header{
   961  		Name:     "symlink",
   962  		Typeflag: tar.TypeSymlink,
   963  		Linkname: symlinkTarget,
   964  		Mode:     0755,
   965  		Uid:      0,
   966  		Gid:      0,
   967  	}
   968  
   969  	err = tarWriter.WriteHeader(header)
   970  	if err != nil {
   971  		c.Fatal(err)
   972  	}
   973  
   974  	tarWriter.Close()
   975  	tarOut.Close()
   976  
   977  	foo, err := os.Create(fooPath)
   978  	if err != nil {
   979  		c.Fatal(err)
   980  	}
   981  	defer foo.Close()
   982  
   983  	if _, err := foo.WriteString("test"); err != nil {
   984  		c.Fatal(err)
   985  	}
   986  
   987  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
   988  	if _, err := os.Stat(nonExistingFile); err == nil || err != nil && !os.IsNotExist(err) {
   989  		c.Fatalf("%s shouldn't have been written and it shouldn't exist", nonExistingFile)
   990  	}
   991  
   992  }
   993  
   994  func (s *DockerSuite) TestBuildAddBadLinksVolume(c *check.C) {
   995  	testRequires(c, DaemonIsLinux) // ln not implemented on Windows busybox
   996  	const (
   997  		dockerfileTemplate = `
   998  		FROM busybox
   999  		RUN ln -s /../../../../../../../../%s /x
  1000  		VOLUME /x
  1001  		ADD foo.txt /x/`
  1002  		targetFile = "foo.txt"
  1003  	)
  1004  	var (
  1005  		name       = "test-link-absolute-volume"
  1006  		dockerfile = ""
  1007  	)
  1008  
  1009  	tempDir, err := ioutil.TempDir("", "test-link-absolute-volume-temp-")
  1010  	if err != nil {
  1011  		c.Fatalf("failed to create temporary directory: %s", tempDir)
  1012  	}
  1013  	defer os.RemoveAll(tempDir)
  1014  
  1015  	dockerfile = fmt.Sprintf(dockerfileTemplate, tempDir)
  1016  	nonExistingFile := filepath.Join(tempDir, targetFile)
  1017  
  1018  	ctx := fakeContext(c, dockerfile, nil)
  1019  	defer ctx.Close()
  1020  	fooPath := filepath.Join(ctx.Dir, targetFile)
  1021  
  1022  	foo, err := os.Create(fooPath)
  1023  	if err != nil {
  1024  		c.Fatal(err)
  1025  	}
  1026  	defer foo.Close()
  1027  
  1028  	if _, err := foo.WriteString("test"); err != nil {
  1029  		c.Fatal(err)
  1030  	}
  1031  
  1032  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  1033  	if _, err := os.Stat(nonExistingFile); err == nil || err != nil && !os.IsNotExist(err) {
  1034  		c.Fatalf("%s shouldn't have been written and it shouldn't exist", nonExistingFile)
  1035  	}
  1036  
  1037  }
  1038  
  1039  // Issue #5270 - ensure we throw a better error than "unexpected EOF"
  1040  // when we can't access files in the context.
  1041  func (s *DockerSuite) TestBuildWithInaccessibleFilesInContext(c *check.C) {
  1042  	testRequires(c, DaemonIsLinux, UnixCli) // test uses chown/chmod: not available on windows
  1043  
  1044  	{
  1045  		name := "testbuildinaccessiblefiles"
  1046  		ctx := fakeContext(c, "FROM scratch\nADD . /foo/", map[string]string{"fileWithoutReadAccess": "foo"})
  1047  		defer ctx.Close()
  1048  		// This is used to ensure we detect inaccessible files early during build in the cli client
  1049  		pathToFileWithoutReadAccess := filepath.Join(ctx.Dir, "fileWithoutReadAccess")
  1050  
  1051  		if err := os.Chown(pathToFileWithoutReadAccess, 0, 0); err != nil {
  1052  			c.Fatalf("failed to chown file to root: %s", err)
  1053  		}
  1054  		if err := os.Chmod(pathToFileWithoutReadAccess, 0700); err != nil {
  1055  			c.Fatalf("failed to chmod file to 700: %s", err)
  1056  		}
  1057  		result := icmd.RunCmd(icmd.Cmd{
  1058  			Command: []string{"su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name)},
  1059  			Dir:     ctx.Dir,
  1060  		})
  1061  		if result.Error == nil {
  1062  			c.Fatalf("build should have failed: %s %s", result.Error, result.Combined())
  1063  		}
  1064  
  1065  		// check if we've detected the failure before we started building
  1066  		if !strings.Contains(result.Combined(), "no permission to read from ") {
  1067  			c.Fatalf("output should've contained the string: no permission to read from but contained: %s", result.Combined())
  1068  		}
  1069  
  1070  		if !strings.Contains(result.Combined(), "Error checking context") {
  1071  			c.Fatalf("output should've contained the string: Error checking context")
  1072  		}
  1073  	}
  1074  	{
  1075  		name := "testbuildinaccessibledirectory"
  1076  		ctx := fakeContext(c, "FROM scratch\nADD . /foo/", map[string]string{"directoryWeCantStat/bar": "foo"})
  1077  		defer ctx.Close()
  1078  		// This is used to ensure we detect inaccessible directories early during build in the cli client
  1079  		pathToDirectoryWithoutReadAccess := filepath.Join(ctx.Dir, "directoryWeCantStat")
  1080  		pathToFileInDirectoryWithoutReadAccess := filepath.Join(pathToDirectoryWithoutReadAccess, "bar")
  1081  
  1082  		if err := os.Chown(pathToDirectoryWithoutReadAccess, 0, 0); err != nil {
  1083  			c.Fatalf("failed to chown directory to root: %s", err)
  1084  		}
  1085  		if err := os.Chmod(pathToDirectoryWithoutReadAccess, 0444); err != nil {
  1086  			c.Fatalf("failed to chmod directory to 444: %s", err)
  1087  		}
  1088  		if err := os.Chmod(pathToFileInDirectoryWithoutReadAccess, 0700); err != nil {
  1089  			c.Fatalf("failed to chmod file to 700: %s", err)
  1090  		}
  1091  
  1092  		result := icmd.RunCmd(icmd.Cmd{
  1093  			Command: []string{"su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name)},
  1094  			Dir:     ctx.Dir,
  1095  		})
  1096  		if result.Error == nil {
  1097  			c.Fatalf("build should have failed: %s %s", result.Error, result.Combined())
  1098  		}
  1099  
  1100  		// check if we've detected the failure before we started building
  1101  		if !strings.Contains(result.Combined(), "can't stat") {
  1102  			c.Fatalf("output should've contained the string: can't access %s", result.Combined())
  1103  		}
  1104  
  1105  		if !strings.Contains(result.Combined(), "Error checking context") {
  1106  			c.Fatalf("output should've contained the string: Error checking context\ngot:%s", result.Combined())
  1107  		}
  1108  
  1109  	}
  1110  	{
  1111  		name := "testlinksok"
  1112  		ctx := fakeContext(c, "FROM scratch\nADD . /foo/", nil)
  1113  		defer ctx.Close()
  1114  
  1115  		target := "../../../../../../../../../../../../../../../../../../../azA"
  1116  		if err := os.Symlink(filepath.Join(ctx.Dir, "g"), target); err != nil {
  1117  			c.Fatal(err)
  1118  		}
  1119  		defer os.Remove(target)
  1120  		// This is used to ensure we don't follow links when checking if everything in the context is accessible
  1121  		// This test doesn't require that we run commands as an unprivileged user
  1122  		buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  1123  	}
  1124  	{
  1125  		name := "testbuildignoredinaccessible"
  1126  		ctx := fakeContext(c, "FROM scratch\nADD . /foo/",
  1127  			map[string]string{
  1128  				"directoryWeCantStat/bar": "foo",
  1129  				".dockerignore":           "directoryWeCantStat",
  1130  			})
  1131  		defer ctx.Close()
  1132  		// This is used to ensure we don't try to add inaccessible files when they are ignored by a .dockerignore pattern
  1133  		pathToDirectoryWithoutReadAccess := filepath.Join(ctx.Dir, "directoryWeCantStat")
  1134  		pathToFileInDirectoryWithoutReadAccess := filepath.Join(pathToDirectoryWithoutReadAccess, "bar")
  1135  		if err := os.Chown(pathToDirectoryWithoutReadAccess, 0, 0); err != nil {
  1136  			c.Fatalf("failed to chown directory to root: %s", err)
  1137  		}
  1138  		if err := os.Chmod(pathToDirectoryWithoutReadAccess, 0444); err != nil {
  1139  			c.Fatalf("failed to chmod directory to 444: %s", err)
  1140  		}
  1141  		if err := os.Chmod(pathToFileInDirectoryWithoutReadAccess, 0700); err != nil {
  1142  			c.Fatalf("failed to chmod file to 700: %s", err)
  1143  		}
  1144  
  1145  		result := icmd.RunCmd(icmd.Cmd{
  1146  			Dir: ctx.Dir,
  1147  			Command: []string{"su", "unprivilegeduser", "-c",
  1148  				fmt.Sprintf("%s build -t %s .", dockerBinary, name)},
  1149  		})
  1150  		result.Assert(c, icmd.Expected{})
  1151  	}
  1152  }
  1153  
  1154  func (s *DockerSuite) TestBuildForceRm(c *check.C) {
  1155  	containerCountBefore := getContainerCount(c)
  1156  	name := "testbuildforcerm"
  1157  
  1158  	buildImage(name, withBuildFlags("--force-rm"), withBuildContext(c,
  1159  		withFile("Dockerfile", `FROM `+minimalBaseImage()+`
  1160  	RUN true
  1161  	RUN thiswillfail`))).Assert(c, icmd.Expected{
  1162  		ExitCode: 1,
  1163  	})
  1164  
  1165  	containerCountAfter := getContainerCount(c)
  1166  	if containerCountBefore != containerCountAfter {
  1167  		c.Fatalf("--force-rm shouldn't have left containers behind")
  1168  	}
  1169  
  1170  }
  1171  
  1172  func (s *DockerSuite) TestBuildRm(c *check.C) {
  1173  	name := "testbuildrm"
  1174  
  1175  	testCases := []struct {
  1176  		buildflags                []string
  1177  		shouldLeftContainerBehind bool
  1178  	}{
  1179  		// Default case (i.e. --rm=true)
  1180  		{
  1181  			buildflags:                []string{},
  1182  			shouldLeftContainerBehind: false,
  1183  		},
  1184  		{
  1185  			buildflags:                []string{"--rm"},
  1186  			shouldLeftContainerBehind: false,
  1187  		},
  1188  		{
  1189  			buildflags:                []string{"--rm=false"},
  1190  			shouldLeftContainerBehind: true,
  1191  		},
  1192  	}
  1193  
  1194  	for _, tc := range testCases {
  1195  		containerCountBefore := getContainerCount(c)
  1196  
  1197  		buildImageSuccessfully(c, name, withBuildFlags(tc.buildflags...), withDockerfile(`FROM busybox
  1198  	RUN echo hello world`))
  1199  
  1200  		containerCountAfter := getContainerCount(c)
  1201  		if tc.shouldLeftContainerBehind {
  1202  			if containerCountBefore == containerCountAfter {
  1203  				c.Fatalf("flags %v should have left containers behind", tc.buildflags)
  1204  			}
  1205  		} else {
  1206  			if containerCountBefore != containerCountAfter {
  1207  				c.Fatalf("flags %v shouldn't have left containers behind", tc.buildflags)
  1208  			}
  1209  		}
  1210  
  1211  		dockerCmd(c, "rmi", name)
  1212  	}
  1213  }
  1214  
  1215  func (s *DockerSuite) TestBuildWithVolumes(c *check.C) {
  1216  	testRequires(c, DaemonIsLinux) // Invalid volume paths on Windows
  1217  	var (
  1218  		result   map[string]map[string]struct{}
  1219  		name     = "testbuildvolumes"
  1220  		emptyMap = make(map[string]struct{})
  1221  		expected = map[string]map[string]struct{}{
  1222  			"/test1":  emptyMap,
  1223  			"/test2":  emptyMap,
  1224  			"/test3":  emptyMap,
  1225  			"/test4":  emptyMap,
  1226  			"/test5":  emptyMap,
  1227  			"/test6":  emptyMap,
  1228  			"[/test7": emptyMap,
  1229  			"/test8]": emptyMap,
  1230  		}
  1231  	)
  1232  
  1233  	buildImageSuccessfully(c, name, withDockerfile(`FROM scratch
  1234  		VOLUME /test1
  1235  		VOLUME /test2
  1236      VOLUME /test3 /test4
  1237      VOLUME ["/test5", "/test6"]
  1238      VOLUME [/test7 /test8]
  1239      `))
  1240  
  1241  	inspectFieldAndUnmarshall(c, name, "Config.Volumes", &result)
  1242  
  1243  	equal := reflect.DeepEqual(&result, &expected)
  1244  	if !equal {
  1245  		c.Fatalf("Volumes %s, expected %s", result, expected)
  1246  	}
  1247  
  1248  }
  1249  
  1250  func (s *DockerSuite) TestBuildMaintainer(c *check.C) {
  1251  	name := "testbuildmaintainer"
  1252  
  1253  	buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+`
  1254          MAINTAINER dockerio`))
  1255  
  1256  	expected := "dockerio"
  1257  	res := inspectField(c, name, "Author")
  1258  	if res != expected {
  1259  		c.Fatalf("Maintainer %s, expected %s", res, expected)
  1260  	}
  1261  }
  1262  
  1263  func (s *DockerSuite) TestBuildUser(c *check.C) {
  1264  	testRequires(c, DaemonIsLinux)
  1265  	name := "testbuilduser"
  1266  	expected := "dockerio"
  1267  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  1268  		RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1269  		USER dockerio
  1270  		RUN [ $(whoami) = 'dockerio' ]`))
  1271  	res := inspectField(c, name, "Config.User")
  1272  	if res != expected {
  1273  		c.Fatalf("User %s, expected %s", res, expected)
  1274  	}
  1275  }
  1276  
  1277  func (s *DockerSuite) TestBuildRelativeWorkdir(c *check.C) {
  1278  	name := "testbuildrelativeworkdir"
  1279  
  1280  	var (
  1281  		expected1     string
  1282  		expected2     string
  1283  		expected3     string
  1284  		expected4     string
  1285  		expectedFinal string
  1286  	)
  1287  
  1288  	if testEnv.DaemonPlatform() == "windows" {
  1289  		expected1 = `C:/`
  1290  		expected2 = `C:/test1`
  1291  		expected3 = `C:/test2`
  1292  		expected4 = `C:/test2/test3`
  1293  		expectedFinal = `C:\test2\test3` // Note inspect is going to return Windows paths, as it's not in busybox
  1294  	} else {
  1295  		expected1 = `/`
  1296  		expected2 = `/test1`
  1297  		expected3 = `/test2`
  1298  		expected4 = `/test2/test3`
  1299  		expectedFinal = `/test2/test3`
  1300  	}
  1301  
  1302  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  1303  		RUN sh -c "[ "$PWD" = "`+expected1+`" ]"
  1304  		WORKDIR test1
  1305  		RUN sh -c "[ "$PWD" = "`+expected2+`" ]"
  1306  		WORKDIR /test2
  1307  		RUN sh -c "[ "$PWD" = "`+expected3+`" ]"
  1308  		WORKDIR test3
  1309  		RUN sh -c "[ "$PWD" = "`+expected4+`" ]"`))
  1310  
  1311  	res := inspectField(c, name, "Config.WorkingDir")
  1312  	if res != expectedFinal {
  1313  		c.Fatalf("Workdir %s, expected %s", res, expectedFinal)
  1314  	}
  1315  }
  1316  
  1317  // #22181 Regression test. Single end-to-end test of using
  1318  // Windows semantics. Most path handling verifications are in unit tests
  1319  func (s *DockerSuite) TestBuildWindowsWorkdirProcessing(c *check.C) {
  1320  	testRequires(c, DaemonIsWindows)
  1321  	buildImageSuccessfully(c, "testbuildwindowsworkdirprocessing", withDockerfile(`FROM busybox
  1322  		WORKDIR C:\\foo
  1323  		WORKDIR bar
  1324  		RUN sh -c "[ "$PWD" = "C:/foo/bar" ]"
  1325  		`))
  1326  }
  1327  
  1328  // #22181 Regression test. Most paths handling verifications are in unit test.
  1329  // One functional test for end-to-end
  1330  func (s *DockerSuite) TestBuildWindowsAddCopyPathProcessing(c *check.C) {
  1331  	testRequires(c, DaemonIsWindows)
  1332  	// TODO Windows (@jhowardmsft). Needs a follow-up PR to 22181 to
  1333  	// support backslash such as .\\ being equivalent to ./ and c:\\ being
  1334  	// equivalent to c:/. This is not currently (nor ever has been) supported
  1335  	// by docker on the Windows platform.
  1336  	buildImageSuccessfully(c, "testbuildwindowsaddcopypathprocessing", withBuildContext(c,
  1337  		withFile("Dockerfile", `FROM busybox
  1338  			# No trailing slash on COPY/ADD
  1339  			# Results in dir being changed to a file
  1340  			WORKDIR /wc1
  1341  			COPY wc1 c:/wc1
  1342  			WORKDIR /wc2
  1343  			ADD wc2 c:/wc2
  1344  			WORKDIR c:/
  1345  			RUN sh -c "[ $(cat c:/wc1/wc1) = 'hellowc1' ]"
  1346  			RUN sh -c "[ $(cat c:/wc2/wc2) = 'worldwc2' ]"
  1347  
  1348  			# Trailing slash on COPY/ADD, Windows-style path.
  1349  			WORKDIR /wd1
  1350  			COPY wd1 c:/wd1/
  1351  			WORKDIR /wd2
  1352  			ADD wd2 c:/wd2/
  1353  			RUN sh -c "[ $(cat c:/wd1/wd1) = 'hellowd1' ]"
  1354  			RUN sh -c "[ $(cat c:/wd2/wd2) = 'worldwd2' ]"
  1355  			`),
  1356  		withFile("wc1", "hellowc1"),
  1357  		withFile("wc2", "worldwc2"),
  1358  		withFile("wd1", "hellowd1"),
  1359  		withFile("wd2", "worldwd2"),
  1360  	))
  1361  }
  1362  
  1363  func (s *DockerSuite) TestBuildWorkdirWithEnvVariables(c *check.C) {
  1364  	name := "testbuildworkdirwithenvvariables"
  1365  
  1366  	var expected string
  1367  	if testEnv.DaemonPlatform() == "windows" {
  1368  		expected = `C:\test1\test2`
  1369  	} else {
  1370  		expected = `/test1/test2`
  1371  	}
  1372  
  1373  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  1374  		ENV DIRPATH /test1
  1375  		ENV SUBDIRNAME test2
  1376  		WORKDIR $DIRPATH
  1377  		WORKDIR $SUBDIRNAME/$MISSING_VAR`))
  1378  	res := inspectField(c, name, "Config.WorkingDir")
  1379  	if res != expected {
  1380  		c.Fatalf("Workdir %s, expected %s", res, expected)
  1381  	}
  1382  }
  1383  
  1384  func (s *DockerSuite) TestBuildRelativeCopy(c *check.C) {
  1385  	// cat /test1/test2/foo gets permission denied for the user
  1386  	testRequires(c, NotUserNamespace)
  1387  
  1388  	var expected string
  1389  	if testEnv.DaemonPlatform() == "windows" {
  1390  		expected = `C:/test1/test2`
  1391  	} else {
  1392  		expected = `/test1/test2`
  1393  	}
  1394  
  1395  	buildImageSuccessfully(c, "testbuildrelativecopy", withBuildContext(c,
  1396  		withFile("Dockerfile", `FROM busybox
  1397  			WORKDIR /test1
  1398  			WORKDIR test2
  1399  			RUN sh -c "[ "$PWD" = '`+expected+`' ]"
  1400  			COPY foo ./
  1401  			RUN sh -c "[ $(cat /test1/test2/foo) = 'hello' ]"
  1402  			ADD foo ./bar/baz
  1403  			RUN sh -c "[ $(cat /test1/test2/bar/baz) = 'hello' ]"
  1404  			COPY foo ./bar/baz2
  1405  			RUN sh -c "[ $(cat /test1/test2/bar/baz2) = 'hello' ]"
  1406  			WORKDIR ..
  1407  			COPY foo ./
  1408  			RUN sh -c "[ $(cat /test1/foo) = 'hello' ]"
  1409  			COPY foo /test3/
  1410  			RUN sh -c "[ $(cat /test3/foo) = 'hello' ]"
  1411  			WORKDIR /test4
  1412  			COPY . .
  1413  			RUN sh -c "[ $(cat /test4/foo) = 'hello' ]"
  1414  			WORKDIR /test5/test6
  1415  			COPY foo ../
  1416  			RUN sh -c "[ $(cat /test5/foo) = 'hello' ]"
  1417  			`),
  1418  		withFile("foo", "hello"),
  1419  	))
  1420  }
  1421  
  1422  func (s *DockerSuite) TestBuildBlankName(c *check.C) {
  1423  	name := "testbuildblankname"
  1424  	testCases := []struct {
  1425  		expression     string
  1426  		expectedStderr string
  1427  	}{
  1428  		{
  1429  			expression:     "ENV =",
  1430  			expectedStderr: "ENV names can not be blank",
  1431  		},
  1432  		{
  1433  			expression:     "LABEL =",
  1434  			expectedStderr: "LABEL names can not be blank",
  1435  		},
  1436  		{
  1437  			expression:     "ARG =foo",
  1438  			expectedStderr: "ARG names can not be blank",
  1439  		},
  1440  	}
  1441  
  1442  	for _, tc := range testCases {
  1443  		buildImage(name, withDockerfile(fmt.Sprintf(`FROM busybox
  1444  		%s`, tc.expression))).Assert(c, icmd.Expected{
  1445  			ExitCode: 1,
  1446  			Err:      tc.expectedStderr,
  1447  		})
  1448  	}
  1449  }
  1450  
  1451  func (s *DockerSuite) TestBuildEnv(c *check.C) {
  1452  	testRequires(c, DaemonIsLinux) // ENV expansion is different in Windows
  1453  	name := "testbuildenv"
  1454  	expected := "[PATH=/test:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PORT=2375]"
  1455  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  1456  		ENV PATH /test:$PATH
  1457  		ENV PORT 2375
  1458  		RUN [ $(env | grep PORT) = 'PORT=2375' ]`))
  1459  	res := inspectField(c, name, "Config.Env")
  1460  	if res != expected {
  1461  		c.Fatalf("Env %s, expected %s", res, expected)
  1462  	}
  1463  }
  1464  
  1465  func (s *DockerSuite) TestBuildPATH(c *check.C) {
  1466  	testRequires(c, DaemonIsLinux) // ENV expansion is different in Windows
  1467  
  1468  	defPath := "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
  1469  
  1470  	fn := func(dockerfile string, expected string) {
  1471  		buildImageSuccessfully(c, "testbldpath", withDockerfile(dockerfile))
  1472  		res := inspectField(c, "testbldpath", "Config.Env")
  1473  		if res != expected {
  1474  			c.Fatalf("Env %q, expected %q for dockerfile:%q", res, expected, dockerfile)
  1475  		}
  1476  	}
  1477  
  1478  	tests := []struct{ dockerfile, exp string }{
  1479  		{"FROM scratch\nMAINTAINER me", "[PATH=" + defPath + "]"},
  1480  		{"FROM busybox\nMAINTAINER me", "[PATH=" + defPath + "]"},
  1481  		{"FROM scratch\nENV FOO=bar", "[PATH=" + defPath + " FOO=bar]"},
  1482  		{"FROM busybox\nENV FOO=bar", "[PATH=" + defPath + " FOO=bar]"},
  1483  		{"FROM scratch\nENV PATH=/test", "[PATH=/test]"},
  1484  		{"FROM busybox\nENV PATH=/test", "[PATH=/test]"},
  1485  		{"FROM scratch\nENV PATH=''", "[PATH=]"},
  1486  		{"FROM busybox\nENV PATH=''", "[PATH=]"},
  1487  	}
  1488  
  1489  	for _, test := range tests {
  1490  		fn(test.dockerfile, test.exp)
  1491  	}
  1492  }
  1493  
  1494  func (s *DockerSuite) TestBuildContextCleanup(c *check.C) {
  1495  	testRequires(c, SameHostDaemon)
  1496  
  1497  	name := "testbuildcontextcleanup"
  1498  	entries, err := ioutil.ReadDir(filepath.Join(testEnv.DockerBasePath(), "tmp"))
  1499  	if err != nil {
  1500  		c.Fatalf("failed to list contents of tmp dir: %s", err)
  1501  	}
  1502  
  1503  	buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+`
  1504          ENTRYPOINT ["/bin/echo"]`))
  1505  
  1506  	entriesFinal, err := ioutil.ReadDir(filepath.Join(testEnv.DockerBasePath(), "tmp"))
  1507  	if err != nil {
  1508  		c.Fatalf("failed to list contents of tmp dir: %s", err)
  1509  	}
  1510  	if err = testutil.CompareDirectoryEntries(entries, entriesFinal); err != nil {
  1511  		c.Fatalf("context should have been deleted, but wasn't")
  1512  	}
  1513  
  1514  }
  1515  
  1516  func (s *DockerSuite) TestBuildContextCleanupFailedBuild(c *check.C) {
  1517  	testRequires(c, SameHostDaemon)
  1518  
  1519  	name := "testbuildcontextcleanup"
  1520  	entries, err := ioutil.ReadDir(filepath.Join(testEnv.DockerBasePath(), "tmp"))
  1521  	if err != nil {
  1522  		c.Fatalf("failed to list contents of tmp dir: %s", err)
  1523  	}
  1524  
  1525  	buildImage(name, withDockerfile(`FROM `+minimalBaseImage()+`
  1526  	RUN /non/existing/command`)).Assert(c, icmd.Expected{
  1527  		ExitCode: 1,
  1528  	})
  1529  
  1530  	entriesFinal, err := ioutil.ReadDir(filepath.Join(testEnv.DockerBasePath(), "tmp"))
  1531  	if err != nil {
  1532  		c.Fatalf("failed to list contents of tmp dir: %s", err)
  1533  	}
  1534  	if err = testutil.CompareDirectoryEntries(entries, entriesFinal); err != nil {
  1535  		c.Fatalf("context should have been deleted, but wasn't")
  1536  	}
  1537  
  1538  }
  1539  
  1540  func (s *DockerSuite) TestBuildCmd(c *check.C) {
  1541  	name := "testbuildcmd"
  1542  	expected := "[/bin/echo Hello World]"
  1543  
  1544  	buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+`
  1545          CMD ["/bin/echo", "Hello World"]`))
  1546  
  1547  	res := inspectField(c, name, "Config.Cmd")
  1548  	if res != expected {
  1549  		c.Fatalf("Cmd %s, expected %s", res, expected)
  1550  	}
  1551  }
  1552  
  1553  func (s *DockerSuite) TestBuildExpose(c *check.C) {
  1554  	testRequires(c, DaemonIsLinux) // Expose not implemented on Windows
  1555  	name := "testbuildexpose"
  1556  	expected := "map[2375/tcp:{}]"
  1557  
  1558  	buildImageSuccessfully(c, name, withDockerfile(`FROM scratch
  1559          EXPOSE 2375`))
  1560  
  1561  	res := inspectField(c, name, "Config.ExposedPorts")
  1562  	if res != expected {
  1563  		c.Fatalf("Exposed ports %s, expected %s", res, expected)
  1564  	}
  1565  }
  1566  
  1567  func (s *DockerSuite) TestBuildExposeMorePorts(c *check.C) {
  1568  	testRequires(c, DaemonIsLinux) // Expose not implemented on Windows
  1569  	// start building docker file with a large number of ports
  1570  	portList := make([]string, 50)
  1571  	line := make([]string, 100)
  1572  	expectedPorts := make([]int, len(portList)*len(line))
  1573  	for i := 0; i < len(portList); i++ {
  1574  		for j := 0; j < len(line); j++ {
  1575  			p := i*len(line) + j + 1
  1576  			line[j] = strconv.Itoa(p)
  1577  			expectedPorts[p-1] = p
  1578  		}
  1579  		if i == len(portList)-1 {
  1580  			portList[i] = strings.Join(line, " ")
  1581  		} else {
  1582  			portList[i] = strings.Join(line, " ") + ` \`
  1583  		}
  1584  	}
  1585  
  1586  	dockerfile := `FROM scratch
  1587  	EXPOSE {{range .}} {{.}}
  1588  	{{end}}`
  1589  	tmpl := template.Must(template.New("dockerfile").Parse(dockerfile))
  1590  	buf := bytes.NewBuffer(nil)
  1591  	tmpl.Execute(buf, portList)
  1592  
  1593  	name := "testbuildexpose"
  1594  	buildImageSuccessfully(c, name, withDockerfile(buf.String()))
  1595  
  1596  	// check if all the ports are saved inside Config.ExposedPorts
  1597  	res := inspectFieldJSON(c, name, "Config.ExposedPorts")
  1598  	var exposedPorts map[string]interface{}
  1599  	if err := json.Unmarshal([]byte(res), &exposedPorts); err != nil {
  1600  		c.Fatal(err)
  1601  	}
  1602  
  1603  	for _, p := range expectedPorts {
  1604  		ep := fmt.Sprintf("%d/tcp", p)
  1605  		if _, ok := exposedPorts[ep]; !ok {
  1606  			c.Errorf("Port(%s) is not exposed", ep)
  1607  		} else {
  1608  			delete(exposedPorts, ep)
  1609  		}
  1610  	}
  1611  	if len(exposedPorts) != 0 {
  1612  		c.Errorf("Unexpected extra exposed ports %v", exposedPorts)
  1613  	}
  1614  }
  1615  
  1616  func (s *DockerSuite) TestBuildExposeOrder(c *check.C) {
  1617  	testRequires(c, DaemonIsLinux) // Expose not implemented on Windows
  1618  	buildID := func(name, exposed string) string {
  1619  		buildImageSuccessfully(c, name, withDockerfile(fmt.Sprintf(`FROM scratch
  1620  		EXPOSE %s`, exposed)))
  1621  		id := inspectField(c, name, "Id")
  1622  		return id
  1623  	}
  1624  
  1625  	id1 := buildID("testbuildexpose1", "80 2375")
  1626  	id2 := buildID("testbuildexpose2", "2375 80")
  1627  	if id1 != id2 {
  1628  		c.Errorf("EXPOSE should invalidate the cache only when ports actually changed")
  1629  	}
  1630  }
  1631  
  1632  func (s *DockerSuite) TestBuildExposeUpperCaseProto(c *check.C) {
  1633  	testRequires(c, DaemonIsLinux) // Expose not implemented on Windows
  1634  	name := "testbuildexposeuppercaseproto"
  1635  	expected := "map[5678/udp:{}]"
  1636  	buildImageSuccessfully(c, name, withDockerfile(`FROM scratch
  1637          EXPOSE 5678/UDP`))
  1638  	res := inspectField(c, name, "Config.ExposedPorts")
  1639  	if res != expected {
  1640  		c.Fatalf("Exposed ports %s, expected %s", res, expected)
  1641  	}
  1642  }
  1643  
  1644  func (s *DockerSuite) TestBuildEmptyEntrypointInheritance(c *check.C) {
  1645  	name := "testbuildentrypointinheritance"
  1646  	name2 := "testbuildentrypointinheritance2"
  1647  
  1648  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  1649          ENTRYPOINT ["/bin/echo"]`))
  1650  	res := inspectField(c, name, "Config.Entrypoint")
  1651  
  1652  	expected := "[/bin/echo]"
  1653  	if res != expected {
  1654  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  1655  	}
  1656  
  1657  	buildImageSuccessfully(c, name2, withDockerfile(fmt.Sprintf(`FROM %s
  1658          ENTRYPOINT []`, name)))
  1659  	res = inspectField(c, name2, "Config.Entrypoint")
  1660  
  1661  	expected = "[]"
  1662  	if res != expected {
  1663  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  1664  	}
  1665  }
  1666  
  1667  func (s *DockerSuite) TestBuildEmptyEntrypoint(c *check.C) {
  1668  	name := "testbuildentrypoint"
  1669  	expected := "[]"
  1670  
  1671  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  1672          ENTRYPOINT []`))
  1673  
  1674  	res := inspectField(c, name, "Config.Entrypoint")
  1675  	if res != expected {
  1676  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  1677  	}
  1678  
  1679  }
  1680  
  1681  func (s *DockerSuite) TestBuildEntrypoint(c *check.C) {
  1682  	name := "testbuildentrypoint"
  1683  
  1684  	expected := "[/bin/echo]"
  1685  	buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+`
  1686          ENTRYPOINT ["/bin/echo"]`))
  1687  
  1688  	res := inspectField(c, name, "Config.Entrypoint")
  1689  	if res != expected {
  1690  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  1691  	}
  1692  
  1693  }
  1694  
  1695  // #6445 ensure ONBUILD triggers aren't committed to grandchildren
  1696  func (s *DockerSuite) TestBuildOnBuildLimitedInheritence(c *check.C) {
  1697  	buildImageSuccessfully(c, "testonbuildtrigger1", withDockerfile(`
  1698  		FROM busybox
  1699  		RUN echo "GRANDPARENT"
  1700  		ONBUILD RUN echo "ONBUILD PARENT"
  1701  		`))
  1702  	// ONBUILD should be run in second build.
  1703  	buildImage("testonbuildtrigger2", withDockerfile("FROM testonbuildtrigger1")).Assert(c, icmd.Expected{
  1704  		Out: "ONBUILD PARENT",
  1705  	})
  1706  	// ONBUILD should *not* be run in third build.
  1707  	result := buildImage("testonbuildtrigger3", withDockerfile("FROM testonbuildtrigger2"))
  1708  	result.Assert(c, icmd.Success)
  1709  	if strings.Contains(result.Combined(), "ONBUILD PARENT") {
  1710  		c.Fatalf("ONBUILD instruction ran in grandchild of ONBUILD parent")
  1711  	}
  1712  }
  1713  
  1714  func (s *DockerSuite) TestBuildSameDockerfileWithAndWithoutCache(c *check.C) {
  1715  	testRequires(c, DaemonIsLinux) // Expose not implemented on Windows
  1716  	name := "testbuildwithcache"
  1717  	dockerfile := `FROM scratch
  1718  		MAINTAINER dockerio
  1719  		EXPOSE 5432
  1720          ENTRYPOINT ["/bin/echo"]`
  1721  	buildImageSuccessfully(c, name, withDockerfile(dockerfile))
  1722  	id1 := getIDByName(c, name)
  1723  	buildImageSuccessfully(c, name, withDockerfile(dockerfile))
  1724  	id2 := getIDByName(c, name)
  1725  	buildImageSuccessfully(c, name, withoutCache, withDockerfile(dockerfile))
  1726  	id3 := getIDByName(c, name)
  1727  	if id1 != id2 {
  1728  		c.Fatal("The cache should have been used but hasn't.")
  1729  	}
  1730  	if id1 == id3 {
  1731  		c.Fatal("The cache should have been invalided but hasn't.")
  1732  	}
  1733  }
  1734  
  1735  // Make sure that ADD/COPY still populate the cache even if they don't use it
  1736  func (s *DockerSuite) TestBuildConditionalCache(c *check.C) {
  1737  	name := "testbuildconditionalcache"
  1738  
  1739  	dockerfile := `
  1740  		FROM busybox
  1741          ADD foo /tmp/`
  1742  	ctx := fakeContext(c, dockerfile, map[string]string{
  1743  		"foo": "hello",
  1744  	})
  1745  	defer ctx.Close()
  1746  
  1747  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  1748  	id1 := getIDByName(c, name)
  1749  
  1750  	if err := ctx.Add("foo", "bye"); err != nil {
  1751  		c.Fatalf("Error modifying foo: %s", err)
  1752  	}
  1753  
  1754  	// Updating a file should invalidate the cache
  1755  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  1756  	id2 := getIDByName(c, name)
  1757  	if id2 == id1 {
  1758  		c.Fatal("Should not have used the cache")
  1759  	}
  1760  
  1761  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  1762  	id3 := getIDByName(c, name)
  1763  	if id3 != id2 {
  1764  		c.Fatal("Should have used the cache")
  1765  	}
  1766  }
  1767  
  1768  // FIXME(vdemeester) this really seems to test the same thing as before
  1769  func (s *DockerSuite) TestBuildAddMultipleLocalFileWithAndWithoutCache(c *check.C) {
  1770  	name := "testbuildaddmultiplelocalfilewithcache"
  1771  	dockerfile := `
  1772  		FROM busybox
  1773          MAINTAINER dockerio
  1774          ADD foo Dockerfile /usr/lib/bla/
  1775  		RUN sh -c "[ $(cat /usr/lib/bla/foo) = "hello" ]"`
  1776  	ctx := fakeContext(c, dockerfile, map[string]string{
  1777  		"foo": "hello",
  1778  	})
  1779  	defer ctx.Close()
  1780  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  1781  	id1 := getIDByName(c, name)
  1782  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  1783  	id2 := getIDByName(c, name)
  1784  	buildImageSuccessfully(c, name, withoutCache, withExternalBuildContext(ctx))
  1785  	id3 := getIDByName(c, name)
  1786  	if id1 != id2 {
  1787  		c.Fatal("The cache should have been used but hasn't.")
  1788  	}
  1789  	if id1 == id3 {
  1790  		c.Fatal("The cache should have been invalided but hasn't.")
  1791  	}
  1792  }
  1793  
  1794  func (s *DockerSuite) TestBuildCopyDirButNotFile(c *check.C) {
  1795  	name := "testbuildcopydirbutnotfile"
  1796  	name2 := "testbuildcopydirbutnotfile2"
  1797  
  1798  	dockerfile := `
  1799          FROM ` + minimalBaseImage() + `
  1800          COPY dir /tmp/`
  1801  	ctx := fakeContext(c, dockerfile, map[string]string{
  1802  		"dir/foo": "hello",
  1803  	})
  1804  	defer ctx.Close()
  1805  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  1806  	id1 := getIDByName(c, name)
  1807  	// Check that adding file with similar name doesn't mess with cache
  1808  	if err := ctx.Add("dir_file", "hello2"); err != nil {
  1809  		c.Fatal(err)
  1810  	}
  1811  	buildImageSuccessfully(c, name2, withExternalBuildContext(ctx))
  1812  	id2 := getIDByName(c, name2)
  1813  	if id1 != id2 {
  1814  		c.Fatal("The cache should have been used but wasn't")
  1815  	}
  1816  }
  1817  
  1818  func (s *DockerSuite) TestBuildAddCurrentDirWithCache(c *check.C) {
  1819  	name := "testbuildaddcurrentdirwithcache"
  1820  	name2 := name + "2"
  1821  	name3 := name + "3"
  1822  	name4 := name + "4"
  1823  	dockerfile := `
  1824          FROM ` + minimalBaseImage() + `
  1825          MAINTAINER dockerio
  1826          ADD . /usr/lib/bla`
  1827  	ctx := fakeContext(c, dockerfile, map[string]string{
  1828  		"foo": "hello",
  1829  	})
  1830  	defer ctx.Close()
  1831  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  1832  	id1 := getIDByName(c, name)
  1833  	// Check that adding file invalidate cache of "ADD ."
  1834  	if err := ctx.Add("bar", "hello2"); err != nil {
  1835  		c.Fatal(err)
  1836  	}
  1837  	buildImageSuccessfully(c, name2, withExternalBuildContext(ctx))
  1838  	id2 := getIDByName(c, name2)
  1839  	if id1 == id2 {
  1840  		c.Fatal("The cache should have been invalided but hasn't.")
  1841  	}
  1842  	// Check that changing file invalidate cache of "ADD ."
  1843  	if err := ctx.Add("foo", "hello1"); err != nil {
  1844  		c.Fatal(err)
  1845  	}
  1846  	buildImageSuccessfully(c, name3, withExternalBuildContext(ctx))
  1847  	id3 := getIDByName(c, name3)
  1848  	if id2 == id3 {
  1849  		c.Fatal("The cache should have been invalided but hasn't.")
  1850  	}
  1851  	// Check that changing file to same content with different mtime does not
  1852  	// invalidate cache of "ADD ."
  1853  	time.Sleep(1 * time.Second) // wait second because of mtime precision
  1854  	if err := ctx.Add("foo", "hello1"); err != nil {
  1855  		c.Fatal(err)
  1856  	}
  1857  	buildImageSuccessfully(c, name4, withExternalBuildContext(ctx))
  1858  	id4 := getIDByName(c, name4)
  1859  	if id3 != id4 {
  1860  		c.Fatal("The cache should have been used but hasn't.")
  1861  	}
  1862  }
  1863  
  1864  // FIXME(vdemeester) this really seems to test the same thing as before (TestBuildAddMultipleLocalFileWithAndWithoutCache)
  1865  func (s *DockerSuite) TestBuildAddCurrentDirWithoutCache(c *check.C) {
  1866  	name := "testbuildaddcurrentdirwithoutcache"
  1867  	dockerfile := `
  1868          FROM ` + minimalBaseImage() + `
  1869          MAINTAINER dockerio
  1870          ADD . /usr/lib/bla`
  1871  	ctx := fakeContext(c, dockerfile, map[string]string{
  1872  		"foo": "hello",
  1873  	})
  1874  	defer ctx.Close()
  1875  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  1876  	id1 := getIDByName(c, name)
  1877  	buildImageSuccessfully(c, name, withoutCache, withExternalBuildContext(ctx))
  1878  	id2 := getIDByName(c, name)
  1879  	if id1 == id2 {
  1880  		c.Fatal("The cache should have been invalided but hasn't.")
  1881  	}
  1882  }
  1883  
  1884  func (s *DockerSuite) TestBuildAddRemoteFileWithAndWithoutCache(c *check.C) {
  1885  	name := "testbuildaddremotefilewithcache"
  1886  	server := fakeStorage(c, map[string]string{
  1887  		"baz": "hello",
  1888  	})
  1889  	defer server.Close()
  1890  
  1891  	dockerfile := fmt.Sprintf(`FROM `+minimalBaseImage()+`
  1892          MAINTAINER dockerio
  1893          ADD %s/baz /usr/lib/baz/quux`, server.URL())
  1894  	buildImageSuccessfully(c, name, withDockerfile(dockerfile))
  1895  	id1 := getIDByName(c, name)
  1896  	buildImageSuccessfully(c, name, withDockerfile(dockerfile))
  1897  	id2 := getIDByName(c, name)
  1898  	buildImageSuccessfully(c, name, withoutCache, withDockerfile(dockerfile))
  1899  	id3 := getIDByName(c, name)
  1900  
  1901  	if id1 != id2 {
  1902  		c.Fatal("The cache should have been used but hasn't.")
  1903  	}
  1904  	if id1 == id3 {
  1905  		c.Fatal("The cache should have been invalided but hasn't.")
  1906  	}
  1907  }
  1908  
  1909  func (s *DockerSuite) TestBuildAddRemoteFileMTime(c *check.C) {
  1910  	name := "testbuildaddremotefilemtime"
  1911  	name2 := name + "2"
  1912  	name3 := name + "3"
  1913  
  1914  	files := map[string]string{"baz": "hello"}
  1915  	server := fakeStorage(c, files)
  1916  	defer server.Close()
  1917  
  1918  	ctx := fakeContext(c, fmt.Sprintf(`FROM `+minimalBaseImage()+`
  1919          MAINTAINER dockerio
  1920          ADD %s/baz /usr/lib/baz/quux`, server.URL()), nil)
  1921  	defer ctx.Close()
  1922  
  1923  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  1924  	id1 := getIDByName(c, name)
  1925  	buildImageSuccessfully(c, name2, withExternalBuildContext(ctx))
  1926  	id2 := getIDByName(c, name2)
  1927  	if id1 != id2 {
  1928  		c.Fatal("The cache should have been used but wasn't - #1")
  1929  	}
  1930  
  1931  	// Now create a different server with same contents (causes different mtime)
  1932  	// The cache should still be used
  1933  
  1934  	// allow some time for clock to pass as mtime precision is only 1s
  1935  	time.Sleep(2 * time.Second)
  1936  
  1937  	server2 := fakeStorage(c, files)
  1938  	defer server2.Close()
  1939  
  1940  	ctx2 := fakeContext(c, fmt.Sprintf(`FROM `+minimalBaseImage()+`
  1941          MAINTAINER dockerio
  1942          ADD %s/baz /usr/lib/baz/quux`, server2.URL()), nil)
  1943  	defer ctx2.Close()
  1944  	buildImageSuccessfully(c, name3, withExternalBuildContext(ctx2))
  1945  	id3 := getIDByName(c, name3)
  1946  	if id1 != id3 {
  1947  		c.Fatal("The cache should have been used but wasn't")
  1948  	}
  1949  }
  1950  
  1951  // FIXME(vdemeester) this really seems to test the same thing as before (combined)
  1952  func (s *DockerSuite) TestBuildAddLocalAndRemoteFilesWithAndWithoutCache(c *check.C) {
  1953  	name := "testbuildaddlocalandremotefilewithcache"
  1954  	server := fakeStorage(c, map[string]string{
  1955  		"baz": "hello",
  1956  	})
  1957  	defer server.Close()
  1958  
  1959  	ctx := fakeContext(c, fmt.Sprintf(`FROM `+minimalBaseImage()+`
  1960          MAINTAINER dockerio
  1961          ADD foo /usr/lib/bla/bar
  1962          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  1963  		map[string]string{
  1964  			"foo": "hello world",
  1965  		})
  1966  	defer ctx.Close()
  1967  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  1968  	id1 := getIDByName(c, name)
  1969  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  1970  	id2 := getIDByName(c, name)
  1971  	buildImageSuccessfully(c, name, withoutCache, withExternalBuildContext(ctx))
  1972  	id3 := getIDByName(c, name)
  1973  	if id1 != id2 {
  1974  		c.Fatal("The cache should have been used but hasn't.")
  1975  	}
  1976  	if id1 == id3 {
  1977  		c.Fatal("The cache should have been invalidated but hasn't.")
  1978  	}
  1979  }
  1980  
  1981  func testContextTar(c *check.C, compression archive.Compression) {
  1982  	ctx := fakeContext(c,
  1983  		`FROM busybox
  1984  ADD foo /foo
  1985  CMD ["cat", "/foo"]`,
  1986  		map[string]string{
  1987  			"foo": "bar",
  1988  		},
  1989  	)
  1990  	defer ctx.Close()
  1991  	context, err := archive.Tar(ctx.Dir, compression)
  1992  	if err != nil {
  1993  		c.Fatalf("failed to build context tar: %v", err)
  1994  	}
  1995  	name := "contexttar"
  1996  
  1997  	icmd.RunCmd(icmd.Cmd{
  1998  		Command: []string{dockerBinary, "build", "-t", name, "-"},
  1999  		Stdin:   context,
  2000  	}).Assert(c, icmd.Success)
  2001  }
  2002  
  2003  func (s *DockerSuite) TestBuildContextTarGzip(c *check.C) {
  2004  	testContextTar(c, archive.Gzip)
  2005  }
  2006  
  2007  func (s *DockerSuite) TestBuildContextTarNoCompression(c *check.C) {
  2008  	testContextTar(c, archive.Uncompressed)
  2009  }
  2010  
  2011  func (s *DockerSuite) TestBuildNoContext(c *check.C) {
  2012  	name := "nocontext"
  2013  	icmd.RunCmd(icmd.Cmd{
  2014  		Command: []string{dockerBinary, "build", "-t", name, "-"},
  2015  		Stdin: strings.NewReader(
  2016  			`FROM busybox
  2017  			CMD ["echo", "ok"]`),
  2018  	}).Assert(c, icmd.Success)
  2019  
  2020  	if out, _ := dockerCmd(c, "run", "--rm", "nocontext"); out != "ok\n" {
  2021  		c.Fatalf("run produced invalid output: %q, expected %q", out, "ok")
  2022  	}
  2023  }
  2024  
  2025  func (s *DockerSuite) TestBuildWithVolumeOwnership(c *check.C) {
  2026  	testRequires(c, DaemonIsLinux)
  2027  	name := "testbuildimg"
  2028  
  2029  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox:latest
  2030          RUN mkdir /test && chown daemon:daemon /test && chmod 0600 /test
  2031          VOLUME /test`))
  2032  
  2033  	out, _ := dockerCmd(c, "run", "--rm", "testbuildimg", "ls", "-la", "/test")
  2034  	if expected := "drw-------"; !strings.Contains(out, expected) {
  2035  		c.Fatalf("expected %s received %s", expected, out)
  2036  	}
  2037  	if expected := "daemon   daemon"; !strings.Contains(out, expected) {
  2038  		c.Fatalf("expected %s received %s", expected, out)
  2039  	}
  2040  
  2041  }
  2042  
  2043  // testing #1405 - config.Cmd does not get cleaned up if
  2044  // utilizing cache
  2045  func (s *DockerSuite) TestBuildEntrypointRunCleanup(c *check.C) {
  2046  	name := "testbuildcmdcleanup"
  2047  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  2048          RUN echo "hello"`))
  2049  
  2050  	buildImageSuccessfully(c, name, withBuildContext(c,
  2051  		withFile("Dockerfile", `FROM busybox
  2052          RUN echo "hello"
  2053          ADD foo /foo
  2054          ENTRYPOINT ["/bin/echo"]`),
  2055  		withFile("foo", "hello")))
  2056  
  2057  	res := inspectField(c, name, "Config.Cmd")
  2058  	// Cmd must be cleaned up
  2059  	if res != "[]" {
  2060  		c.Fatalf("Cmd %s, expected nil", res)
  2061  	}
  2062  }
  2063  
  2064  func (s *DockerSuite) TestBuildAddFileNotFound(c *check.C) {
  2065  	name := "testbuildaddnotfound"
  2066  	expected := "foo: no such file or directory"
  2067  
  2068  	if testEnv.DaemonPlatform() == "windows" {
  2069  		expected = "foo: The system cannot find the file specified"
  2070  	}
  2071  
  2072  	buildImage(name, withBuildContext(c,
  2073  		withFile("Dockerfile", `FROM `+minimalBaseImage()+`
  2074          ADD foo /usr/local/bar`),
  2075  		withFile("bar", "hello"))).Assert(c, icmd.Expected{
  2076  		ExitCode: 1,
  2077  		Err:      expected,
  2078  	})
  2079  }
  2080  
  2081  func (s *DockerSuite) TestBuildInheritance(c *check.C) {
  2082  	testRequires(c, DaemonIsLinux)
  2083  	name := "testbuildinheritance"
  2084  
  2085  	buildImageSuccessfully(c, name, withDockerfile(`FROM scratch
  2086  		EXPOSE 2375`))
  2087  	ports1 := inspectField(c, name, "Config.ExposedPorts")
  2088  
  2089  	buildImageSuccessfully(c, name, withDockerfile(fmt.Sprintf(`FROM %s
  2090  		ENTRYPOINT ["/bin/echo"]`, name)))
  2091  
  2092  	res := inspectField(c, name, "Config.Entrypoint")
  2093  	if expected := "[/bin/echo]"; res != expected {
  2094  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  2095  	}
  2096  	ports2 := inspectField(c, name, "Config.ExposedPorts")
  2097  	if ports1 != ports2 {
  2098  		c.Fatalf("Ports must be same: %s != %s", ports1, ports2)
  2099  	}
  2100  }
  2101  
  2102  func (s *DockerSuite) TestBuildFails(c *check.C) {
  2103  	name := "testbuildfails"
  2104  	buildImage(name, withDockerfile(`FROM busybox
  2105  		RUN sh -c "exit 23"`)).Assert(c, icmd.Expected{
  2106  		ExitCode: 23,
  2107  		Err:      "returned a non-zero code: 23",
  2108  	})
  2109  }
  2110  
  2111  func (s *DockerSuite) TestBuildOnBuild(c *check.C) {
  2112  	name := "testbuildonbuild"
  2113  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  2114  		ONBUILD RUN touch foobar`))
  2115  	buildImageSuccessfully(c, name, withDockerfile(fmt.Sprintf(`FROM %s
  2116  		RUN [ -f foobar ]`, name)))
  2117  }
  2118  
  2119  // gh #2446
  2120  func (s *DockerSuite) TestBuildAddToSymlinkDest(c *check.C) {
  2121  	makeLink := `ln -s /foo /bar`
  2122  	if testEnv.DaemonPlatform() == "windows" {
  2123  		makeLink = `mklink /D C:\bar C:\foo`
  2124  	}
  2125  	name := "testbuildaddtosymlinkdest"
  2126  	buildImageSuccessfully(c, name, withBuildContext(c,
  2127  		withFile("Dockerfile", `
  2128  		FROM busybox
  2129  		RUN sh -c "mkdir /foo"
  2130  		RUN `+makeLink+`
  2131  		ADD foo /bar/
  2132  		RUN sh -c "[ -f /bar/foo ]"
  2133  		RUN sh -c "[ -f /foo/foo ]"`),
  2134  		withFile("foo", "hello"),
  2135  	))
  2136  }
  2137  
  2138  func (s *DockerSuite) TestBuildEscapeWhitespace(c *check.C) {
  2139  	name := "testbuildescapewhitespace"
  2140  
  2141  	buildImageSuccessfully(c, name, withDockerfile(`
  2142    # ESCAPE=\
  2143    FROM busybox
  2144    MAINTAINER "Docker \
  2145  IO <io@\
  2146  docker.com>"
  2147    `))
  2148  
  2149  	res := inspectField(c, name, "Author")
  2150  	if res != "\"Docker IO <io@docker.com>\"" {
  2151  		c.Fatalf("Parsed string did not match the escaped string. Got: %q", res)
  2152  	}
  2153  
  2154  }
  2155  
  2156  func (s *DockerSuite) TestBuildVerifyIntString(c *check.C) {
  2157  	// Verify that strings that look like ints are still passed as strings
  2158  	name := "testbuildstringing"
  2159  
  2160  	buildImageSuccessfully(c, name, withDockerfile(`
  2161  	FROM busybox
  2162  	MAINTAINER 123`))
  2163  
  2164  	out, _ := dockerCmd(c, "inspect", name)
  2165  	if !strings.Contains(out, "\"123\"") {
  2166  		c.Fatalf("Output does not contain the int as a string:\n%s", out)
  2167  	}
  2168  
  2169  }
  2170  
  2171  func (s *DockerSuite) TestBuildDockerignore(c *check.C) {
  2172  	name := "testbuilddockerignore"
  2173  	buildImageSuccessfully(c, name, withBuildContext(c,
  2174  		withFile("Dockerfile", `
  2175  		FROM busybox
  2176  		 ADD . /bla
  2177  		RUN sh -c "[[ -f /bla/src/x.go ]]"
  2178  		RUN sh -c "[[ -f /bla/Makefile ]]"
  2179  		RUN sh -c "[[ ! -e /bla/src/_vendor ]]"
  2180  		RUN sh -c "[[ ! -e /bla/.gitignore ]]"
  2181  		RUN sh -c "[[ ! -e /bla/README.md ]]"
  2182  		RUN sh -c "[[ ! -e /bla/dir/foo ]]"
  2183  		RUN sh -c "[[ ! -e /bla/foo ]]"
  2184  		RUN sh -c "[[ ! -e /bla/.git ]]"
  2185  		RUN sh -c "[[ ! -e v.cc ]]"
  2186  		RUN sh -c "[[ ! -e src/v.cc ]]"
  2187  		RUN sh -c "[[ ! -e src/_vendor/v.cc ]]"`),
  2188  		withFile("Makefile", "all:"),
  2189  		withFile(".git/HEAD", "ref: foo"),
  2190  		withFile("src/x.go", "package main"),
  2191  		withFile("src/_vendor/v.go", "package main"),
  2192  		withFile("src/_vendor/v.cc", "package main"),
  2193  		withFile("src/v.cc", "package main"),
  2194  		withFile("v.cc", "package main"),
  2195  		withFile("dir/foo", ""),
  2196  		withFile(".gitignore", ""),
  2197  		withFile("README.md", "readme"),
  2198  		withFile(".dockerignore", `
  2199  .git
  2200  pkg
  2201  .gitignore
  2202  src/_vendor
  2203  *.md
  2204  **/*.cc
  2205  dir`),
  2206  	))
  2207  }
  2208  
  2209  func (s *DockerSuite) TestBuildDockerignoreCleanPaths(c *check.C) {
  2210  	name := "testbuilddockerignorecleanpaths"
  2211  	buildImageSuccessfully(c, name, withBuildContext(c,
  2212  		withFile("Dockerfile", `
  2213          FROM busybox
  2214          ADD . /tmp/
  2215          RUN sh -c "(! ls /tmp/foo) && (! ls /tmp/foo2) && (! ls /tmp/dir1/foo)"`),
  2216  		withFile("foo", "foo"),
  2217  		withFile("foo2", "foo2"),
  2218  		withFile("dir1/foo", "foo in dir1"),
  2219  		withFile(".dockerignore", "./foo\ndir1//foo\n./dir1/../foo2"),
  2220  	))
  2221  }
  2222  
  2223  func (s *DockerSuite) TestBuildDockerignoreExceptions(c *check.C) {
  2224  	name := "testbuilddockerignoreexceptions"
  2225  	buildImageSuccessfully(c, name, withBuildContext(c,
  2226  		withFile("Dockerfile", `
  2227  		FROM busybox
  2228  		ADD . /bla
  2229  		RUN sh -c "[[ -f /bla/src/x.go ]]"
  2230  		RUN sh -c "[[ -f /bla/Makefile ]]"
  2231  		RUN sh -c "[[ ! -e /bla/src/_vendor ]]"
  2232  		RUN sh -c "[[ ! -e /bla/.gitignore ]]"
  2233  		RUN sh -c "[[ ! -e /bla/README.md ]]"
  2234  		RUN sh -c "[[  -e /bla/dir/dir/foo ]]"
  2235  		RUN sh -c "[[ ! -e /bla/dir/foo1 ]]"
  2236  		RUN sh -c "[[ -f /bla/dir/e ]]"
  2237  		RUN sh -c "[[ -f /bla/dir/e-dir/foo ]]"
  2238  		RUN sh -c "[[ ! -e /bla/foo ]]"
  2239  		RUN sh -c "[[ ! -e /bla/.git ]]"
  2240  		RUN sh -c "[[ -e /bla/dir/a.cc ]]"`),
  2241  		withFile("Makefile", "all:"),
  2242  		withFile(".git/HEAD", "ref: foo"),
  2243  		withFile("src/x.go", "package main"),
  2244  		withFile("src/_vendor/v.go", "package main"),
  2245  		withFile("dir/foo", ""),
  2246  		withFile("dir/foo1", ""),
  2247  		withFile("dir/dir/f1", ""),
  2248  		withFile("dir/dir/foo", ""),
  2249  		withFile("dir/e", ""),
  2250  		withFile("dir/e-dir/foo", ""),
  2251  		withFile(".gitignore", ""),
  2252  		withFile("README.md", "readme"),
  2253  		withFile("dir/a.cc", "hello"),
  2254  		withFile(".dockerignore", `
  2255  .git
  2256  pkg
  2257  .gitignore
  2258  src/_vendor
  2259  *.md
  2260  dir
  2261  !dir/e*
  2262  !dir/dir/foo
  2263  **/*.cc
  2264  !**/*.cc`),
  2265  	))
  2266  }
  2267  
  2268  func (s *DockerSuite) TestBuildDockerignoringDockerfile(c *check.C) {
  2269  	name := "testbuilddockerignoredockerfile"
  2270  	dockerfile := `
  2271  		FROM busybox
  2272  		ADD . /tmp/
  2273  		RUN sh -c "! ls /tmp/Dockerfile"
  2274  		RUN ls /tmp/.dockerignore`
  2275  	buildImageSuccessfully(c, name, withBuildContext(c,
  2276  		withFile("Dockerfile", dockerfile),
  2277  		withFile(".dockerignore", "Dockerfile\n"),
  2278  	))
  2279  	buildImageSuccessfully(c, name, withBuildContext(c,
  2280  		withFile("Dockerfile", dockerfile),
  2281  		withFile(".dockerignore", "./Dockerfile\n"),
  2282  	))
  2283  }
  2284  
  2285  func (s *DockerSuite) TestBuildDockerignoringRenamedDockerfile(c *check.C) {
  2286  	name := "testbuilddockerignoredockerfile"
  2287  	dockerfile := `
  2288  		FROM busybox
  2289  		ADD . /tmp/
  2290  		RUN ls /tmp/Dockerfile
  2291  		RUN sh -c "! ls /tmp/MyDockerfile"
  2292  		RUN ls /tmp/.dockerignore`
  2293  	buildImageSuccessfully(c, name, withBuildFlags("-f", "MyDockerfile"), withBuildContext(c,
  2294  		withFile("Dockerfile", "Should not use me"),
  2295  		withFile("MyDockerfile", dockerfile),
  2296  		withFile(".dockerignore", "MyDockerfile\n"),
  2297  	))
  2298  	buildImageSuccessfully(c, name, withBuildFlags("-f", "MyDockerfile"), withBuildContext(c,
  2299  		withFile("Dockerfile", "Should not use me"),
  2300  		withFile("MyDockerfile", dockerfile),
  2301  		withFile(".dockerignore", "./MyDockerfile\n"),
  2302  	))
  2303  }
  2304  
  2305  func (s *DockerSuite) TestBuildDockerignoringDockerignore(c *check.C) {
  2306  	name := "testbuilddockerignoredockerignore"
  2307  	dockerfile := `
  2308  		FROM busybox
  2309  		ADD . /tmp/
  2310  		RUN sh -c "! ls /tmp/.dockerignore"
  2311  		RUN ls /tmp/Dockerfile`
  2312  	buildImageSuccessfully(c, name, withBuildContext(c,
  2313  		withFile("Dockerfile", dockerfile),
  2314  		withFile(".dockerignore", ".dockerignore\n"),
  2315  	))
  2316  }
  2317  
  2318  func (s *DockerSuite) TestBuildDockerignoreTouchDockerfile(c *check.C) {
  2319  	name := "testbuilddockerignoretouchdockerfile"
  2320  	dockerfile := `
  2321          FROM busybox
  2322  		ADD . /tmp/`
  2323  	ctx := fakeContext(c, dockerfile, map[string]string{
  2324  		"Dockerfile":    dockerfile,
  2325  		".dockerignore": "Dockerfile\n",
  2326  	})
  2327  	defer ctx.Close()
  2328  
  2329  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  2330  	id1 := getIDByName(c, name)
  2331  
  2332  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  2333  	id2 := getIDByName(c, name)
  2334  	if id1 != id2 {
  2335  		c.Fatalf("Didn't use the cache - 1")
  2336  	}
  2337  
  2338  	// Now make sure touching Dockerfile doesn't invalidate the cache
  2339  	if err := ctx.Add("Dockerfile", dockerfile+"\n# hi"); err != nil {
  2340  		c.Fatalf("Didn't add Dockerfile: %s", err)
  2341  	}
  2342  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  2343  	id2 = getIDByName(c, name)
  2344  	if id1 != id2 {
  2345  		c.Fatalf("Didn't use the cache - 2")
  2346  	}
  2347  
  2348  	// One more time but just 'touch' it instead of changing the content
  2349  	if err := ctx.Add("Dockerfile", dockerfile+"\n# hi"); err != nil {
  2350  		c.Fatalf("Didn't add Dockerfile: %s", err)
  2351  	}
  2352  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  2353  	id2 = getIDByName(c, name)
  2354  	if id1 != id2 {
  2355  		c.Fatalf("Didn't use the cache - 3")
  2356  	}
  2357  }
  2358  
  2359  func (s *DockerSuite) TestBuildDockerignoringWholeDir(c *check.C) {
  2360  	name := "testbuilddockerignorewholedir"
  2361  
  2362  	dockerfile := `
  2363  		FROM busybox
  2364  		COPY . /
  2365  		RUN sh -c "[[ ! -e /.gitignore ]]"
  2366  		RUN sh -c "[[ ! -e /Makefile ]]"`
  2367  
  2368  	buildImageSuccessfully(c, name, withBuildContext(c,
  2369  		withFile("Dockerfile", dockerfile),
  2370  		withFile(".dockerignore", "*\n"),
  2371  		withFile("Makefile", "all:"),
  2372  		withFile(".gitignore", ""),
  2373  	))
  2374  }
  2375  
  2376  func (s *DockerSuite) TestBuildDockerignoringOnlyDotfiles(c *check.C) {
  2377  	name := "testbuilddockerignorewholedir"
  2378  
  2379  	dockerfile := `
  2380  		FROM busybox
  2381  		COPY . /
  2382  		RUN sh -c "[[ ! -e /.gitignore ]]"
  2383  		RUN sh -c "[[ -f /Makefile ]]"`
  2384  
  2385  	buildImageSuccessfully(c, name, withBuildContext(c,
  2386  		withFile("Dockerfile", dockerfile),
  2387  		withFile(".dockerignore", ".*"),
  2388  		withFile("Makefile", "all:"),
  2389  		withFile(".gitignore", ""),
  2390  	))
  2391  }
  2392  
  2393  func (s *DockerSuite) TestBuildDockerignoringBadExclusion(c *check.C) {
  2394  	name := "testbuilddockerignorebadexclusion"
  2395  	buildImage(name, withBuildContext(c,
  2396  		withFile("Dockerfile", `
  2397  		FROM busybox
  2398  		COPY . /
  2399  		RUN sh -c "[[ ! -e /.gitignore ]]"
  2400  		RUN sh -c "[[ -f /Makefile ]]"`),
  2401  		withFile("Makefile", "all:"),
  2402  		withFile(".gitignore", ""),
  2403  		withFile(".dockerignore", "!\n"),
  2404  	)).Assert(c, icmd.Expected{
  2405  		ExitCode: 1,
  2406  		Err:      "Error checking context: 'Illegal exclusion pattern: !",
  2407  	})
  2408  }
  2409  
  2410  func (s *DockerSuite) TestBuildDockerignoringWildTopDir(c *check.C) {
  2411  	dockerfile := `
  2412  		FROM busybox
  2413  		COPY . /
  2414  		RUN sh -c "[[ ! -e /.dockerignore ]]"
  2415  		RUN sh -c "[[ ! -e /Dockerfile ]]"
  2416  		RUN sh -c "[[ ! -e /file1 ]]"
  2417  		RUN sh -c "[[ ! -e /dir ]]"`
  2418  
  2419  	// All of these should result in ignoring all files
  2420  	for _, variant := range []string{"**", "**/", "**/**", "*"} {
  2421  		buildImageSuccessfully(c, "noname", withBuildContext(c,
  2422  			withFile("Dockerfile", dockerfile),
  2423  			withFile("file1", ""),
  2424  			withFile("dir/file1", ""),
  2425  			withFile(".dockerignore", variant),
  2426  		))
  2427  
  2428  		dockerCmd(c, "rmi", "noname")
  2429  	}
  2430  }
  2431  
  2432  func (s *DockerSuite) TestBuildDockerignoringWildDirs(c *check.C) {
  2433  	dockerfile := `
  2434          FROM busybox
  2435  		COPY . /
  2436  		#RUN sh -c "[[ -e /.dockerignore ]]"
  2437  		RUN sh -c "[[ -e /Dockerfile ]]           && \
  2438  		           [[ ! -e /file0 ]]              && \
  2439  		           [[ ! -e /dir1/file0 ]]         && \
  2440  		           [[ ! -e /dir2/file0 ]]         && \
  2441  		           [[ ! -e /file1 ]]              && \
  2442  		           [[ ! -e /dir1/file1 ]]         && \
  2443  		           [[ ! -e /dir1/dir2/file1 ]]    && \
  2444  		           [[ ! -e /dir1/file2 ]]         && \
  2445  		           [[   -e /dir1/dir2/file2 ]]    && \
  2446  		           [[ ! -e /dir1/dir2/file4 ]]    && \
  2447  		           [[ ! -e /dir1/dir2/file5 ]]    && \
  2448  		           [[ ! -e /dir1/dir2/file6 ]]    && \
  2449  		           [[ ! -e /dir1/dir3/file7 ]]    && \
  2450  		           [[ ! -e /dir1/dir3/file8 ]]    && \
  2451  		           [[   -e /dir1/dir3 ]]          && \
  2452  		           [[   -e /dir1/dir4 ]]          && \
  2453  		           [[ ! -e 'dir1/dir5/fileAA' ]]  && \
  2454  		           [[   -e 'dir1/dir5/fileAB' ]]  && \
  2455  		           [[   -e 'dir1/dir5/fileB' ]]"   # "." in pattern means nothing
  2456  
  2457  		RUN echo all done!`
  2458  
  2459  	dockerignore := `
  2460  **/file0
  2461  **/*file1
  2462  **/dir1/file2
  2463  dir1/**/file4
  2464  **/dir2/file5
  2465  **/dir1/dir2/file6
  2466  dir1/dir3/**
  2467  **/dir4/**
  2468  **/file?A
  2469  **/file\?B
  2470  **/dir5/file.
  2471  `
  2472  
  2473  	buildImageSuccessfully(c, "noname", withBuildContext(c,
  2474  		withFile("Dockerfile", dockerfile),
  2475  		withFile(".dockerignore", dockerignore),
  2476  		withFile("dir1/file0", ""),
  2477  		withFile("dir1/dir2/file0", ""),
  2478  		withFile("file1", ""),
  2479  		withFile("dir1/file1", ""),
  2480  		withFile("dir1/dir2/file1", ""),
  2481  		withFile("dir1/file2", ""),
  2482  		withFile("dir1/dir2/file2", ""), // remains
  2483  		withFile("dir1/dir2/file4", ""),
  2484  		withFile("dir1/dir2/file5", ""),
  2485  		withFile("dir1/dir2/file6", ""),
  2486  		withFile("dir1/dir3/file7", ""),
  2487  		withFile("dir1/dir3/file8", ""),
  2488  		withFile("dir1/dir4/file9", ""),
  2489  		withFile("dir1/dir5/fileAA", ""),
  2490  		withFile("dir1/dir5/fileAB", ""),
  2491  		withFile("dir1/dir5/fileB", ""),
  2492  	))
  2493  }
  2494  
  2495  func (s *DockerSuite) TestBuildLineBreak(c *check.C) {
  2496  	testRequires(c, DaemonIsLinux)
  2497  	name := "testbuildlinebreak"
  2498  	buildImageSuccessfully(c, name, withDockerfile(`FROM  busybox
  2499  RUN    sh -c 'echo root:testpass \
  2500  	> /tmp/passwd'
  2501  RUN    mkdir -p /var/run/sshd
  2502  RUN    sh -c "[ "$(cat /tmp/passwd)" = "root:testpass" ]"
  2503  RUN    sh -c "[ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]"`))
  2504  }
  2505  
  2506  func (s *DockerSuite) TestBuildEOLInLine(c *check.C) {
  2507  	testRequires(c, DaemonIsLinux)
  2508  	name := "testbuildeolinline"
  2509  	buildImageSuccessfully(c, name, withDockerfile(`FROM   busybox
  2510  RUN    sh -c 'echo root:testpass > /tmp/passwd'
  2511  RUN    echo "foo \n bar"; echo "baz"
  2512  RUN    mkdir -p /var/run/sshd
  2513  RUN    sh -c "[ "$(cat /tmp/passwd)" = "root:testpass" ]"
  2514  RUN    sh -c "[ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]"`))
  2515  }
  2516  
  2517  func (s *DockerSuite) TestBuildCommentsShebangs(c *check.C) {
  2518  	testRequires(c, DaemonIsLinux)
  2519  	name := "testbuildcomments"
  2520  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  2521  # This is an ordinary comment.
  2522  RUN { echo '#!/bin/sh'; echo 'echo hello world'; } > /hello.sh
  2523  RUN [ ! -x /hello.sh ]
  2524  # comment with line break \
  2525  RUN chmod +x /hello.sh
  2526  RUN [ -x /hello.sh ]
  2527  RUN [ "$(cat /hello.sh)" = $'#!/bin/sh\necho hello world' ]
  2528  RUN [ "$(/hello.sh)" = "hello world" ]`))
  2529  }
  2530  
  2531  func (s *DockerSuite) TestBuildUsersAndGroups(c *check.C) {
  2532  	testRequires(c, DaemonIsLinux)
  2533  	name := "testbuildusers"
  2534  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  2535  
  2536  # Make sure our defaults work
  2537  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)" = '0:0/root:root' ]
  2538  
  2539  # TODO decide if "args.user = strconv.Itoa(syscall.Getuid())" is acceptable behavior for changeUser in sysvinit instead of "return nil" when "USER" isn't specified (so that we get the proper group list even if that is the empty list, even in the default case of not supplying an explicit USER to run as, which implies USER 0)
  2540  USER root
  2541  RUN [ "$(id -G):$(id -Gn)" = '0 10:root wheel' ]
  2542  
  2543  # Setup dockerio user and group
  2544  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd && \
  2545  	echo 'dockerio:x:1001:' >> /etc/group
  2546  
  2547  # Make sure we can switch to our user and all the information is exactly as we expect it to be
  2548  USER dockerio
  2549  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  2550  
  2551  # Switch back to root and double check that worked exactly as we might expect it to
  2552  USER root
  2553  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '0:0/root:root/0 10:root wheel' ] && \
  2554          # Add a "supplementary" group for our dockerio user
  2555  	echo 'supplementary:x:1002:dockerio' >> /etc/group
  2556  
  2557  # ... and then go verify that we get it like we expect
  2558  USER dockerio
  2559  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001 1002:dockerio supplementary' ]
  2560  USER 1001
  2561  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001 1002:dockerio supplementary' ]
  2562  
  2563  # super test the new "user:group" syntax
  2564  USER dockerio:dockerio
  2565  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  2566  USER 1001:dockerio
  2567  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  2568  USER dockerio:1001
  2569  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  2570  USER 1001:1001
  2571  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  2572  USER dockerio:supplementary
  2573  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  2574  USER dockerio:1002
  2575  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  2576  USER 1001:supplementary
  2577  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  2578  USER 1001:1002
  2579  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  2580  
  2581  # make sure unknown uid/gid still works properly
  2582  USER 1042:1043
  2583  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1042:1043/1042:1043/1043:1043' ]`))
  2584  }
  2585  
  2586  // FIXME(vdemeester) rename this test (and probably "merge" it with the one below TestBuildEnvUsage2)
  2587  func (s *DockerSuite) TestBuildEnvUsage(c *check.C) {
  2588  	// /docker/world/hello is not owned by the correct user
  2589  	testRequires(c, NotUserNamespace)
  2590  	testRequires(c, DaemonIsLinux)
  2591  	name := "testbuildenvusage"
  2592  	dockerfile := `FROM busybox
  2593  ENV    HOME /root
  2594  ENV    PATH $HOME/bin:$PATH
  2595  ENV    PATH /tmp:$PATH
  2596  RUN    [ "$PATH" = "/tmp:$HOME/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ]
  2597  ENV    FOO /foo/baz
  2598  ENV    BAR /bar
  2599  ENV    BAZ $BAR
  2600  ENV    FOOPATH $PATH:$FOO
  2601  RUN    [ "$BAR" = "$BAZ" ]
  2602  RUN    [ "$FOOPATH" = "$PATH:/foo/baz" ]
  2603  ENV    FROM hello/docker/world
  2604  ENV    TO /docker/world/hello
  2605  ADD    $FROM $TO
  2606  RUN    [ "$(cat $TO)" = "hello" ]
  2607  ENV    abc=def
  2608  ENV    ghi=$abc
  2609  RUN    [ "$ghi" = "def" ]
  2610  `
  2611  	buildImageSuccessfully(c, name, withBuildContext(c,
  2612  		withFile("Dockerfile", dockerfile),
  2613  		withFile("hello/docker/world", "hello"),
  2614  	))
  2615  }
  2616  
  2617  // FIXME(vdemeester) rename this test (and probably "merge" it with the one above TestBuildEnvUsage)
  2618  func (s *DockerSuite) TestBuildEnvUsage2(c *check.C) {
  2619  	// /docker/world/hello is not owned by the correct user
  2620  	testRequires(c, NotUserNamespace)
  2621  	testRequires(c, DaemonIsLinux)
  2622  	name := "testbuildenvusage2"
  2623  	dockerfile := `FROM busybox
  2624  ENV    abc=def def="hello world"
  2625  RUN    [ "$abc,$def" = "def,hello world" ]
  2626  ENV    def=hello\ world v1=abc v2="hi there" v3='boogie nights' v4="with'quotes too"
  2627  RUN    [ "$def,$v1,$v2,$v3,$v4" = "hello world,abc,hi there,boogie nights,with'quotes too" ]
  2628  ENV    abc=zzz FROM=hello/docker/world
  2629  ENV    abc=zzz TO=/docker/world/hello
  2630  ADD    $FROM $TO
  2631  RUN    [ "$abc,$(cat $TO)" = "zzz,hello" ]
  2632  ENV    abc 'yyy'
  2633  RUN    [ $abc = 'yyy' ]
  2634  ENV    abc=
  2635  RUN    [ "$abc" = "" ]
  2636  
  2637  # use grep to make sure if the builder substitutes \$foo by mistake
  2638  # we don't get a false positive
  2639  ENV    abc=\$foo
  2640  RUN    [ "$abc" = "\$foo" ] && (echo "$abc" | grep foo)
  2641  ENV    abc \$foo
  2642  RUN    [ "$abc" = "\$foo" ] && (echo "$abc" | grep foo)
  2643  
  2644  ENV    abc=\'foo\' abc2=\"foo\"
  2645  RUN    [ "$abc,$abc2" = "'foo',\"foo\"" ]
  2646  ENV    abc "foo"
  2647  RUN    [ "$abc" = "foo" ]
  2648  ENV    abc 'foo'
  2649  RUN    [ "$abc" = 'foo' ]
  2650  ENV    abc \'foo\'
  2651  RUN    [ "$abc" = "'foo'" ]
  2652  ENV    abc \"foo\"
  2653  RUN    [ "$abc" = '"foo"' ]
  2654  
  2655  ENV    abc=ABC
  2656  RUN    [ "$abc" = "ABC" ]
  2657  ENV    def1=${abc:-DEF} def2=${ccc:-DEF}
  2658  ENV    def3=${ccc:-${def2}xx} def4=${abc:+ALT} def5=${def2:+${abc}:} def6=${ccc:-\$abc:} def7=${ccc:-\${abc}:}
  2659  RUN    [ "$def1,$def2,$def3,$def4,$def5,$def6,$def7" = 'ABC,DEF,DEFxx,ALT,ABC:,$abc:,${abc:}' ]
  2660  ENV    mypath=${mypath:+$mypath:}/home
  2661  ENV    mypath=${mypath:+$mypath:}/away
  2662  RUN    [ "$mypath" = '/home:/away' ]
  2663  
  2664  ENV    e1=bar
  2665  ENV    e2=$e1 e3=$e11 e4=\$e1 e5=\$e11
  2666  RUN    [ "$e0,$e1,$e2,$e3,$e4,$e5" = ',bar,bar,,$e1,$e11' ]
  2667  
  2668  ENV    ee1 bar
  2669  ENV    ee2 $ee1
  2670  ENV    ee3 $ee11
  2671  ENV    ee4 \$ee1
  2672  ENV    ee5 \$ee11
  2673  RUN    [ "$ee1,$ee2,$ee3,$ee4,$ee5" = 'bar,bar,,$ee1,$ee11' ]
  2674  
  2675  ENV    eee1="foo" eee2='foo'
  2676  ENV    eee3 "foo"
  2677  ENV    eee4 'foo'
  2678  RUN    [ "$eee1,$eee2,$eee3,$eee4" = 'foo,foo,foo,foo' ]
  2679  
  2680  `
  2681  	buildImageSuccessfully(c, name, withBuildContext(c,
  2682  		withFile("Dockerfile", dockerfile),
  2683  		withFile("hello/docker/world", "hello"),
  2684  	))
  2685  }
  2686  
  2687  func (s *DockerSuite) TestBuildAddScript(c *check.C) {
  2688  	testRequires(c, DaemonIsLinux)
  2689  	name := "testbuildaddscript"
  2690  	dockerfile := `
  2691  FROM busybox
  2692  ADD test /test
  2693  RUN ["chmod","+x","/test"]
  2694  RUN ["/test"]
  2695  RUN [ "$(cat /testfile)" = 'test!' ]`
  2696  
  2697  	buildImageSuccessfully(c, name, withBuildContext(c,
  2698  		withFile("Dockerfile", dockerfile),
  2699  		withFile("test", "#!/bin/sh\necho 'test!' > /testfile"),
  2700  	))
  2701  }
  2702  
  2703  func (s *DockerSuite) TestBuildAddTar(c *check.C) {
  2704  	// /test/foo is not owned by the correct user
  2705  	testRequires(c, NotUserNamespace)
  2706  	name := "testbuildaddtar"
  2707  
  2708  	ctx := func() *FakeContext {
  2709  		dockerfile := `
  2710  FROM busybox
  2711  ADD test.tar /
  2712  RUN cat /test/foo | grep Hi
  2713  ADD test.tar /test.tar
  2714  RUN cat /test.tar/test/foo | grep Hi
  2715  ADD test.tar /unlikely-to-exist
  2716  RUN cat /unlikely-to-exist/test/foo | grep Hi
  2717  ADD test.tar /unlikely-to-exist-trailing-slash/
  2718  RUN cat /unlikely-to-exist-trailing-slash/test/foo | grep Hi
  2719  RUN sh -c "mkdir /existing-directory" #sh -c is needed on Windows to use the correct mkdir
  2720  ADD test.tar /existing-directory
  2721  RUN cat /existing-directory/test/foo | grep Hi
  2722  ADD test.tar /existing-directory-trailing-slash/
  2723  RUN cat /existing-directory-trailing-slash/test/foo | grep Hi`
  2724  		tmpDir, err := ioutil.TempDir("", "fake-context")
  2725  		c.Assert(err, check.IsNil)
  2726  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  2727  		if err != nil {
  2728  			c.Fatalf("failed to create test.tar archive: %v", err)
  2729  		}
  2730  		defer testTar.Close()
  2731  
  2732  		tw := tar.NewWriter(testTar)
  2733  
  2734  		if err := tw.WriteHeader(&tar.Header{
  2735  			Name: "test/foo",
  2736  			Size: 2,
  2737  		}); err != nil {
  2738  			c.Fatalf("failed to write tar file header: %v", err)
  2739  		}
  2740  		if _, err := tw.Write([]byte("Hi")); err != nil {
  2741  			c.Fatalf("failed to write tar file content: %v", err)
  2742  		}
  2743  		if err := tw.Close(); err != nil {
  2744  			c.Fatalf("failed to close tar archive: %v", err)
  2745  		}
  2746  
  2747  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  2748  			c.Fatalf("failed to open destination dockerfile: %v", err)
  2749  		}
  2750  		return fakeContextFromDir(tmpDir)
  2751  	}()
  2752  	defer ctx.Close()
  2753  
  2754  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  2755  }
  2756  
  2757  func (s *DockerSuite) TestBuildAddBrokenTar(c *check.C) {
  2758  	name := "testbuildaddbrokentar"
  2759  
  2760  	ctx := func() *FakeContext {
  2761  		dockerfile := `
  2762  FROM busybox
  2763  ADD test.tar /`
  2764  		tmpDir, err := ioutil.TempDir("", "fake-context")
  2765  		c.Assert(err, check.IsNil)
  2766  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  2767  		if err != nil {
  2768  			c.Fatalf("failed to create test.tar archive: %v", err)
  2769  		}
  2770  		defer testTar.Close()
  2771  
  2772  		tw := tar.NewWriter(testTar)
  2773  
  2774  		if err := tw.WriteHeader(&tar.Header{
  2775  			Name: "test/foo",
  2776  			Size: 2,
  2777  		}); err != nil {
  2778  			c.Fatalf("failed to write tar file header: %v", err)
  2779  		}
  2780  		if _, err := tw.Write([]byte("Hi")); err != nil {
  2781  			c.Fatalf("failed to write tar file content: %v", err)
  2782  		}
  2783  		if err := tw.Close(); err != nil {
  2784  			c.Fatalf("failed to close tar archive: %v", err)
  2785  		}
  2786  
  2787  		// Corrupt the tar by removing one byte off the end
  2788  		stat, err := testTar.Stat()
  2789  		if err != nil {
  2790  			c.Fatalf("failed to stat tar archive: %v", err)
  2791  		}
  2792  		if err := testTar.Truncate(stat.Size() - 1); err != nil {
  2793  			c.Fatalf("failed to truncate tar archive: %v", err)
  2794  		}
  2795  
  2796  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  2797  			c.Fatalf("failed to open destination dockerfile: %v", err)
  2798  		}
  2799  		return fakeContextFromDir(tmpDir)
  2800  	}()
  2801  	defer ctx.Close()
  2802  
  2803  	buildImage(name, withExternalBuildContext(ctx)).Assert(c, icmd.Expected{
  2804  		ExitCode: 1,
  2805  	})
  2806  }
  2807  
  2808  func (s *DockerSuite) TestBuildAddNonTar(c *check.C) {
  2809  	name := "testbuildaddnontar"
  2810  
  2811  	// Should not try to extract test.tar
  2812  	buildImageSuccessfully(c, name, withBuildContext(c,
  2813  		withFile("Dockerfile", `
  2814  		FROM busybox
  2815  		ADD test.tar /
  2816  		RUN test -f /test.tar`),
  2817  		withFile("test.tar", "not_a_tar_file"),
  2818  	))
  2819  }
  2820  
  2821  func (s *DockerSuite) TestBuildAddTarXz(c *check.C) {
  2822  	// /test/foo is not owned by the correct user
  2823  	testRequires(c, NotUserNamespace)
  2824  	testRequires(c, DaemonIsLinux)
  2825  	name := "testbuildaddtarxz"
  2826  
  2827  	ctx := func() *FakeContext {
  2828  		dockerfile := `
  2829  			FROM busybox
  2830  			ADD test.tar.xz /
  2831  			RUN cat /test/foo | grep Hi`
  2832  		tmpDir, err := ioutil.TempDir("", "fake-context")
  2833  		c.Assert(err, check.IsNil)
  2834  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  2835  		if err != nil {
  2836  			c.Fatalf("failed to create test.tar archive: %v", err)
  2837  		}
  2838  		defer testTar.Close()
  2839  
  2840  		tw := tar.NewWriter(testTar)
  2841  
  2842  		if err := tw.WriteHeader(&tar.Header{
  2843  			Name: "test/foo",
  2844  			Size: 2,
  2845  		}); err != nil {
  2846  			c.Fatalf("failed to write tar file header: %v", err)
  2847  		}
  2848  		if _, err := tw.Write([]byte("Hi")); err != nil {
  2849  			c.Fatalf("failed to write tar file content: %v", err)
  2850  		}
  2851  		if err := tw.Close(); err != nil {
  2852  			c.Fatalf("failed to close tar archive: %v", err)
  2853  		}
  2854  
  2855  		icmd.RunCmd(icmd.Cmd{
  2856  			Command: []string{"xz", "-k", "test.tar"},
  2857  			Dir:     tmpDir,
  2858  		}).Assert(c, icmd.Success)
  2859  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  2860  			c.Fatalf("failed to open destination dockerfile: %v", err)
  2861  		}
  2862  		return fakeContextFromDir(tmpDir)
  2863  	}()
  2864  
  2865  	defer ctx.Close()
  2866  
  2867  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  2868  }
  2869  
  2870  func (s *DockerSuite) TestBuildAddTarXzGz(c *check.C) {
  2871  	testRequires(c, DaemonIsLinux)
  2872  	name := "testbuildaddtarxzgz"
  2873  
  2874  	ctx := func() *FakeContext {
  2875  		dockerfile := `
  2876  			FROM busybox
  2877  			ADD test.tar.xz.gz /
  2878  			RUN ls /test.tar.xz.gz`
  2879  		tmpDir, err := ioutil.TempDir("", "fake-context")
  2880  		c.Assert(err, check.IsNil)
  2881  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  2882  		if err != nil {
  2883  			c.Fatalf("failed to create test.tar archive: %v", err)
  2884  		}
  2885  		defer testTar.Close()
  2886  
  2887  		tw := tar.NewWriter(testTar)
  2888  
  2889  		if err := tw.WriteHeader(&tar.Header{
  2890  			Name: "test/foo",
  2891  			Size: 2,
  2892  		}); err != nil {
  2893  			c.Fatalf("failed to write tar file header: %v", err)
  2894  		}
  2895  		if _, err := tw.Write([]byte("Hi")); err != nil {
  2896  			c.Fatalf("failed to write tar file content: %v", err)
  2897  		}
  2898  		if err := tw.Close(); err != nil {
  2899  			c.Fatalf("failed to close tar archive: %v", err)
  2900  		}
  2901  
  2902  		icmd.RunCmd(icmd.Cmd{
  2903  			Command: []string{"xz", "-k", "test.tar"},
  2904  			Dir:     tmpDir,
  2905  		}).Assert(c, icmd.Success)
  2906  
  2907  		icmd.RunCmd(icmd.Cmd{
  2908  			Command: []string{"gzip", "test.tar.xz"},
  2909  			Dir:     tmpDir,
  2910  		})
  2911  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  2912  			c.Fatalf("failed to open destination dockerfile: %v", err)
  2913  		}
  2914  		return fakeContextFromDir(tmpDir)
  2915  	}()
  2916  
  2917  	defer ctx.Close()
  2918  
  2919  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  2920  }
  2921  
  2922  func (s *DockerSuite) TestBuildFromGit(c *check.C) {
  2923  	name := "testbuildfromgit"
  2924  	git := newFakeGit(c, "repo", map[string]string{
  2925  		"Dockerfile": `FROM busybox
  2926  		ADD first /first
  2927  		RUN [ -f /first ]
  2928  		MAINTAINER docker`,
  2929  		"first": "test git data",
  2930  	}, true)
  2931  	defer git.Close()
  2932  
  2933  	buildImageSuccessfully(c, name, withBuildContextPath(git.RepoURL))
  2934  
  2935  	res := inspectField(c, name, "Author")
  2936  	if res != "docker" {
  2937  		c.Fatalf("Maintainer should be docker, got %s", res)
  2938  	}
  2939  }
  2940  
  2941  func (s *DockerSuite) TestBuildFromGitWithContext(c *check.C) {
  2942  	name := "testbuildfromgit"
  2943  	git := newFakeGit(c, "repo", map[string]string{
  2944  		"docker/Dockerfile": `FROM busybox
  2945  					ADD first /first
  2946  					RUN [ -f /first ]
  2947  					MAINTAINER docker`,
  2948  		"docker/first": "test git data",
  2949  	}, true)
  2950  	defer git.Close()
  2951  
  2952  	buildImageSuccessfully(c, name, withBuildContextPath(fmt.Sprintf("%s#master:docker", git.RepoURL)))
  2953  
  2954  	res := inspectField(c, name, "Author")
  2955  	if res != "docker" {
  2956  		c.Fatalf("Maintainer should be docker, got %s", res)
  2957  	}
  2958  }
  2959  
  2960  func (s *DockerSuite) TestBuildFromGitwithF(c *check.C) {
  2961  	name := "testbuildfromgitwithf"
  2962  	git := newFakeGit(c, "repo", map[string]string{
  2963  		"myApp/myDockerfile": `FROM busybox
  2964  					RUN echo hi from Dockerfile`,
  2965  	}, true)
  2966  	defer git.Close()
  2967  
  2968  	buildImage(name, withBuildFlags("-f", "myApp/myDockerfile"), withBuildContextPath(git.RepoURL)).Assert(c, icmd.Expected{
  2969  		Out: "hi from Dockerfile",
  2970  	})
  2971  }
  2972  
  2973  func (s *DockerSuite) TestBuildFromRemoteTarball(c *check.C) {
  2974  	name := "testbuildfromremotetarball"
  2975  
  2976  	buffer := new(bytes.Buffer)
  2977  	tw := tar.NewWriter(buffer)
  2978  	defer tw.Close()
  2979  
  2980  	dockerfile := []byte(`FROM busybox
  2981  					MAINTAINER docker`)
  2982  	if err := tw.WriteHeader(&tar.Header{
  2983  		Name: "Dockerfile",
  2984  		Size: int64(len(dockerfile)),
  2985  	}); err != nil {
  2986  		c.Fatalf("failed to write tar file header: %v", err)
  2987  	}
  2988  	if _, err := tw.Write(dockerfile); err != nil {
  2989  		c.Fatalf("failed to write tar file content: %v", err)
  2990  	}
  2991  	if err := tw.Close(); err != nil {
  2992  		c.Fatalf("failed to close tar archive: %v", err)
  2993  	}
  2994  
  2995  	server := fakeBinaryStorage(c, map[string]*bytes.Buffer{
  2996  		"testT.tar": buffer,
  2997  	})
  2998  	defer server.Close()
  2999  
  3000  	buildImageSuccessfully(c, name, withBuildContextPath(server.URL()+"/testT.tar"))
  3001  
  3002  	res := inspectField(c, name, "Author")
  3003  	if res != "docker" {
  3004  		c.Fatalf("Maintainer should be docker, got %s", res)
  3005  	}
  3006  }
  3007  
  3008  func (s *DockerSuite) TestBuildCleanupCmdOnEntrypoint(c *check.C) {
  3009  	name := "testbuildcmdcleanuponentrypoint"
  3010  
  3011  	buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+`
  3012  		CMD ["test"]
  3013  		ENTRYPOINT ["echo"]`))
  3014  	buildImageSuccessfully(c, name, withDockerfile(fmt.Sprintf(`FROM %s
  3015  		ENTRYPOINT ["cat"]`, name)))
  3016  
  3017  	res := inspectField(c, name, "Config.Cmd")
  3018  	if res != "[]" {
  3019  		c.Fatalf("Cmd %s, expected nil", res)
  3020  	}
  3021  	res = inspectField(c, name, "Config.Entrypoint")
  3022  	if expected := "[cat]"; res != expected {
  3023  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  3024  	}
  3025  }
  3026  
  3027  func (s *DockerSuite) TestBuildClearCmd(c *check.C) {
  3028  	name := "testbuildclearcmd"
  3029  	buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+`
  3030     ENTRYPOINT ["/bin/bash"]
  3031     CMD []`))
  3032  
  3033  	res := inspectFieldJSON(c, name, "Config.Cmd")
  3034  	if res != "[]" {
  3035  		c.Fatalf("Cmd %s, expected %s", res, "[]")
  3036  	}
  3037  }
  3038  
  3039  func (s *DockerSuite) TestBuildEmptyCmd(c *check.C) {
  3040  	// Skip on Windows. Base image on Windows has a CMD set in the image.
  3041  	testRequires(c, DaemonIsLinux)
  3042  
  3043  	name := "testbuildemptycmd"
  3044  	buildImageSuccessfully(c, name, withDockerfile("FROM "+minimalBaseImage()+"\nMAINTAINER quux\n"))
  3045  
  3046  	res := inspectFieldJSON(c, name, "Config.Cmd")
  3047  	if res != "null" {
  3048  		c.Fatalf("Cmd %s, expected %s", res, "null")
  3049  	}
  3050  }
  3051  
  3052  func (s *DockerSuite) TestBuildOnBuildOutput(c *check.C) {
  3053  	name := "testbuildonbuildparent"
  3054  	buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nONBUILD RUN echo foo\n"))
  3055  
  3056  	buildImage(name, withDockerfile("FROM "+name+"\nMAINTAINER quux\n")).Assert(c, icmd.Expected{
  3057  		Out: "# Executing 1 build trigger",
  3058  	})
  3059  }
  3060  
  3061  // FIXME(vdemeester) should be a unit test
  3062  func (s *DockerSuite) TestBuildInvalidTag(c *check.C) {
  3063  	name := "abcd:" + stringutils.GenerateRandomAlphaOnlyString(200)
  3064  	buildImage(name, withDockerfile("FROM "+minimalBaseImage()+"\nMAINTAINER quux\n")).Assert(c, icmd.Expected{
  3065  		ExitCode: 125,
  3066  		Err:      "invalid reference format",
  3067  	})
  3068  }
  3069  
  3070  func (s *DockerSuite) TestBuildCmdShDashC(c *check.C) {
  3071  	name := "testbuildcmdshc"
  3072  	buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nCMD echo cmd\n"))
  3073  
  3074  	res := inspectFieldJSON(c, name, "Config.Cmd")
  3075  	expected := `["/bin/sh","-c","echo cmd"]`
  3076  	if testEnv.DaemonPlatform() == "windows" {
  3077  		expected = `["cmd","/S","/C","echo cmd"]`
  3078  	}
  3079  	if res != expected {
  3080  		c.Fatalf("Expected value %s not in Config.Cmd: %s", expected, res)
  3081  	}
  3082  
  3083  }
  3084  
  3085  func (s *DockerSuite) TestBuildCmdSpaces(c *check.C) {
  3086  	// Test to make sure that when we strcat arrays we take into account
  3087  	// the arg separator to make sure ["echo","hi"] and ["echo hi"] don't
  3088  	// look the same
  3089  	name := "testbuildcmdspaces"
  3090  
  3091  	buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nCMD [\"echo hi\"]\n"))
  3092  	id1 := getIDByName(c, name)
  3093  	buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nCMD [\"echo\", \"hi\"]\n"))
  3094  	id2 := getIDByName(c, name)
  3095  
  3096  	if id1 == id2 {
  3097  		c.Fatal("Should not have resulted in the same CMD")
  3098  	}
  3099  
  3100  	// Now do the same with ENTRYPOINT
  3101  	buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nENTRYPOINT [\"echo hi\"]\n"))
  3102  	id1 = getIDByName(c, name)
  3103  	buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nENTRYPOINT [\"echo\", \"hi\"]\n"))
  3104  	id2 = getIDByName(c, name)
  3105  
  3106  	if id1 == id2 {
  3107  		c.Fatal("Should not have resulted in the same ENTRYPOINT")
  3108  	}
  3109  }
  3110  
  3111  func (s *DockerSuite) TestBuildCmdJSONNoShDashC(c *check.C) {
  3112  	name := "testbuildcmdjson"
  3113  	buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nCMD [\"echo\", \"cmd\"]"))
  3114  
  3115  	res := inspectFieldJSON(c, name, "Config.Cmd")
  3116  	expected := `["echo","cmd"]`
  3117  	if res != expected {
  3118  		c.Fatalf("Expected value %s not in Config.Cmd: %s", expected, res)
  3119  	}
  3120  }
  3121  
  3122  func (s *DockerSuite) TestBuildEntrypointCanBeOverridenByChild(c *check.C) {
  3123  	buildImageSuccessfully(c, "parent", withDockerfile(`
  3124      FROM busybox
  3125      ENTRYPOINT exit 130
  3126      `))
  3127  
  3128  	icmd.RunCommand(dockerBinary, "run", "parent").Assert(c, icmd.Expected{
  3129  		ExitCode: 130,
  3130  	})
  3131  
  3132  	buildImageSuccessfully(c, "child", withDockerfile(`
  3133      FROM parent
  3134      ENTRYPOINT exit 5
  3135      `))
  3136  
  3137  	icmd.RunCommand(dockerBinary, "run", "child").Assert(c, icmd.Expected{
  3138  		ExitCode: 5,
  3139  	})
  3140  }
  3141  
  3142  func (s *DockerSuite) TestBuildEntrypointCanBeOverridenByChildInspect(c *check.C) {
  3143  	var (
  3144  		name     = "testbuildepinherit"
  3145  		name2    = "testbuildepinherit2"
  3146  		expected = `["/bin/sh","-c","echo quux"]`
  3147  	)
  3148  
  3149  	if testEnv.DaemonPlatform() == "windows" {
  3150  		expected = `["cmd","/S","/C","echo quux"]`
  3151  	}
  3152  
  3153  	buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nENTRYPOINT /foo/bar"))
  3154  	buildImageSuccessfully(c, name2, withDockerfile(fmt.Sprintf("FROM %s\nENTRYPOINT echo quux", name)))
  3155  
  3156  	res := inspectFieldJSON(c, name2, "Config.Entrypoint")
  3157  	if res != expected {
  3158  		c.Fatalf("Expected value %s not in Config.Entrypoint: %s", expected, res)
  3159  	}
  3160  
  3161  	icmd.RunCommand(dockerBinary, "run", name2).Assert(c, icmd.Expected{
  3162  		Out: "quux",
  3163  	})
  3164  }
  3165  
  3166  func (s *DockerSuite) TestBuildRunShEntrypoint(c *check.C) {
  3167  	name := "testbuildentrypoint"
  3168  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  3169                                  ENTRYPOINT echo`))
  3170  	dockerCmd(c, "run", "--rm", name)
  3171  }
  3172  
  3173  func (s *DockerSuite) TestBuildExoticShellInterpolation(c *check.C) {
  3174  	testRequires(c, DaemonIsLinux)
  3175  	name := "testbuildexoticshellinterpolation"
  3176  
  3177  	buildImageSuccessfully(c, name, withDockerfile(`
  3178  		FROM busybox
  3179  
  3180  		ENV SOME_VAR a.b.c
  3181  
  3182  		RUN [ "$SOME_VAR"       = 'a.b.c' ]
  3183  		RUN [ "${SOME_VAR}"     = 'a.b.c' ]
  3184  		RUN [ "${SOME_VAR%.*}"  = 'a.b'   ]
  3185  		RUN [ "${SOME_VAR%%.*}" = 'a'     ]
  3186  		RUN [ "${SOME_VAR#*.}"  = 'b.c'   ]
  3187  		RUN [ "${SOME_VAR##*.}" = 'c'     ]
  3188  		RUN [ "${SOME_VAR/c/d}" = 'a.b.d' ]
  3189  		RUN [ "${#SOME_VAR}"    = '5'     ]
  3190  
  3191  		RUN [ "${SOME_UNSET_VAR:-$SOME_VAR}" = 'a.b.c' ]
  3192  		RUN [ "${SOME_VAR:+Version: ${SOME_VAR}}" = 'Version: a.b.c' ]
  3193  		RUN [ "${SOME_UNSET_VAR:+${SOME_VAR}}" = '' ]
  3194  		RUN [ "${SOME_UNSET_VAR:-${SOME_VAR:-d.e.f}}" = 'a.b.c' ]
  3195  	`))
  3196  }
  3197  
  3198  func (s *DockerSuite) TestBuildVerifySingleQuoteFails(c *check.C) {
  3199  	// This testcase is supposed to generate an error because the
  3200  	// JSON array we're passing in on the CMD uses single quotes instead
  3201  	// of double quotes (per the JSON spec). This means we interpret it
  3202  	// as a "string" instead of "JSON array" and pass it on to "sh -c" and
  3203  	// it should barf on it.
  3204  	name := "testbuildsinglequotefails"
  3205  	expectedExitCode := 2
  3206  	if testEnv.DaemonPlatform() == "windows" {
  3207  		expectedExitCode = 127
  3208  	}
  3209  
  3210  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  3211  		CMD [ '/bin/sh', '-c', 'echo hi' ]`))
  3212  
  3213  	icmd.RunCommand(dockerBinary, "run", "--rm", name).Assert(c, icmd.Expected{
  3214  		ExitCode: expectedExitCode,
  3215  	})
  3216  }
  3217  
  3218  func (s *DockerSuite) TestBuildVerboseOut(c *check.C) {
  3219  	name := "testbuildverboseout"
  3220  	expected := "\n123\n"
  3221  
  3222  	if testEnv.DaemonPlatform() == "windows" {
  3223  		expected = "\n123\r\n"
  3224  	}
  3225  
  3226  	buildImage(name, withDockerfile(`FROM busybox
  3227  RUN echo 123`)).Assert(c, icmd.Expected{
  3228  		Out: expected,
  3229  	})
  3230  }
  3231  
  3232  func (s *DockerSuite) TestBuildWithTabs(c *check.C) {
  3233  	name := "testbuildwithtabs"
  3234  	buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nRUN echo\tone\t\ttwo"))
  3235  	res := inspectFieldJSON(c, name, "ContainerConfig.Cmd")
  3236  	expected1 := `["/bin/sh","-c","echo\tone\t\ttwo"]`
  3237  	expected2 := `["/bin/sh","-c","echo\u0009one\u0009\u0009two"]` // syntactically equivalent, and what Go 1.3 generates
  3238  	if testEnv.DaemonPlatform() == "windows" {
  3239  		expected1 = `["cmd","/S","/C","echo\tone\t\ttwo"]`
  3240  		expected2 = `["cmd","/S","/C","echo\u0009one\u0009\u0009two"]` // syntactically equivalent, and what Go 1.3 generates
  3241  	}
  3242  	if res != expected1 && res != expected2 {
  3243  		c.Fatalf("Missing tabs.\nGot: %s\nExp: %s or %s", res, expected1, expected2)
  3244  	}
  3245  }
  3246  
  3247  func (s *DockerSuite) TestBuildLabels(c *check.C) {
  3248  	name := "testbuildlabel"
  3249  	expected := `{"License":"GPL","Vendor":"Acme"}`
  3250  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  3251  		LABEL Vendor=Acme
  3252                  LABEL License GPL`))
  3253  	res := inspectFieldJSON(c, name, "Config.Labels")
  3254  	if res != expected {
  3255  		c.Fatalf("Labels %s, expected %s", res, expected)
  3256  	}
  3257  }
  3258  
  3259  func (s *DockerSuite) TestBuildLabelsCache(c *check.C) {
  3260  	name := "testbuildlabelcache"
  3261  
  3262  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  3263  		LABEL Vendor=Acme`))
  3264  	id1 := getIDByName(c, name)
  3265  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  3266  		LABEL Vendor=Acme`))
  3267  	id2 := getIDByName(c, name)
  3268  	if id1 != id2 {
  3269  		c.Fatalf("Build 2 should have worked & used cache(%s,%s)", id1, id2)
  3270  	}
  3271  
  3272  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  3273  		LABEL Vendor=Acme1`))
  3274  	id2 = getIDByName(c, name)
  3275  	if id1 == id2 {
  3276  		c.Fatalf("Build 3 should have worked & NOT used cache(%s,%s)", id1, id2)
  3277  	}
  3278  
  3279  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  3280  		LABEL Vendor Acme`))
  3281  	id2 = getIDByName(c, name)
  3282  	if id1 != id2 {
  3283  		c.Fatalf("Build 4 should have worked & used cache(%s,%s)", id1, id2)
  3284  	}
  3285  
  3286  	// Now make sure the cache isn't used by mistake
  3287  	buildImageSuccessfully(c, name, withoutCache, withDockerfile(`FROM busybox
  3288         LABEL f1=b1 f2=b2`))
  3289  
  3290  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  3291         LABEL f1=b1 f2=b2`))
  3292  	id2 = getIDByName(c, name)
  3293  	if id1 == id2 {
  3294  		c.Fatalf("Build 6 should have worked & NOT used the cache(%s,%s)", id1, id2)
  3295  	}
  3296  
  3297  }
  3298  
  3299  func (s *DockerSuite) TestBuildNotVerboseSuccess(c *check.C) {
  3300  	// This test makes sure that -q works correctly when build is successful:
  3301  	// stdout has only the image ID (long image ID) and stderr is empty.
  3302  	outRegexp := regexp.MustCompile("^(sha256:|)[a-z0-9]{64}\\n$")
  3303  	buildFlags := withBuildFlags("-q")
  3304  
  3305  	tt := []struct {
  3306  		Name      string
  3307  		BuildFunc func(string) *icmd.Result
  3308  	}{
  3309  		{
  3310  			Name: "quiet_build_stdin_success",
  3311  			BuildFunc: func(name string) *icmd.Result {
  3312  				return buildImage(name, buildFlags, withDockerfile("FROM busybox"))
  3313  			},
  3314  		},
  3315  		{
  3316  			Name: "quiet_build_ctx_success",
  3317  			BuildFunc: func(name string) *icmd.Result {
  3318  				return buildImage(name, buildFlags, withBuildContext(c,
  3319  					withFile("Dockerfile", "FROM busybox"),
  3320  					withFile("quiet_build_success_fctx", "test"),
  3321  				))
  3322  			},
  3323  		},
  3324  		{
  3325  			Name: "quiet_build_git_success",
  3326  			BuildFunc: func(name string) *icmd.Result {
  3327  				git := newFakeGit(c, "repo", map[string]string{
  3328  					"Dockerfile": "FROM busybox",
  3329  				}, true)
  3330  				return buildImage(name, buildFlags, withBuildContextPath(git.RepoURL))
  3331  			},
  3332  		},
  3333  	}
  3334  
  3335  	for _, te := range tt {
  3336  		result := te.BuildFunc(te.Name)
  3337  		result.Assert(c, icmd.Success)
  3338  		if outRegexp.Find([]byte(result.Stdout())) == nil {
  3339  			c.Fatalf("Test %s expected stdout to match the [%v] regexp, but it is [%v]", te.Name, outRegexp, result.Stdout())
  3340  		}
  3341  
  3342  		if result.Stderr() != "" {
  3343  			c.Fatalf("Test %s expected stderr to be empty, but it is [%#v]", te.Name, result.Stderr())
  3344  		}
  3345  	}
  3346  
  3347  }
  3348  
  3349  func (s *DockerSuite) TestBuildNotVerboseFailureWithNonExistImage(c *check.C) {
  3350  	// This test makes sure that -q works correctly when build fails by
  3351  	// comparing between the stderr output in quiet mode and in stdout
  3352  	// and stderr output in verbose mode
  3353  	testRequires(c, Network)
  3354  	testName := "quiet_build_not_exists_image"
  3355  	dockerfile := "FROM busybox11"
  3356  	quietResult := buildImage(testName, withBuildFlags("-q"), withDockerfile(dockerfile))
  3357  	quietResult.Assert(c, icmd.Expected{
  3358  		ExitCode: 1,
  3359  	})
  3360  	result := buildImage(testName, withDockerfile(dockerfile))
  3361  	result.Assert(c, icmd.Expected{
  3362  		ExitCode: 1,
  3363  	})
  3364  	if quietResult.Stderr() != result.Combined() {
  3365  		c.Fatal(fmt.Errorf("Test[%s] expected that quiet stderr and verbose stdout are equal; quiet [%v], verbose [%v]", testName, quietResult.Stderr(), result.Combined()))
  3366  	}
  3367  }
  3368  
  3369  func (s *DockerSuite) TestBuildNotVerboseFailure(c *check.C) {
  3370  	// This test makes sure that -q works correctly when build fails by
  3371  	// comparing between the stderr output in quiet mode and in stdout
  3372  	// and stderr output in verbose mode
  3373  	testCases := []struct {
  3374  		testName   string
  3375  		dockerfile string
  3376  	}{
  3377  		{"quiet_build_no_from_at_the_beginning", "RUN whoami"},
  3378  		{"quiet_build_unknown_instr", "FROMD busybox"},
  3379  	}
  3380  
  3381  	for _, tc := range testCases {
  3382  		quietResult := buildImage(tc.testName, withBuildFlags("-q"), withDockerfile(tc.dockerfile))
  3383  		quietResult.Assert(c, icmd.Expected{
  3384  			ExitCode: 1,
  3385  		})
  3386  		result := buildImage(tc.testName, withDockerfile(tc.dockerfile))
  3387  		result.Assert(c, icmd.Expected{
  3388  			ExitCode: 1,
  3389  		})
  3390  		if quietResult.Stderr() != result.Combined() {
  3391  			c.Fatal(fmt.Errorf("Test[%s] expected that quiet stderr and verbose stdout are equal; quiet [%v], verbose [%v]", tc.testName, quietResult.Stderr(), result.Combined()))
  3392  		}
  3393  	}
  3394  }
  3395  
  3396  func (s *DockerSuite) TestBuildNotVerboseFailureRemote(c *check.C) {
  3397  	// This test ensures that when given a wrong URL, stderr in quiet mode and
  3398  	// stderr in verbose mode are identical.
  3399  	// TODO(vdemeester) with cobra, stdout has a carriage return too much so this test should not check stdout
  3400  	URL := "http://something.invalid"
  3401  	name := "quiet_build_wrong_remote"
  3402  	quietResult := buildImage(name, withBuildFlags("-q"), withBuildContextPath(URL))
  3403  	quietResult.Assert(c, icmd.Expected{
  3404  		ExitCode: 1,
  3405  	})
  3406  	result := buildImage(name, withBuildContextPath(URL))
  3407  	result.Assert(c, icmd.Expected{
  3408  		ExitCode: 1,
  3409  	})
  3410  	if strings.TrimSpace(quietResult.Stderr()) != strings.TrimSpace(result.Combined()) {
  3411  		c.Fatal(fmt.Errorf("Test[%s] expected that quiet stderr and verbose stdout are equal; quiet [%v], verbose [%v]", name, quietResult.Stderr(), result.Combined()))
  3412  	}
  3413  }
  3414  
  3415  func (s *DockerSuite) TestBuildStderr(c *check.C) {
  3416  	// This test just makes sure that no non-error output goes
  3417  	// to stderr
  3418  	name := "testbuildstderr"
  3419  	result := buildImage(name, withDockerfile("FROM busybox\nRUN echo one"))
  3420  	result.Assert(c, icmd.Success)
  3421  
  3422  	// Windows to non-Windows should have a security warning
  3423  	if runtime.GOOS == "windows" && testEnv.DaemonPlatform() != "windows" && !strings.Contains(result.Stdout(), "SECURITY WARNING:") {
  3424  		c.Fatalf("Stdout contains unexpected output: %q", result.Stdout())
  3425  	}
  3426  
  3427  	// Stderr should always be empty
  3428  	if result.Stderr() != "" {
  3429  		c.Fatalf("Stderr should have been empty, instead it's: %q", result.Stderr())
  3430  	}
  3431  }
  3432  
  3433  func (s *DockerSuite) TestBuildChownSingleFile(c *check.C) {
  3434  	testRequires(c, UnixCli, DaemonIsLinux) // test uses chown: not available on windows
  3435  
  3436  	name := "testbuildchownsinglefile"
  3437  
  3438  	ctx := fakeContext(c, `
  3439  FROM busybox
  3440  COPY test /
  3441  RUN ls -l /test
  3442  RUN [ $(ls -l /test | awk '{print $3":"$4}') = 'root:root' ]
  3443  `, map[string]string{
  3444  		"test": "test",
  3445  	})
  3446  	defer ctx.Close()
  3447  
  3448  	if err := os.Chown(filepath.Join(ctx.Dir, "test"), 4242, 4242); err != nil {
  3449  		c.Fatal(err)
  3450  	}
  3451  
  3452  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  3453  }
  3454  
  3455  func (s *DockerSuite) TestBuildSymlinkBreakout(c *check.C) {
  3456  	name := "testbuildsymlinkbreakout"
  3457  	tmpdir, err := ioutil.TempDir("", name)
  3458  	c.Assert(err, check.IsNil)
  3459  	defer os.RemoveAll(tmpdir)
  3460  	ctx := filepath.Join(tmpdir, "context")
  3461  	if err := os.MkdirAll(ctx, 0755); err != nil {
  3462  		c.Fatal(err)
  3463  	}
  3464  	if err := ioutil.WriteFile(filepath.Join(ctx, "Dockerfile"), []byte(`
  3465  	from busybox
  3466  	add symlink.tar /
  3467  	add inject /symlink/
  3468  	`), 0644); err != nil {
  3469  		c.Fatal(err)
  3470  	}
  3471  	inject := filepath.Join(ctx, "inject")
  3472  	if err := ioutil.WriteFile(inject, nil, 0644); err != nil {
  3473  		c.Fatal(err)
  3474  	}
  3475  	f, err := os.Create(filepath.Join(ctx, "symlink.tar"))
  3476  	if err != nil {
  3477  		c.Fatal(err)
  3478  	}
  3479  	w := tar.NewWriter(f)
  3480  	w.WriteHeader(&tar.Header{
  3481  		Name:     "symlink2",
  3482  		Typeflag: tar.TypeSymlink,
  3483  		Linkname: "/../../../../../../../../../../../../../../",
  3484  		Uid:      os.Getuid(),
  3485  		Gid:      os.Getgid(),
  3486  	})
  3487  	w.WriteHeader(&tar.Header{
  3488  		Name:     "symlink",
  3489  		Typeflag: tar.TypeSymlink,
  3490  		Linkname: filepath.Join("symlink2", tmpdir),
  3491  		Uid:      os.Getuid(),
  3492  		Gid:      os.Getgid(),
  3493  	})
  3494  	w.Close()
  3495  	f.Close()
  3496  
  3497  	buildImageSuccessfully(c, name, withoutCache, withExternalBuildContext(fakeContextFromDir(ctx)))
  3498  	if _, err := os.Lstat(filepath.Join(tmpdir, "inject")); err == nil {
  3499  		c.Fatal("symlink breakout - inject")
  3500  	} else if !os.IsNotExist(err) {
  3501  		c.Fatalf("unexpected error: %v", err)
  3502  	}
  3503  }
  3504  
  3505  func (s *DockerSuite) TestBuildXZHost(c *check.C) {
  3506  	// /usr/local/sbin/xz gets permission denied for the user
  3507  	testRequires(c, NotUserNamespace)
  3508  	testRequires(c, DaemonIsLinux)
  3509  	name := "testbuildxzhost"
  3510  
  3511  	buildImageSuccessfully(c, name, withBuildContext(c,
  3512  		withFile("Dockerfile", `
  3513  FROM busybox
  3514  ADD xz /usr/local/sbin/
  3515  RUN chmod 755 /usr/local/sbin/xz
  3516  ADD test.xz /
  3517  RUN [ ! -e /injected ]`),
  3518  		withFile("test.xz", "\xfd\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00"+
  3519  			"\x21\x01\x16\x00\x00\x00\x74\x2f\xe5\xa3\x01\x00\x3f\xfd"+
  3520  			"\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00\x21"),
  3521  		withFile("xz", "#!/bin/sh\ntouch /injected"),
  3522  	))
  3523  }
  3524  
  3525  func (s *DockerSuite) TestBuildVolumesRetainContents(c *check.C) {
  3526  	// /foo/file gets permission denied for the user
  3527  	testRequires(c, NotUserNamespace)
  3528  	testRequires(c, DaemonIsLinux) // TODO Windows: Issue #20127
  3529  	var (
  3530  		name     = "testbuildvolumescontent"
  3531  		expected = "some text"
  3532  		volName  = "/foo"
  3533  	)
  3534  
  3535  	if testEnv.DaemonPlatform() == "windows" {
  3536  		volName = "C:/foo"
  3537  	}
  3538  
  3539  	buildImageSuccessfully(c, name, withBuildContext(c,
  3540  		withFile("Dockerfile", `
  3541  FROM busybox
  3542  COPY content /foo/file
  3543  VOLUME `+volName+`
  3544  CMD cat /foo/file`),
  3545  		withFile("content", expected),
  3546  	))
  3547  
  3548  	out, _ := dockerCmd(c, "run", "--rm", name)
  3549  	if out != expected {
  3550  		c.Fatalf("expected file contents for /foo/file to be %q but received %q", expected, out)
  3551  	}
  3552  
  3553  }
  3554  
  3555  // FIXME(vdemeester) part of this should be unit test, other part should be clearer
  3556  func (s *DockerSuite) TestBuildRenamedDockerfile(c *check.C) {
  3557  	ctx := fakeContext(c, `FROM busybox
  3558  	RUN echo from Dockerfile`,
  3559  		map[string]string{
  3560  			"Dockerfile":       "FROM busybox\nRUN echo from Dockerfile",
  3561  			"files/Dockerfile": "FROM busybox\nRUN echo from files/Dockerfile",
  3562  			"files/dFile":      "FROM busybox\nRUN echo from files/dFile",
  3563  			"dFile":            "FROM busybox\nRUN echo from dFile",
  3564  			"files/dFile2":     "FROM busybox\nRUN echo from files/dFile2",
  3565  		})
  3566  	defer ctx.Close()
  3567  
  3568  	out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-t", "test1", ".")
  3569  	if err != nil {
  3570  		c.Fatalf("Failed to build: %s\n%s", out, err)
  3571  	}
  3572  	if !strings.Contains(out, "from Dockerfile") {
  3573  		c.Fatalf("test1 should have used Dockerfile, output:%s", out)
  3574  	}
  3575  
  3576  	out, _, err = dockerCmdInDir(c, ctx.Dir, "build", "-f", filepath.Join("files", "Dockerfile"), "-t", "test2", ".")
  3577  	if err != nil {
  3578  		c.Fatal(err)
  3579  	}
  3580  	if !strings.Contains(out, "from files/Dockerfile") {
  3581  		c.Fatalf("test2 should have used files/Dockerfile, output:%s", out)
  3582  	}
  3583  
  3584  	out, _, err = dockerCmdInDir(c, ctx.Dir, "build", fmt.Sprintf("--file=%s", filepath.Join("files", "dFile")), "-t", "test3", ".")
  3585  	if err != nil {
  3586  		c.Fatal(err)
  3587  	}
  3588  	if !strings.Contains(out, "from files/dFile") {
  3589  		c.Fatalf("test3 should have used files/dFile, output:%s", out)
  3590  	}
  3591  
  3592  	out, _, err = dockerCmdInDir(c, ctx.Dir, "build", "--file=dFile", "-t", "test4", ".")
  3593  	if err != nil {
  3594  		c.Fatal(err)
  3595  	}
  3596  	if !strings.Contains(out, "from dFile") {
  3597  		c.Fatalf("test4 should have used dFile, output:%s", out)
  3598  	}
  3599  
  3600  	dirWithNoDockerfile, err := ioutil.TempDir(os.TempDir(), "test5")
  3601  	c.Assert(err, check.IsNil)
  3602  	nonDockerfileFile := filepath.Join(dirWithNoDockerfile, "notDockerfile")
  3603  	if _, err = os.Create(nonDockerfileFile); err != nil {
  3604  		c.Fatal(err)
  3605  	}
  3606  	out, _, err = dockerCmdInDir(c, ctx.Dir, "build", fmt.Sprintf("--file=%s", nonDockerfileFile), "-t", "test5", ".")
  3607  
  3608  	if err == nil {
  3609  		c.Fatalf("test5 was supposed to fail to find passwd")
  3610  	}
  3611  
  3612  	if expected := fmt.Sprintf("The Dockerfile (%s) must be within the build context (.)", nonDockerfileFile); !strings.Contains(out, expected) {
  3613  		c.Fatalf("wrong error message:%v\nexpected to contain=%v", out, expected)
  3614  	}
  3615  
  3616  	out, _, err = dockerCmdInDir(c, filepath.Join(ctx.Dir, "files"), "build", "-f", filepath.Join("..", "Dockerfile"), "-t", "test6", "..")
  3617  	if err != nil {
  3618  		c.Fatalf("test6 failed: %s", err)
  3619  	}
  3620  	if !strings.Contains(out, "from Dockerfile") {
  3621  		c.Fatalf("test6 should have used root Dockerfile, output:%s", out)
  3622  	}
  3623  
  3624  	out, _, err = dockerCmdInDir(c, filepath.Join(ctx.Dir, "files"), "build", "-f", filepath.Join(ctx.Dir, "files", "Dockerfile"), "-t", "test7", "..")
  3625  	if err != nil {
  3626  		c.Fatalf("test7 failed: %s", err)
  3627  	}
  3628  	if !strings.Contains(out, "from files/Dockerfile") {
  3629  		c.Fatalf("test7 should have used files Dockerfile, output:%s", out)
  3630  	}
  3631  
  3632  	out, _, err = dockerCmdInDir(c, filepath.Join(ctx.Dir, "files"), "build", "-f", filepath.Join("..", "Dockerfile"), "-t", "test8", ".")
  3633  	if err == nil || !strings.Contains(out, "must be within the build context") {
  3634  		c.Fatalf("test8 should have failed with Dockerfile out of context: %s", err)
  3635  	}
  3636  
  3637  	tmpDir := os.TempDir()
  3638  	out, _, err = dockerCmdInDir(c, tmpDir, "build", "-t", "test9", ctx.Dir)
  3639  	if err != nil {
  3640  		c.Fatalf("test9 - failed: %s", err)
  3641  	}
  3642  	if !strings.Contains(out, "from Dockerfile") {
  3643  		c.Fatalf("test9 should have used root Dockerfile, output:%s", out)
  3644  	}
  3645  
  3646  	out, _, err = dockerCmdInDir(c, filepath.Join(ctx.Dir, "files"), "build", "-f", "dFile2", "-t", "test10", ".")
  3647  	if err != nil {
  3648  		c.Fatalf("test10 should have worked: %s", err)
  3649  	}
  3650  	if !strings.Contains(out, "from files/dFile2") {
  3651  		c.Fatalf("test10 should have used files/dFile2, output:%s", out)
  3652  	}
  3653  
  3654  }
  3655  
  3656  func (s *DockerSuite) TestBuildFromMixedcaseDockerfile(c *check.C) {
  3657  	testRequires(c, UnixCli) // Dockerfile overwrites dockerfile on windows
  3658  	testRequires(c, DaemonIsLinux)
  3659  
  3660  	// If Dockerfile is not present, use dockerfile
  3661  	buildImage("test1", withBuildContext(c,
  3662  		withFile("dockerfile", `FROM busybox
  3663  	RUN echo from dockerfile`),
  3664  	)).Assert(c, icmd.Expected{
  3665  		Out: "from dockerfile",
  3666  	})
  3667  
  3668  	// Prefer Dockerfile in place of dockerfile
  3669  	buildImage("test1", withBuildContext(c,
  3670  		withFile("dockerfile", `FROM busybox
  3671  	RUN echo from dockerfile`),
  3672  		withFile("Dockerfile", `FROM busybox
  3673  	RUN echo from Dockerfile`),
  3674  	)).Assert(c, icmd.Expected{
  3675  		Out: "from Dockerfile",
  3676  	})
  3677  }
  3678  
  3679  func (s *DockerSuite) TestBuildFromURLWithF(c *check.C) {
  3680  	server := fakeStorage(c, map[string]string{"baz": `FROM busybox
  3681  RUN echo from baz
  3682  COPY * /tmp/
  3683  RUN find /tmp/`})
  3684  	defer server.Close()
  3685  
  3686  	ctx := fakeContext(c, `FROM busybox
  3687  RUN echo from Dockerfile`,
  3688  		map[string]string{})
  3689  	defer ctx.Close()
  3690  
  3691  	// Make sure that -f is ignored and that we don't use the Dockerfile
  3692  	// that's in the current dir
  3693  	result := buildImage("test1", withBuildFlags("-f", "baz", server.URL()+"/baz"), func(cmd *icmd.Cmd) func() {
  3694  		cmd.Dir = ctx.Dir
  3695  		return nil
  3696  	})
  3697  	result.Assert(c, icmd.Success)
  3698  
  3699  	if !strings.Contains(result.Combined(), "from baz") ||
  3700  		strings.Contains(result.Combined(), "/tmp/baz") ||
  3701  		!strings.Contains(result.Combined(), "/tmp/Dockerfile") {
  3702  		c.Fatalf("Missing proper output: %s", result.Combined())
  3703  	}
  3704  
  3705  }
  3706  
  3707  func (s *DockerSuite) TestBuildFromStdinWithF(c *check.C) {
  3708  	testRequires(c, DaemonIsLinux) // TODO Windows: This test is flaky; no idea why
  3709  	ctx := fakeContext(c, `FROM busybox
  3710  RUN echo "from Dockerfile"`,
  3711  		map[string]string{})
  3712  	defer ctx.Close()
  3713  
  3714  	// Make sure that -f is ignored and that we don't use the Dockerfile
  3715  	// that's in the current dir
  3716  	result := buildImage("test1", withBuildFlags("-f", "baz", "-"), func(cmd *icmd.Cmd) func() {
  3717  		cmd.Dir = ctx.Dir
  3718  		cmd.Stdin = strings.NewReader(`FROM busybox
  3719  RUN echo "from baz"
  3720  COPY * /tmp/
  3721  RUN sh -c "find /tmp/" # sh -c is needed on Windows to use the correct find`)
  3722  		return nil
  3723  	})
  3724  	result.Assert(c, icmd.Success)
  3725  
  3726  	if !strings.Contains(result.Combined(), "from baz") ||
  3727  		strings.Contains(result.Combined(), "/tmp/baz") ||
  3728  		!strings.Contains(result.Combined(), "/tmp/Dockerfile") {
  3729  		c.Fatalf("Missing proper output: %s", result.Combined())
  3730  	}
  3731  
  3732  }
  3733  
  3734  func (s *DockerSuite) TestBuildFromOfficialNames(c *check.C) {
  3735  	name := "testbuildfromofficial"
  3736  	fromNames := []string{
  3737  		"busybox",
  3738  		"docker.io/busybox",
  3739  		"index.docker.io/busybox",
  3740  		"library/busybox",
  3741  		"docker.io/library/busybox",
  3742  		"index.docker.io/library/busybox",
  3743  	}
  3744  	for idx, fromName := range fromNames {
  3745  		imgName := fmt.Sprintf("%s%d", name, idx)
  3746  		buildImageSuccessfully(c, imgName, withDockerfile("FROM "+fromName))
  3747  		dockerCmd(c, "rmi", imgName)
  3748  	}
  3749  }
  3750  
  3751  func (s *DockerSuite) TestBuildDockerfileOutsideContext(c *check.C) {
  3752  	testRequires(c, UnixCli, DaemonIsLinux) // uses os.Symlink: not implemented in windows at the time of writing (go-1.4.2)
  3753  
  3754  	name := "testbuilddockerfileoutsidecontext"
  3755  	tmpdir, err := ioutil.TempDir("", name)
  3756  	c.Assert(err, check.IsNil)
  3757  	defer os.RemoveAll(tmpdir)
  3758  	ctx := filepath.Join(tmpdir, "context")
  3759  	if err := os.MkdirAll(ctx, 0755); err != nil {
  3760  		c.Fatal(err)
  3761  	}
  3762  	if err := ioutil.WriteFile(filepath.Join(ctx, "Dockerfile"), []byte("FROM scratch\nENV X Y"), 0644); err != nil {
  3763  		c.Fatal(err)
  3764  	}
  3765  	wd, err := os.Getwd()
  3766  	if err != nil {
  3767  		c.Fatal(err)
  3768  	}
  3769  	defer os.Chdir(wd)
  3770  	if err := os.Chdir(ctx); err != nil {
  3771  		c.Fatal(err)
  3772  	}
  3773  	if err := ioutil.WriteFile(filepath.Join(tmpdir, "outsideDockerfile"), []byte("FROM scratch\nENV x y"), 0644); err != nil {
  3774  		c.Fatal(err)
  3775  	}
  3776  	if err := os.Symlink(filepath.Join("..", "outsideDockerfile"), filepath.Join(ctx, "dockerfile1")); err != nil {
  3777  		c.Fatal(err)
  3778  	}
  3779  	if err := os.Symlink(filepath.Join(tmpdir, "outsideDockerfile"), filepath.Join(ctx, "dockerfile2")); err != nil {
  3780  		c.Fatal(err)
  3781  	}
  3782  
  3783  	for _, dockerfilePath := range []string{
  3784  		filepath.Join("..", "outsideDockerfile"),
  3785  		filepath.Join(ctx, "dockerfile1"),
  3786  		filepath.Join(ctx, "dockerfile2"),
  3787  	} {
  3788  		result := dockerCmdWithResult("build", "-t", name, "--no-cache", "-f", dockerfilePath, ".")
  3789  		c.Assert(result, icmd.Matches, icmd.Expected{
  3790  			Err:      "must be within the build context",
  3791  			ExitCode: 1,
  3792  		})
  3793  		deleteImages(name)
  3794  	}
  3795  
  3796  	os.Chdir(tmpdir)
  3797  
  3798  	// Path to Dockerfile should be resolved relative to working directory, not relative to context.
  3799  	// There is a Dockerfile in the context, but since there is no Dockerfile in the current directory, the following should fail
  3800  	out, _, err := dockerCmdWithError("build", "-t", name, "--no-cache", "-f", "Dockerfile", ctx)
  3801  	if err == nil {
  3802  		c.Fatalf("Expected error. Out: %s", out)
  3803  	}
  3804  }
  3805  
  3806  // FIXME(vdemeester) should be a unit test
  3807  func (s *DockerSuite) TestBuildSpaces(c *check.C) {
  3808  	// Test to make sure that leading/trailing spaces on a command
  3809  	// doesn't change the error msg we get
  3810  	name := "testspaces"
  3811  	ctx := fakeContext(c, "FROM busybox\nCOPY\n",
  3812  		map[string]string{
  3813  			"Dockerfile": "FROM busybox\nCOPY\n",
  3814  		})
  3815  	defer ctx.Close()
  3816  
  3817  	result1 := buildImage(name, withExternalBuildContext(ctx))
  3818  	result1.Assert(c, icmd.Expected{
  3819  		ExitCode: 1,
  3820  	})
  3821  
  3822  	ctx.Add("Dockerfile", "FROM busybox\nCOPY    ")
  3823  	result2 := buildImage(name, withExternalBuildContext(ctx))
  3824  	result2.Assert(c, icmd.Expected{
  3825  		ExitCode: 1,
  3826  	})
  3827  
  3828  	removeLogTimestamps := func(s string) string {
  3829  		return regexp.MustCompile(`time="(.*?)"`).ReplaceAllString(s, `time=[TIMESTAMP]`)
  3830  	}
  3831  
  3832  	// Skip over the times
  3833  	e1 := removeLogTimestamps(result1.Error.Error())
  3834  	e2 := removeLogTimestamps(result2.Error.Error())
  3835  
  3836  	// Ignore whitespace since that's what were verifying doesn't change stuff
  3837  	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
  3838  		c.Fatalf("Build 2's error wasn't the same as build 1's\n1:%s\n2:%s", result1.Error, result2.Error)
  3839  	}
  3840  
  3841  	ctx.Add("Dockerfile", "FROM busybox\n   COPY")
  3842  	result2 = buildImage(name, withoutCache, withExternalBuildContext(ctx))
  3843  	result2.Assert(c, icmd.Expected{
  3844  		ExitCode: 1,
  3845  	})
  3846  
  3847  	// Skip over the times
  3848  	e1 = removeLogTimestamps(result1.Error.Error())
  3849  	e2 = removeLogTimestamps(result2.Error.Error())
  3850  
  3851  	// Ignore whitespace since that's what were verifying doesn't change stuff
  3852  	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
  3853  		c.Fatalf("Build 3's error wasn't the same as build 1's\n1:%s\n3:%s", result1.Error, result2.Error)
  3854  	}
  3855  
  3856  	ctx.Add("Dockerfile", "FROM busybox\n   COPY    ")
  3857  	result2 = buildImage(name, withoutCache, withExternalBuildContext(ctx))
  3858  	result2.Assert(c, icmd.Expected{
  3859  		ExitCode: 1,
  3860  	})
  3861  
  3862  	// Skip over the times
  3863  	e1 = removeLogTimestamps(result1.Error.Error())
  3864  	e2 = removeLogTimestamps(result2.Error.Error())
  3865  
  3866  	// Ignore whitespace since that's what were verifying doesn't change stuff
  3867  	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
  3868  		c.Fatalf("Build 4's error wasn't the same as build 1's\n1:%s\n4:%s", result1.Error, result2.Error)
  3869  	}
  3870  
  3871  }
  3872  
  3873  func (s *DockerSuite) TestBuildSpacesWithQuotes(c *check.C) {
  3874  	// Test to make sure that spaces in quotes aren't lost
  3875  	name := "testspacesquotes"
  3876  
  3877  	dockerfile := `FROM busybox
  3878  RUN echo "  \
  3879    foo  "`
  3880  
  3881  	expected := "\n    foo  \n"
  3882  	// Windows uses the builtin echo, which preserves quotes
  3883  	if testEnv.DaemonPlatform() == "windows" {
  3884  		expected = "\"    foo  \""
  3885  	}
  3886  
  3887  	buildImage(name, withDockerfile(dockerfile)).Assert(c, icmd.Expected{
  3888  		Out: expected,
  3889  	})
  3890  }
  3891  
  3892  // #4393
  3893  func (s *DockerSuite) TestBuildVolumeFileExistsinContainer(c *check.C) {
  3894  	testRequires(c, DaemonIsLinux) // TODO Windows: This should error out
  3895  	buildImage("docker-test-errcreatevolumewithfile", withDockerfile(`
  3896  	FROM busybox
  3897  	RUN touch /foo
  3898  	VOLUME /foo
  3899  	`)).Assert(c, icmd.Expected{
  3900  		ExitCode: 1,
  3901  		Err:      "file exists",
  3902  	})
  3903  }
  3904  
  3905  // FIXME(vdemeester) should be a unit test
  3906  func (s *DockerSuite) TestBuildMissingArgs(c *check.C) {
  3907  	// Test to make sure that all Dockerfile commands (except the ones listed
  3908  	// in skipCmds) will generate an error if no args are provided.
  3909  	// Note: INSERT is deprecated so we exclude it because of that.
  3910  	skipCmds := map[string]struct{}{
  3911  		"CMD":        {},
  3912  		"RUN":        {},
  3913  		"ENTRYPOINT": {},
  3914  		"INSERT":     {},
  3915  	}
  3916  
  3917  	if testEnv.DaemonPlatform() == "windows" {
  3918  		skipCmds = map[string]struct{}{
  3919  			"CMD":        {},
  3920  			"RUN":        {},
  3921  			"ENTRYPOINT": {},
  3922  			"INSERT":     {},
  3923  			"STOPSIGNAL": {},
  3924  			"ARG":        {},
  3925  			"USER":       {},
  3926  			"EXPOSE":     {},
  3927  		}
  3928  	}
  3929  
  3930  	for cmd := range command.Commands {
  3931  		cmd = strings.ToUpper(cmd)
  3932  		if _, ok := skipCmds[cmd]; ok {
  3933  			continue
  3934  		}
  3935  		var dockerfile string
  3936  		if cmd == "FROM" {
  3937  			dockerfile = cmd
  3938  		} else {
  3939  			// Add FROM to make sure we don't complain about it missing
  3940  			dockerfile = "FROM busybox\n" + cmd
  3941  		}
  3942  
  3943  		buildImage("args", withDockerfile(dockerfile)).Assert(c, icmd.Expected{
  3944  			ExitCode: 1,
  3945  			Err:      cmd + " requires",
  3946  		})
  3947  	}
  3948  
  3949  }
  3950  
  3951  func (s *DockerSuite) TestBuildEmptyScratch(c *check.C) {
  3952  	testRequires(c, DaemonIsLinux)
  3953  	buildImage("sc", withDockerfile("FROM scratch")).Assert(c, icmd.Expected{
  3954  		ExitCode: 1,
  3955  		Err:      "No image was generated",
  3956  	})
  3957  }
  3958  
  3959  func (s *DockerSuite) TestBuildDotDotFile(c *check.C) {
  3960  	buildImageSuccessfully(c, "sc", withBuildContext(c,
  3961  		withFile("Dockerfile", "FROM busybox\n"),
  3962  		withFile("..gitme", ""),
  3963  	))
  3964  }
  3965  
  3966  func (s *DockerSuite) TestBuildRUNoneJSON(c *check.C) {
  3967  	testRequires(c, DaemonIsLinux) // No hello-world Windows image
  3968  	name := "testbuildrunonejson"
  3969  
  3970  	buildImage(name, withDockerfile(`FROM hello-world:frozen
  3971  RUN [ "/hello" ]`)).Assert(c, icmd.Expected{
  3972  		Out: "Hello from Docker",
  3973  	})
  3974  }
  3975  
  3976  func (s *DockerSuite) TestBuildEmptyStringVolume(c *check.C) {
  3977  	name := "testbuildemptystringvolume"
  3978  
  3979  	buildImage(name, withDockerfile(`
  3980    FROM busybox
  3981    ENV foo=""
  3982    VOLUME $foo
  3983    `)).Assert(c, icmd.Expected{
  3984  		ExitCode: 1,
  3985  	})
  3986  }
  3987  
  3988  func (s *DockerSuite) TestBuildContainerWithCgroupParent(c *check.C) {
  3989  	testRequires(c, SameHostDaemon, DaemonIsLinux)
  3990  
  3991  	cgroupParent := "test"
  3992  	data, err := ioutil.ReadFile("/proc/self/cgroup")
  3993  	if err != nil {
  3994  		c.Fatalf("failed to read '/proc/self/cgroup - %v", err)
  3995  	}
  3996  	selfCgroupPaths := testutil.ParseCgroupPaths(string(data))
  3997  	_, found := selfCgroupPaths["memory"]
  3998  	if !found {
  3999  		c.Fatalf("unable to find self memory cgroup path. CgroupsPath: %v", selfCgroupPaths)
  4000  	}
  4001  	result := buildImage("buildcgroupparent",
  4002  		withBuildFlags("--cgroup-parent", cgroupParent),
  4003  		withDockerfile(`
  4004  FROM busybox
  4005  RUN cat /proc/self/cgroup
  4006  `))
  4007  	result.Assert(c, icmd.Success)
  4008  	m, err := regexp.MatchString(fmt.Sprintf("memory:.*/%s/.*", cgroupParent), result.Combined())
  4009  	c.Assert(err, check.IsNil)
  4010  	if !m {
  4011  		c.Fatalf("There is no expected memory cgroup with parent /%s/: %s", cgroupParent, result.Combined())
  4012  	}
  4013  }
  4014  
  4015  // FIXME(vdemeester) could be a unit test
  4016  func (s *DockerSuite) TestBuildNoDupOutput(c *check.C) {
  4017  	// Check to make sure our build output prints the Dockerfile cmd
  4018  	// property - there was a bug that caused it to be duplicated on the
  4019  	// Step X  line
  4020  	name := "testbuildnodupoutput"
  4021  	result := buildImage(name, withDockerfile(`
  4022    FROM busybox
  4023    RUN env`))
  4024  	result.Assert(c, icmd.Success)
  4025  	exp := "\nStep 2/2 : RUN env\n"
  4026  	if !strings.Contains(result.Combined(), exp) {
  4027  		c.Fatalf("Bad output\nGot:%s\n\nExpected to contain:%s\n", result.Combined(), exp)
  4028  	}
  4029  }
  4030  
  4031  // GH15826
  4032  // FIXME(vdemeester) could be a unit test
  4033  func (s *DockerSuite) TestBuildStartsFromOne(c *check.C) {
  4034  	// Explicit check to ensure that build starts from step 1 rather than 0
  4035  	name := "testbuildstartsfromone"
  4036  	result := buildImage(name, withDockerfile(`FROM busybox`))
  4037  	result.Assert(c, icmd.Success)
  4038  	exp := "\nStep 1/1 : FROM busybox\n"
  4039  	if !strings.Contains(result.Combined(), exp) {
  4040  		c.Fatalf("Bad output\nGot:%s\n\nExpected to contain:%s\n", result.Combined(), exp)
  4041  	}
  4042  }
  4043  
  4044  func (s *DockerSuite) TestBuildRUNErrMsg(c *check.C) {
  4045  	// Test to make sure the bad command is quoted with just "s and
  4046  	// not as a Go []string
  4047  	name := "testbuildbadrunerrmsg"
  4048  	shell := "/bin/sh -c"
  4049  	exitCode := 127
  4050  	if testEnv.DaemonPlatform() == "windows" {
  4051  		shell = "cmd /S /C"
  4052  		// architectural - Windows has to start the container to determine the exe is bad, Linux does not
  4053  		exitCode = 1
  4054  	}
  4055  	exp := fmt.Sprintf(`The command '%s badEXE a1 \& a2	a3' returned a non-zero code: %d`, shell, exitCode)
  4056  
  4057  	buildImage(name, withDockerfile(`
  4058    FROM busybox
  4059    RUN badEXE a1 \& a2	a3`)).Assert(c, icmd.Expected{
  4060  		ExitCode: exitCode,
  4061  		Err:      exp,
  4062  	})
  4063  }
  4064  
  4065  func (s *DockerTrustSuite) TestTrustedBuild(c *check.C) {
  4066  	repoName := s.setupTrustedImage(c, "trusted-build")
  4067  	dockerFile := fmt.Sprintf(`
  4068    FROM %s
  4069    RUN []
  4070      `, repoName)
  4071  
  4072  	name := "testtrustedbuild"
  4073  
  4074  	buildImage(name, trustedBuild, withDockerfile(dockerFile)).Assert(c, icmd.Expected{
  4075  		Out: fmt.Sprintf("FROM %s@sha", repoName[:len(repoName)-7]),
  4076  	})
  4077  
  4078  	// We should also have a tag reference for the image.
  4079  	dockerCmd(c, "inspect", repoName)
  4080  
  4081  	// We should now be able to remove the tag reference.
  4082  	dockerCmd(c, "rmi", repoName)
  4083  }
  4084  
  4085  func (s *DockerTrustSuite) TestTrustedBuildUntrustedTag(c *check.C) {
  4086  	repoName := fmt.Sprintf("%v/dockercli/build-untrusted-tag:latest", privateRegistryURL)
  4087  	dockerFile := fmt.Sprintf(`
  4088    FROM %s
  4089    RUN []
  4090      `, repoName)
  4091  
  4092  	name := "testtrustedbuilduntrustedtag"
  4093  
  4094  	buildImage(name, trustedBuild, withDockerfile(dockerFile)).Assert(c, icmd.Expected{
  4095  		ExitCode: 1,
  4096  		Err:      "does not have trust data for",
  4097  	})
  4098  }
  4099  
  4100  func (s *DockerTrustSuite) TestBuildContextDirIsSymlink(c *check.C) {
  4101  	testRequires(c, DaemonIsLinux)
  4102  	tempDir, err := ioutil.TempDir("", "test-build-dir-is-symlink-")
  4103  	c.Assert(err, check.IsNil)
  4104  	defer os.RemoveAll(tempDir)
  4105  
  4106  	// Make a real context directory in this temp directory with a simple
  4107  	// Dockerfile.
  4108  	realContextDirname := filepath.Join(tempDir, "context")
  4109  	if err := os.Mkdir(realContextDirname, os.FileMode(0755)); err != nil {
  4110  		c.Fatal(err)
  4111  	}
  4112  
  4113  	if err = ioutil.WriteFile(
  4114  		filepath.Join(realContextDirname, "Dockerfile"),
  4115  		[]byte(`
  4116  			FROM busybox
  4117  			RUN echo hello world
  4118  		`),
  4119  		os.FileMode(0644),
  4120  	); err != nil {
  4121  		c.Fatal(err)
  4122  	}
  4123  
  4124  	// Make a symlink to the real context directory.
  4125  	contextSymlinkName := filepath.Join(tempDir, "context_link")
  4126  	if err := os.Symlink(realContextDirname, contextSymlinkName); err != nil {
  4127  		c.Fatal(err)
  4128  	}
  4129  
  4130  	// Executing the build with the symlink as the specified context should
  4131  	// *not* fail.
  4132  	dockerCmd(c, "build", contextSymlinkName)
  4133  }
  4134  
  4135  func (s *DockerTrustSuite) TestTrustedBuildTagFromReleasesRole(c *check.C) {
  4136  	testRequires(c, NotaryHosting)
  4137  
  4138  	latestTag := s.setupTrustedImage(c, "trusted-build-releases-role")
  4139  	repoName := strings.TrimSuffix(latestTag, ":latest")
  4140  
  4141  	// Now create the releases role
  4142  	s.notaryCreateDelegation(c, repoName, "targets/releases", s.not.keys[0].Public)
  4143  	s.notaryImportKey(c, repoName, "targets/releases", s.not.keys[0].Private)
  4144  	s.notaryPublish(c, repoName)
  4145  
  4146  	// push a different tag to the releases role
  4147  	otherTag := fmt.Sprintf("%s:other", repoName)
  4148  	dockerCmd(c, "tag", "busybox", otherTag)
  4149  
  4150  	icmd.RunCmd(icmd.Command(dockerBinary, "push", otherTag), trustedCmd).Assert(c, icmd.Success)
  4151  	s.assertTargetInRoles(c, repoName, "other", "targets/releases")
  4152  	s.assertTargetNotInRoles(c, repoName, "other", "targets")
  4153  
  4154  	out, status := dockerCmd(c, "rmi", otherTag)
  4155  	c.Assert(status, check.Equals, 0, check.Commentf("docker rmi failed: %s", out))
  4156  
  4157  	dockerFile := fmt.Sprintf(`
  4158    FROM %s
  4159    RUN []
  4160      `, otherTag)
  4161  	name := "testtrustedbuildreleasesrole"
  4162  	buildImage(name, trustedBuild, withDockerfile(dockerFile)).Assert(c, icmd.Expected{
  4163  		Out: fmt.Sprintf("FROM %s@sha", repoName),
  4164  	})
  4165  }
  4166  
  4167  func (s *DockerTrustSuite) TestTrustedBuildTagIgnoresOtherDelegationRoles(c *check.C) {
  4168  	testRequires(c, NotaryHosting)
  4169  
  4170  	latestTag := s.setupTrustedImage(c, "trusted-build-releases-role")
  4171  	repoName := strings.TrimSuffix(latestTag, ":latest")
  4172  
  4173  	// Now create a non-releases delegation role
  4174  	s.notaryCreateDelegation(c, repoName, "targets/other", s.not.keys[0].Public)
  4175  	s.notaryImportKey(c, repoName, "targets/other", s.not.keys[0].Private)
  4176  	s.notaryPublish(c, repoName)
  4177  
  4178  	// push a different tag to the other role
  4179  	otherTag := fmt.Sprintf("%s:other", repoName)
  4180  	dockerCmd(c, "tag", "busybox", otherTag)
  4181  
  4182  	icmd.RunCmd(icmd.Command(dockerBinary, "push", otherTag), trustedCmd).Assert(c, icmd.Success)
  4183  	s.assertTargetInRoles(c, repoName, "other", "targets/other")
  4184  	s.assertTargetNotInRoles(c, repoName, "other", "targets")
  4185  
  4186  	out, status := dockerCmd(c, "rmi", otherTag)
  4187  	c.Assert(status, check.Equals, 0, check.Commentf("docker rmi failed: %s", out))
  4188  
  4189  	dockerFile := fmt.Sprintf(`
  4190    FROM %s
  4191    RUN []
  4192      `, otherTag)
  4193  
  4194  	name := "testtrustedbuildotherrole"
  4195  	buildImage(name, trustedBuild, withDockerfile(dockerFile)).Assert(c, icmd.Expected{
  4196  		ExitCode: 1,
  4197  	})
  4198  }
  4199  
  4200  // Issue #15634: COPY fails when path starts with "null"
  4201  func (s *DockerSuite) TestBuildNullStringInAddCopyVolume(c *check.C) {
  4202  	name := "testbuildnullstringinaddcopyvolume"
  4203  	volName := "nullvolume"
  4204  	if testEnv.DaemonPlatform() == "windows" {
  4205  		volName = `C:\\nullvolume`
  4206  	}
  4207  
  4208  	buildImageSuccessfully(c, name, withBuildContext(c,
  4209  		withFile("Dockerfile", `
  4210  		FROM busybox
  4211  
  4212  		ADD null /
  4213  		COPY nullfile /
  4214  		VOLUME `+volName+`
  4215  		`),
  4216  		withFile("null", "test1"),
  4217  		withFile("nullfile", "test2"),
  4218  	))
  4219  }
  4220  
  4221  func (s *DockerSuite) TestBuildStopSignal(c *check.C) {
  4222  	testRequires(c, DaemonIsLinux) // Windows does not support STOPSIGNAL yet
  4223  	imgName := "test_build_stop_signal"
  4224  	buildImageSuccessfully(c, imgName, withDockerfile(`FROM busybox
  4225  		 STOPSIGNAL SIGKILL`))
  4226  	res := inspectFieldJSON(c, imgName, "Config.StopSignal")
  4227  	if res != `"SIGKILL"` {
  4228  		c.Fatalf("Signal %s, expected SIGKILL", res)
  4229  	}
  4230  
  4231  	containerName := "test-container-stop-signal"
  4232  	dockerCmd(c, "run", "-d", "--name", containerName, imgName, "top")
  4233  	res = inspectFieldJSON(c, containerName, "Config.StopSignal")
  4234  	if res != `"SIGKILL"` {
  4235  		c.Fatalf("Signal %s, expected SIGKILL", res)
  4236  	}
  4237  }
  4238  
  4239  func (s *DockerSuite) TestBuildBuildTimeArg(c *check.C) {
  4240  	imgName := "bldargtest"
  4241  	envKey := "foo"
  4242  	envVal := "bar"
  4243  	var dockerfile string
  4244  	if testEnv.DaemonPlatform() == "windows" {
  4245  		// Bugs in Windows busybox port - use the default base image and native cmd stuff
  4246  		dockerfile = fmt.Sprintf(`FROM `+minimalBaseImage()+`
  4247  			ARG %s
  4248  			RUN echo %%%s%%
  4249  			CMD setlocal enableextensions && if defined %s (echo %%%s%%)`, envKey, envKey, envKey, envKey)
  4250  	} else {
  4251  		dockerfile = fmt.Sprintf(`FROM busybox
  4252  			ARG %s
  4253  			RUN echo $%s
  4254  			CMD echo $%s`, envKey, envKey, envKey)
  4255  
  4256  	}
  4257  	buildImage(imgName,
  4258  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4259  		withDockerfile(dockerfile),
  4260  	).Assert(c, icmd.Expected{
  4261  		Out: envVal,
  4262  	})
  4263  
  4264  	containerName := "bldargCont"
  4265  	out, _ := dockerCmd(c, "run", "--name", containerName, imgName)
  4266  	out = strings.Trim(out, " \r\n'")
  4267  	if out != "" {
  4268  		c.Fatalf("run produced invalid output: %q, expected empty string", out)
  4269  	}
  4270  }
  4271  
  4272  func (s *DockerSuite) TestBuildBuildTimeArgHistory(c *check.C) {
  4273  	imgName := "bldargtest"
  4274  	envKey := "foo"
  4275  	envVal := "bar"
  4276  	envDef := "bar1"
  4277  	dockerfile := fmt.Sprintf(`FROM busybox
  4278  		ARG %s=%s`, envKey, envDef)
  4279  	buildImage(imgName,
  4280  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4281  		withDockerfile(dockerfile),
  4282  	).Assert(c, icmd.Expected{
  4283  		Out: envVal,
  4284  	})
  4285  
  4286  	out, _ := dockerCmd(c, "history", "--no-trunc", imgName)
  4287  	outputTabs := strings.Split(out, "\n")[1]
  4288  	if !strings.Contains(outputTabs, envDef) {
  4289  		c.Fatalf("failed to find arg default in image history output: %q expected: %q", outputTabs, envDef)
  4290  	}
  4291  }
  4292  
  4293  func (s *DockerSuite) TestBuildBuildTimeArgCacheHit(c *check.C) {
  4294  	imgName := "bldargtest"
  4295  	envKey := "foo"
  4296  	envVal := "bar"
  4297  	dockerfile := fmt.Sprintf(`FROM busybox
  4298  		ARG %s
  4299  		RUN echo $%s`, envKey, envKey)
  4300  	buildImageSuccessfully(c, imgName,
  4301  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4302  		withDockerfile(dockerfile),
  4303  	)
  4304  	origImgID := getIDByName(c, imgName)
  4305  
  4306  	imgNameCache := "bldargtestcachehit"
  4307  	buildImageSuccessfully(c, imgNameCache,
  4308  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4309  		withDockerfile(dockerfile),
  4310  	)
  4311  	newImgID := getIDByName(c, imgName)
  4312  	if newImgID != origImgID {
  4313  		c.Fatalf("build didn't use cache! expected image id: %q built image id: %q", origImgID, newImgID)
  4314  	}
  4315  }
  4316  
  4317  func (s *DockerSuite) TestBuildBuildTimeArgCacheMissExtraArg(c *check.C) {
  4318  	imgName := "bldargtest"
  4319  	envKey := "foo"
  4320  	envVal := "bar"
  4321  	extraEnvKey := "foo1"
  4322  	extraEnvVal := "bar1"
  4323  	dockerfile := fmt.Sprintf(`FROM busybox
  4324  		ARG %s
  4325  		ARG %s
  4326  		RUN echo $%s`, envKey, extraEnvKey, envKey)
  4327  	buildImageSuccessfully(c, imgName,
  4328  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4329  		withDockerfile(dockerfile),
  4330  	)
  4331  	origImgID := getIDByName(c, imgName)
  4332  
  4333  	imgNameCache := "bldargtestcachemiss"
  4334  	buildImageSuccessfully(c, imgNameCache,
  4335  		withBuildFlags(
  4336  			"--build-arg", fmt.Sprintf("%s=%s", envKey, envVal),
  4337  			"--build-arg", fmt.Sprintf("%s=%s", extraEnvKey, extraEnvVal),
  4338  		),
  4339  		withDockerfile(dockerfile),
  4340  	)
  4341  	newImgID := getIDByName(c, imgNameCache)
  4342  
  4343  	if newImgID == origImgID {
  4344  		c.Fatalf("build used cache, expected a miss!")
  4345  	}
  4346  }
  4347  
  4348  func (s *DockerSuite) TestBuildBuildTimeArgCacheMissSameArgDiffVal(c *check.C) {
  4349  	imgName := "bldargtest"
  4350  	envKey := "foo"
  4351  	envVal := "bar"
  4352  	newEnvVal := "bar1"
  4353  	dockerfile := fmt.Sprintf(`FROM busybox
  4354  		ARG %s
  4355  		RUN echo $%s`, envKey, envKey)
  4356  	buildImageSuccessfully(c, imgName,
  4357  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4358  		withDockerfile(dockerfile),
  4359  	)
  4360  	origImgID := getIDByName(c, imgName)
  4361  
  4362  	imgNameCache := "bldargtestcachemiss"
  4363  	buildImageSuccessfully(c, imgNameCache,
  4364  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, newEnvVal)),
  4365  		withDockerfile(dockerfile),
  4366  	)
  4367  	newImgID := getIDByName(c, imgNameCache)
  4368  	if newImgID == origImgID {
  4369  		c.Fatalf("build used cache, expected a miss!")
  4370  	}
  4371  }
  4372  
  4373  func (s *DockerSuite) TestBuildBuildTimeArgOverrideArgDefinedBeforeEnv(c *check.C) {
  4374  	testRequires(c, DaemonIsLinux) // Windows does not support ARG
  4375  	imgName := "bldargtest"
  4376  	envKey := "foo"
  4377  	envVal := "bar"
  4378  	envValOveride := "barOverride"
  4379  	dockerfile := fmt.Sprintf(`FROM busybox
  4380  		ARG %s
  4381  		ENV %s %s
  4382  		RUN echo $%s
  4383  		CMD echo $%s
  4384          `, envKey, envKey, envValOveride, envKey, envKey)
  4385  
  4386  	result := buildImage(imgName,
  4387  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4388  		withDockerfile(dockerfile),
  4389  	)
  4390  	result.Assert(c, icmd.Success)
  4391  	if strings.Count(result.Combined(), envValOveride) != 2 {
  4392  		c.Fatalf("failed to access environment variable in output: %q expected: %q", result.Combined(), envValOveride)
  4393  	}
  4394  
  4395  	containerName := "bldargCont"
  4396  	if out, _ := dockerCmd(c, "run", "--name", containerName, imgName); !strings.Contains(out, envValOveride) {
  4397  		c.Fatalf("run produced invalid output: %q, expected %q", out, envValOveride)
  4398  	}
  4399  }
  4400  
  4401  // FIXME(vdemeester) might be useful to merge with the one above ?
  4402  func (s *DockerSuite) TestBuildBuildTimeArgOverrideEnvDefinedBeforeArg(c *check.C) {
  4403  	testRequires(c, DaemonIsLinux) // Windows does not support ARG
  4404  	imgName := "bldargtest"
  4405  	envKey := "foo"
  4406  	envVal := "bar"
  4407  	envValOveride := "barOverride"
  4408  	dockerfile := fmt.Sprintf(`FROM busybox
  4409  		ENV %s %s
  4410  		ARG %s
  4411  		RUN echo $%s
  4412  		CMD echo $%s
  4413          `, envKey, envValOveride, envKey, envKey, envKey)
  4414  	result := buildImage(imgName,
  4415  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4416  		withDockerfile(dockerfile),
  4417  	)
  4418  	result.Assert(c, icmd.Success)
  4419  	if strings.Count(result.Combined(), envValOveride) != 2 {
  4420  		c.Fatalf("failed to access environment variable in output: %q expected: %q", result.Combined(), envValOveride)
  4421  	}
  4422  
  4423  	containerName := "bldargCont"
  4424  	if out, _ := dockerCmd(c, "run", "--name", containerName, imgName); !strings.Contains(out, envValOveride) {
  4425  		c.Fatalf("run produced invalid output: %q, expected %q", out, envValOveride)
  4426  	}
  4427  }
  4428  
  4429  func (s *DockerSuite) TestBuildBuildTimeArgExpansion(c *check.C) {
  4430  	testRequires(c, DaemonIsLinux) // Windows does not support ARG
  4431  	imgName := "bldvarstest"
  4432  
  4433  	wdVar := "WDIR"
  4434  	wdVal := "/tmp/"
  4435  	addVar := "AFILE"
  4436  	addVal := "addFile"
  4437  	copyVar := "CFILE"
  4438  	copyVal := "copyFile"
  4439  	envVar := "foo"
  4440  	envVal := "bar"
  4441  	exposeVar := "EPORT"
  4442  	exposeVal := "9999"
  4443  	userVar := "USER"
  4444  	userVal := "testUser"
  4445  	volVar := "VOL"
  4446  	volVal := "/testVol/"
  4447  
  4448  	buildImageSuccessfully(c, imgName,
  4449  		withBuildFlags(
  4450  			"--build-arg", fmt.Sprintf("%s=%s", wdVar, wdVal),
  4451  			"--build-arg", fmt.Sprintf("%s=%s", addVar, addVal),
  4452  			"--build-arg", fmt.Sprintf("%s=%s", copyVar, copyVal),
  4453  			"--build-arg", fmt.Sprintf("%s=%s", envVar, envVal),
  4454  			"--build-arg", fmt.Sprintf("%s=%s", exposeVar, exposeVal),
  4455  			"--build-arg", fmt.Sprintf("%s=%s", userVar, userVal),
  4456  			"--build-arg", fmt.Sprintf("%s=%s", volVar, volVal),
  4457  		),
  4458  		withBuildContext(c,
  4459  			withFile("Dockerfile", fmt.Sprintf(`FROM busybox
  4460  		ARG %s
  4461  		WORKDIR ${%s}
  4462  		ARG %s
  4463  		ADD ${%s} testDir/
  4464  		ARG %s
  4465  		COPY $%s testDir/
  4466  		ARG %s
  4467  		ENV %s=${%s}
  4468  		ARG %s
  4469  		EXPOSE $%s
  4470  		ARG %s
  4471  		USER $%s
  4472  		ARG %s
  4473  		VOLUME ${%s}`,
  4474  				wdVar, wdVar, addVar, addVar, copyVar, copyVar, envVar, envVar,
  4475  				envVar, exposeVar, exposeVar, userVar, userVar, volVar, volVar)),
  4476  			withFile(addVal, "some stuff"),
  4477  			withFile(copyVal, "some stuff"),
  4478  		),
  4479  	)
  4480  
  4481  	res := inspectField(c, imgName, "Config.WorkingDir")
  4482  	if res != filepath.ToSlash(filepath.Clean(wdVal)) {
  4483  		c.Fatalf("Config.WorkingDir value mismatch. Expected: %s, got: %s", filepath.ToSlash(filepath.Clean(wdVal)), res)
  4484  	}
  4485  
  4486  	var resArr []string
  4487  	inspectFieldAndUnmarshall(c, imgName, "Config.Env", &resArr)
  4488  
  4489  	found := false
  4490  	for _, v := range resArr {
  4491  		if fmt.Sprintf("%s=%s", envVar, envVal) == v {
  4492  			found = true
  4493  			break
  4494  		}
  4495  	}
  4496  	if !found {
  4497  		c.Fatalf("Config.Env value mismatch. Expected <key=value> to exist: %s=%s, got: %v",
  4498  			envVar, envVal, resArr)
  4499  	}
  4500  
  4501  	var resMap map[string]interface{}
  4502  	inspectFieldAndUnmarshall(c, imgName, "Config.ExposedPorts", &resMap)
  4503  	if _, ok := resMap[fmt.Sprintf("%s/tcp", exposeVal)]; !ok {
  4504  		c.Fatalf("Config.ExposedPorts value mismatch. Expected exposed port: %s/tcp, got: %v", exposeVal, resMap)
  4505  	}
  4506  
  4507  	res = inspectField(c, imgName, "Config.User")
  4508  	if res != userVal {
  4509  		c.Fatalf("Config.User value mismatch. Expected: %s, got: %s", userVal, res)
  4510  	}
  4511  
  4512  	inspectFieldAndUnmarshall(c, imgName, "Config.Volumes", &resMap)
  4513  	if _, ok := resMap[volVal]; !ok {
  4514  		c.Fatalf("Config.Volumes value mismatch. Expected volume: %s, got: %v", volVal, resMap)
  4515  	}
  4516  }
  4517  
  4518  func (s *DockerSuite) TestBuildBuildTimeArgExpansionOverride(c *check.C) {
  4519  	testRequires(c, DaemonIsLinux) // Windows does not support ARG
  4520  	imgName := "bldvarstest"
  4521  	envKey := "foo"
  4522  	envVal := "bar"
  4523  	envKey1 := "foo1"
  4524  	envValOveride := "barOverride"
  4525  	dockerfile := fmt.Sprintf(`FROM busybox
  4526  		ARG %s
  4527  		ENV %s %s
  4528  		ENV %s ${%s}
  4529  		RUN echo $%s
  4530  		CMD echo $%s`, envKey, envKey, envValOveride, envKey1, envKey, envKey1, envKey1)
  4531  	result := buildImage(imgName,
  4532  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4533  		withDockerfile(dockerfile),
  4534  	)
  4535  	result.Assert(c, icmd.Success)
  4536  	if strings.Count(result.Combined(), envValOveride) != 2 {
  4537  		c.Fatalf("failed to access environment variable in output: %q expected: %q", result.Combined(), envValOveride)
  4538  	}
  4539  
  4540  	containerName := "bldargCont"
  4541  	if out, _ := dockerCmd(c, "run", "--name", containerName, imgName); !strings.Contains(out, envValOveride) {
  4542  		c.Fatalf("run produced invalid output: %q, expected %q", out, envValOveride)
  4543  	}
  4544  }
  4545  
  4546  func (s *DockerSuite) TestBuildBuildTimeArgUntrustedDefinedAfterUse(c *check.C) {
  4547  	testRequires(c, DaemonIsLinux) // Windows does not support ARG
  4548  	imgName := "bldargtest"
  4549  	envKey := "foo"
  4550  	envVal := "bar"
  4551  	dockerfile := fmt.Sprintf(`FROM busybox
  4552  		RUN echo $%s
  4553  		ARG %s
  4554  		CMD echo $%s`, envKey, envKey, envKey)
  4555  	result := buildImage(imgName,
  4556  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4557  		withDockerfile(dockerfile),
  4558  	)
  4559  	result.Assert(c, icmd.Success)
  4560  	if strings.Contains(result.Combined(), envVal) {
  4561  		c.Fatalf("able to access environment variable in output: %q expected to be missing", result.Combined())
  4562  	}
  4563  
  4564  	containerName := "bldargCont"
  4565  	if out, _ := dockerCmd(c, "run", "--name", containerName, imgName); out != "\n" {
  4566  		c.Fatalf("run produced invalid output: %q, expected empty string", out)
  4567  	}
  4568  }
  4569  
  4570  func (s *DockerSuite) TestBuildBuildTimeArgBuiltinArg(c *check.C) {
  4571  	testRequires(c, DaemonIsLinux) // Windows does not support --build-arg
  4572  	imgName := "bldargtest"
  4573  	envKey := "HTTP_PROXY"
  4574  	envVal := "bar"
  4575  	dockerfile := fmt.Sprintf(`FROM busybox
  4576  		RUN echo $%s
  4577  		CMD echo $%s`, envKey, envKey)
  4578  
  4579  	result := buildImage(imgName,
  4580  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4581  		withDockerfile(dockerfile),
  4582  	)
  4583  	result.Assert(c, icmd.Success)
  4584  	if !strings.Contains(result.Combined(), envVal) {
  4585  		c.Fatalf("failed to access environment variable in output: %q expected: %q", result.Combined(), envVal)
  4586  	}
  4587  	containerName := "bldargCont"
  4588  	if out, _ := dockerCmd(c, "run", "--name", containerName, imgName); out != "\n" {
  4589  		c.Fatalf("run produced invalid output: %q, expected empty string", out)
  4590  	}
  4591  }
  4592  
  4593  func (s *DockerSuite) TestBuildBuildTimeArgDefaultOverride(c *check.C) {
  4594  	testRequires(c, DaemonIsLinux) // Windows does not support ARG
  4595  	imgName := "bldargtest"
  4596  	envKey := "foo"
  4597  	envVal := "bar"
  4598  	envValOveride := "barOverride"
  4599  	dockerfile := fmt.Sprintf(`FROM busybox
  4600  		ARG %s=%s
  4601  		ENV %s $%s
  4602  		RUN echo $%s
  4603  		CMD echo $%s`, envKey, envVal, envKey, envKey, envKey, envKey)
  4604  	result := buildImage(imgName,
  4605  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envValOveride)),
  4606  		withDockerfile(dockerfile),
  4607  	)
  4608  	result.Assert(c, icmd.Success)
  4609  	if strings.Count(result.Combined(), envValOveride) != 1 {
  4610  		c.Fatalf("failed to access environment variable in output: %q expected: %q", result.Combined(), envValOveride)
  4611  	}
  4612  
  4613  	containerName := "bldargCont"
  4614  	if out, _ := dockerCmd(c, "run", "--name", containerName, imgName); !strings.Contains(out, envValOveride) {
  4615  		c.Fatalf("run produced invalid output: %q, expected %q", out, envValOveride)
  4616  	}
  4617  }
  4618  
  4619  func (s *DockerSuite) TestBuildBuildTimeArgUnconsumedArg(c *check.C) {
  4620  	imgName := "bldargtest"
  4621  	envKey := "foo"
  4622  	envVal := "bar"
  4623  	dockerfile := fmt.Sprintf(`FROM busybox
  4624  		RUN echo $%s
  4625  		CMD echo $%s`, envKey, envKey)
  4626  	warnStr := "[Warning] One or more build-args"
  4627  	buildImage(imgName,
  4628  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4629  		withDockerfile(dockerfile),
  4630  	).Assert(c, icmd.Expected{
  4631  		Out: warnStr,
  4632  	})
  4633  }
  4634  
  4635  func (s *DockerSuite) TestBuildBuildTimeArgEnv(c *check.C) {
  4636  	testRequires(c, DaemonIsLinux) // Windows does not support ARG
  4637  	dockerfile := `FROM busybox
  4638  		ARG FOO1=fromfile
  4639  		ARG FOO2=fromfile
  4640  		ARG FOO3=fromfile
  4641  		ARG FOO4=fromfile
  4642  		ARG FOO5
  4643  		ARG FOO6
  4644  		RUN env
  4645  		RUN [ "$FOO1" == "fromcmd" ]
  4646  		RUN [ "$FOO2" == "" ]
  4647  		RUN [ "$FOO3" == "fromenv" ]
  4648  		RUN [ "$FOO4" == "fromfile" ]
  4649  		RUN [ "$FOO5" == "fromcmd" ]
  4650  		# The following should not exist at all in the env
  4651  		RUN [ "$(env | grep FOO6)" == "" ]
  4652  		RUN [ "$(env | grep FOO7)" == "" ]
  4653  		RUN [ "$(env | grep FOO8)" == "" ]
  4654  		RUN [ "$(env | grep FOO9)" == "" ]
  4655  	    `
  4656  	result := buildImage("testbuildtimeargenv",
  4657  		withBuildFlags(
  4658  			"--build-arg", fmt.Sprintf("FOO1=fromcmd"),
  4659  			"--build-arg", fmt.Sprintf("FOO2="),
  4660  			"--build-arg", fmt.Sprintf("FOO3"), // set in env
  4661  			"--build-arg", fmt.Sprintf("FOO4"), // not set in env
  4662  			"--build-arg", fmt.Sprintf("FOO5=fromcmd"),
  4663  			// FOO6 is not set at all
  4664  			"--build-arg", fmt.Sprintf("FOO7=fromcmd"), // should produce a warning
  4665  			"--build-arg", fmt.Sprintf("FOO8="), // should produce a warning
  4666  			"--build-arg", fmt.Sprintf("FOO9"), // should produce a warning
  4667  		),
  4668  		withEnvironmentVariales(append(os.Environ(),
  4669  			"FOO1=fromenv",
  4670  			"FOO2=fromenv",
  4671  			"FOO3=fromenv")...),
  4672  		withBuildContext(c,
  4673  			withFile("Dockerfile", dockerfile),
  4674  		),
  4675  	)
  4676  	result.Assert(c, icmd.Success)
  4677  
  4678  	// Now check to make sure we got a warning msg about unused build-args
  4679  	i := strings.Index(result.Combined(), "[Warning]")
  4680  	if i < 0 {
  4681  		c.Fatalf("Missing the build-arg warning in %q", result.Combined())
  4682  	}
  4683  
  4684  	out := result.Combined()[i:] // "out" should contain just the warning message now
  4685  
  4686  	// These were specified on a --build-arg but no ARG was in the Dockerfile
  4687  	c.Assert(out, checker.Contains, "FOO7")
  4688  	c.Assert(out, checker.Contains, "FOO8")
  4689  	c.Assert(out, checker.Contains, "FOO9")
  4690  }
  4691  
  4692  func (s *DockerSuite) TestBuildBuildTimeArgQuotedValVariants(c *check.C) {
  4693  	imgName := "bldargtest"
  4694  	envKey := "foo"
  4695  	envKey1 := "foo1"
  4696  	envKey2 := "foo2"
  4697  	envKey3 := "foo3"
  4698  	dockerfile := fmt.Sprintf(`FROM busybox
  4699  		ARG %s=""
  4700  		ARG %s=''
  4701  		ARG %s="''"
  4702  		ARG %s='""'
  4703  		RUN [ "$%s" != "$%s" ]
  4704  		RUN [ "$%s" != "$%s" ]
  4705  		RUN [ "$%s" != "$%s" ]
  4706  		RUN [ "$%s" != "$%s" ]
  4707  		RUN [ "$%s" != "$%s" ]`, envKey, envKey1, envKey2, envKey3,
  4708  		envKey, envKey2, envKey, envKey3, envKey1, envKey2, envKey1, envKey3,
  4709  		envKey2, envKey3)
  4710  	buildImageSuccessfully(c, imgName, withDockerfile(dockerfile))
  4711  }
  4712  
  4713  func (s *DockerSuite) TestBuildBuildTimeArgEmptyValVariants(c *check.C) {
  4714  	testRequires(c, DaemonIsLinux) // Windows does not support ARG
  4715  	imgName := "bldargtest"
  4716  	envKey := "foo"
  4717  	envKey1 := "foo1"
  4718  	envKey2 := "foo2"
  4719  	dockerfile := fmt.Sprintf(`FROM busybox
  4720  		ARG %s=
  4721  		ARG %s=""
  4722  		ARG %s=''
  4723  		RUN [ "$%s" == "$%s" ]
  4724  		RUN [ "$%s" == "$%s" ]
  4725  		RUN [ "$%s" == "$%s" ]`, envKey, envKey1, envKey2, envKey, envKey1, envKey1, envKey2, envKey, envKey2)
  4726  	buildImageSuccessfully(c, imgName, withDockerfile(dockerfile))
  4727  }
  4728  
  4729  func (s *DockerSuite) TestBuildBuildTimeArgDefintionWithNoEnvInjection(c *check.C) {
  4730  	imgName := "bldargtest"
  4731  	envKey := "foo"
  4732  	dockerfile := fmt.Sprintf(`FROM busybox
  4733  		ARG %s
  4734  		RUN env`, envKey)
  4735  
  4736  	result := buildImage(imgName, withDockerfile(dockerfile))
  4737  	result.Assert(c, icmd.Success)
  4738  	if strings.Count(result.Combined(), envKey) != 1 {
  4739  		c.Fatalf("unexpected number of occurrences of the arg in output: %q expected: 1", result.Combined())
  4740  	}
  4741  }
  4742  
  4743  func (s *DockerSuite) TestBuildNoNamedVolume(c *check.C) {
  4744  	volName := "testname:/foo"
  4745  
  4746  	if testEnv.DaemonPlatform() == "windows" {
  4747  		volName = "testname:C:\\foo"
  4748  	}
  4749  	dockerCmd(c, "run", "-v", volName, "busybox", "sh", "-c", "touch /foo/oops")
  4750  
  4751  	dockerFile := `FROM busybox
  4752  	VOLUME ` + volName + `
  4753  	RUN ls /foo/oops
  4754  	`
  4755  	buildImage("test", withDockerfile(dockerFile)).Assert(c, icmd.Expected{
  4756  		ExitCode: 1,
  4757  	})
  4758  }
  4759  
  4760  func (s *DockerSuite) TestBuildTagEvent(c *check.C) {
  4761  	since := daemonUnixTime(c)
  4762  
  4763  	dockerFile := `FROM busybox
  4764  	RUN echo events
  4765  	`
  4766  	buildImageSuccessfully(c, "test", withDockerfile(dockerFile))
  4767  
  4768  	until := daemonUnixTime(c)
  4769  	out, _ := dockerCmd(c, "events", "--since", since, "--until", until, "--filter", "type=image")
  4770  	events := strings.Split(strings.TrimSpace(out), "\n")
  4771  	actions := eventActionsByIDAndType(c, events, "test:latest", "image")
  4772  	var foundTag bool
  4773  	for _, a := range actions {
  4774  		if a == "tag" {
  4775  			foundTag = true
  4776  			break
  4777  		}
  4778  	}
  4779  
  4780  	c.Assert(foundTag, checker.True, check.Commentf("No tag event found:\n%s", out))
  4781  }
  4782  
  4783  // #15780
  4784  func (s *DockerSuite) TestBuildMultipleTags(c *check.C) {
  4785  	dockerfile := `
  4786  	FROM busybox
  4787  	MAINTAINER test-15780
  4788  	`
  4789  	buildImageSuccessfully(c, "tag1", withBuildFlags("-t", "tag2:v2", "-t", "tag1:latest", "-t", "tag1"), withDockerfile(dockerfile))
  4790  
  4791  	id1 := getIDByName(c, "tag1")
  4792  	id2 := getIDByName(c, "tag2:v2")
  4793  	c.Assert(id1, check.Equals, id2)
  4794  }
  4795  
  4796  // #17290
  4797  func (s *DockerSuite) TestBuildCacheBrokenSymlink(c *check.C) {
  4798  	name := "testbuildbrokensymlink"
  4799  	ctx := fakeContext(c, `
  4800  	FROM busybox
  4801  	COPY . ./`,
  4802  		map[string]string{
  4803  			"foo": "bar",
  4804  		})
  4805  	defer ctx.Close()
  4806  
  4807  	err := os.Symlink(filepath.Join(ctx.Dir, "nosuchfile"), filepath.Join(ctx.Dir, "asymlink"))
  4808  	c.Assert(err, checker.IsNil)
  4809  
  4810  	// warm up cache
  4811  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  4812  
  4813  	// add new file to context, should invalidate cache
  4814  	err = ioutil.WriteFile(filepath.Join(ctx.Dir, "newfile"), []byte("foo"), 0644)
  4815  	c.Assert(err, checker.IsNil)
  4816  
  4817  	result := buildImage(name, withExternalBuildContext(ctx))
  4818  	result.Assert(c, icmd.Success)
  4819  	if strings.Contains(result.Combined(), "Using cache") {
  4820  		c.Fatal("2nd build used cache on ADD, it shouldn't")
  4821  	}
  4822  }
  4823  
  4824  func (s *DockerSuite) TestBuildFollowSymlinkToFile(c *check.C) {
  4825  	name := "testbuildbrokensymlink"
  4826  	ctx := fakeContext(c, `
  4827  	FROM busybox
  4828  	COPY asymlink target`,
  4829  		map[string]string{
  4830  			"foo": "bar",
  4831  		})
  4832  	defer ctx.Close()
  4833  
  4834  	err := os.Symlink("foo", filepath.Join(ctx.Dir, "asymlink"))
  4835  	c.Assert(err, checker.IsNil)
  4836  
  4837  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  4838  
  4839  	out, _ := dockerCmd(c, "run", "--rm", name, "cat", "target")
  4840  	c.Assert(out, checker.Matches, "bar")
  4841  
  4842  	// change target file should invalidate cache
  4843  	err = ioutil.WriteFile(filepath.Join(ctx.Dir, "foo"), []byte("baz"), 0644)
  4844  	c.Assert(err, checker.IsNil)
  4845  
  4846  	result := buildImage(name, withExternalBuildContext(ctx))
  4847  	result.Assert(c, icmd.Success)
  4848  	c.Assert(result.Combined(), checker.Not(checker.Contains), "Using cache")
  4849  
  4850  	out, _ = dockerCmd(c, "run", "--rm", name, "cat", "target")
  4851  	c.Assert(out, checker.Matches, "baz")
  4852  }
  4853  
  4854  func (s *DockerSuite) TestBuildFollowSymlinkToDir(c *check.C) {
  4855  	name := "testbuildbrokensymlink"
  4856  	ctx := fakeContext(c, `
  4857  	FROM busybox
  4858  	COPY asymlink /`,
  4859  		map[string]string{
  4860  			"foo/abc": "bar",
  4861  			"foo/def": "baz",
  4862  		})
  4863  	defer ctx.Close()
  4864  
  4865  	err := os.Symlink("foo", filepath.Join(ctx.Dir, "asymlink"))
  4866  	c.Assert(err, checker.IsNil)
  4867  
  4868  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  4869  
  4870  	out, _ := dockerCmd(c, "run", "--rm", name, "cat", "abc", "def")
  4871  	c.Assert(out, checker.Matches, "barbaz")
  4872  
  4873  	// change target file should invalidate cache
  4874  	err = ioutil.WriteFile(filepath.Join(ctx.Dir, "foo/def"), []byte("bax"), 0644)
  4875  	c.Assert(err, checker.IsNil)
  4876  
  4877  	result := buildImage(name, withExternalBuildContext(ctx))
  4878  	result.Assert(c, icmd.Success)
  4879  	c.Assert(result.Combined(), checker.Not(checker.Contains), "Using cache")
  4880  
  4881  	out, _ = dockerCmd(c, "run", "--rm", name, "cat", "abc", "def")
  4882  	c.Assert(out, checker.Matches, "barbax")
  4883  
  4884  }
  4885  
  4886  // TestBuildSymlinkBasename tests that target file gets basename from symlink,
  4887  // not from the target file.
  4888  func (s *DockerSuite) TestBuildSymlinkBasename(c *check.C) {
  4889  	name := "testbuildbrokensymlink"
  4890  	ctx := fakeContext(c, `
  4891  	FROM busybox
  4892  	COPY asymlink /`,
  4893  		map[string]string{
  4894  			"foo": "bar",
  4895  		})
  4896  	defer ctx.Close()
  4897  
  4898  	err := os.Symlink("foo", filepath.Join(ctx.Dir, "asymlink"))
  4899  	c.Assert(err, checker.IsNil)
  4900  
  4901  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  4902  
  4903  	out, _ := dockerCmd(c, "run", "--rm", name, "cat", "asymlink")
  4904  	c.Assert(out, checker.Matches, "bar")
  4905  }
  4906  
  4907  // #17827
  4908  func (s *DockerSuite) TestBuildCacheRootSource(c *check.C) {
  4909  	name := "testbuildrootsource"
  4910  	ctx := fakeContext(c, `
  4911  	FROM busybox
  4912  	COPY / /data`,
  4913  		map[string]string{
  4914  			"foo": "bar",
  4915  		})
  4916  	defer ctx.Close()
  4917  
  4918  	// warm up cache
  4919  	buildImageSuccessfully(c, name, withExternalBuildContext(ctx))
  4920  
  4921  	// change file, should invalidate cache
  4922  	err := ioutil.WriteFile(filepath.Join(ctx.Dir, "foo"), []byte("baz"), 0644)
  4923  	c.Assert(err, checker.IsNil)
  4924  
  4925  	result := buildImage(name, withExternalBuildContext(ctx))
  4926  	result.Assert(c, icmd.Success)
  4927  
  4928  	c.Assert(result.Combined(), checker.Not(checker.Contains), "Using cache")
  4929  }
  4930  
  4931  // #19375
  4932  func (s *DockerSuite) TestBuildFailsGitNotCallable(c *check.C) {
  4933  	buildImage("gitnotcallable", withEnvironmentVariales("PATH="),
  4934  		withBuildContextPath("github.com/docker/v1.10-migrator.git")).Assert(c, icmd.Expected{
  4935  		ExitCode: 1,
  4936  		Err:      "unable to prepare context: unable to find 'git': ",
  4937  	})
  4938  
  4939  	buildImage("gitnotcallable", withEnvironmentVariales("PATH="),
  4940  		withBuildContextPath("https://github.com/docker/v1.10-migrator.git")).Assert(c, icmd.Expected{
  4941  		ExitCode: 1,
  4942  		Err:      "unable to prepare context: unable to find 'git': ",
  4943  	})
  4944  }
  4945  
  4946  // TestBuildWorkdirWindowsPath tests that a Windows style path works as a workdir
  4947  func (s *DockerSuite) TestBuildWorkdirWindowsPath(c *check.C) {
  4948  	testRequires(c, DaemonIsWindows)
  4949  	name := "testbuildworkdirwindowspath"
  4950  	buildImageSuccessfully(c, name, withDockerfile(`
  4951  	FROM `+testEnv.MinimalBaseImage()+`
  4952  	RUN mkdir C:\\work
  4953  	WORKDIR C:\\work
  4954  	RUN if "%CD%" NEQ "C:\work" exit -1
  4955  	`))
  4956  }
  4957  
  4958  func (s *DockerSuite) TestBuildLabel(c *check.C) {
  4959  	name := "testbuildlabel"
  4960  	testLabel := "foo"
  4961  
  4962  	buildImageSuccessfully(c, name, withBuildFlags("--label", testLabel),
  4963  		withDockerfile(`
  4964    FROM `+minimalBaseImage()+`
  4965    LABEL default foo
  4966  `))
  4967  
  4968  	var labels map[string]string
  4969  	inspectFieldAndUnmarshall(c, name, "Config.Labels", &labels)
  4970  	if _, ok := labels[testLabel]; !ok {
  4971  		c.Fatal("label not found in image")
  4972  	}
  4973  }
  4974  
  4975  func (s *DockerSuite) TestBuildLabelOneNode(c *check.C) {
  4976  	name := "testbuildlabel"
  4977  	buildImageSuccessfully(c, name, withBuildFlags("--label", "foo=bar"),
  4978  		withDockerfile("FROM busybox"))
  4979  
  4980  	var labels map[string]string
  4981  	inspectFieldAndUnmarshall(c, name, "Config.Labels", &labels)
  4982  	v, ok := labels["foo"]
  4983  	if !ok {
  4984  		c.Fatal("label `foo` not found in image")
  4985  	}
  4986  	c.Assert(v, checker.Equals, "bar")
  4987  }
  4988  
  4989  func (s *DockerSuite) TestBuildLabelCacheCommit(c *check.C) {
  4990  	name := "testbuildlabelcachecommit"
  4991  	testLabel := "foo"
  4992  
  4993  	buildImageSuccessfully(c, name, withDockerfile(`
  4994    FROM `+minimalBaseImage()+`
  4995    LABEL default foo
  4996    `))
  4997  	buildImageSuccessfully(c, name, withBuildFlags("--label", testLabel),
  4998  		withDockerfile(`
  4999    FROM `+minimalBaseImage()+`
  5000    LABEL default foo
  5001    `))
  5002  
  5003  	var labels map[string]string
  5004  	inspectFieldAndUnmarshall(c, name, "Config.Labels", &labels)
  5005  	if _, ok := labels[testLabel]; !ok {
  5006  		c.Fatal("label not found in image")
  5007  	}
  5008  }
  5009  
  5010  func (s *DockerSuite) TestBuildLabelMultiple(c *check.C) {
  5011  	name := "testbuildlabelmultiple"
  5012  	testLabels := map[string]string{
  5013  		"foo": "bar",
  5014  		"123": "456",
  5015  	}
  5016  	labelArgs := []string{}
  5017  	for k, v := range testLabels {
  5018  		labelArgs = append(labelArgs, "--label", k+"="+v)
  5019  	}
  5020  
  5021  	buildImageSuccessfully(c, name, withBuildFlags(labelArgs...),
  5022  		withDockerfile(`
  5023    FROM `+minimalBaseImage()+`
  5024    LABEL default foo
  5025  `))
  5026  
  5027  	var labels map[string]string
  5028  	inspectFieldAndUnmarshall(c, name, "Config.Labels", &labels)
  5029  	for k, v := range testLabels {
  5030  		if x, ok := labels[k]; !ok || x != v {
  5031  			c.Fatalf("label %s=%s not found in image", k, v)
  5032  		}
  5033  	}
  5034  }
  5035  
  5036  func (s *DockerRegistryAuthHtpasswdSuite) TestBuildFromAuthenticatedRegistry(c *check.C) {
  5037  	dockerCmd(c, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), privateRegistryURL)
  5038  	baseImage := privateRegistryURL + "/baseimage"
  5039  
  5040  	buildImageSuccessfully(c, baseImage, withDockerfile(`
  5041  	FROM busybox
  5042  	ENV env1 val1
  5043  	`))
  5044  
  5045  	dockerCmd(c, "push", baseImage)
  5046  	dockerCmd(c, "rmi", baseImage)
  5047  
  5048  	buildImageSuccessfully(c, baseImage, withDockerfile(fmt.Sprintf(`
  5049  	FROM %s
  5050  	ENV env2 val2
  5051  	`, baseImage)))
  5052  }
  5053  
  5054  func (s *DockerRegistryAuthHtpasswdSuite) TestBuildWithExternalAuth(c *check.C) {
  5055  	osPath := os.Getenv("PATH")
  5056  	defer os.Setenv("PATH", osPath)
  5057  
  5058  	workingDir, err := os.Getwd()
  5059  	c.Assert(err, checker.IsNil)
  5060  	absolute, err := filepath.Abs(filepath.Join(workingDir, "fixtures", "auth"))
  5061  	c.Assert(err, checker.IsNil)
  5062  	testPath := fmt.Sprintf("%s%c%s", osPath, filepath.ListSeparator, absolute)
  5063  
  5064  	os.Setenv("PATH", testPath)
  5065  
  5066  	repoName := fmt.Sprintf("%v/dockercli/busybox:authtest", privateRegistryURL)
  5067  
  5068  	tmp, err := ioutil.TempDir("", "integration-cli-")
  5069  	c.Assert(err, checker.IsNil)
  5070  
  5071  	externalAuthConfig := `{ "credsStore": "shell-test" }`
  5072  
  5073  	configPath := filepath.Join(tmp, "config.json")
  5074  	err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644)
  5075  	c.Assert(err, checker.IsNil)
  5076  
  5077  	dockerCmd(c, "--config", tmp, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), privateRegistryURL)
  5078  
  5079  	b, err := ioutil.ReadFile(configPath)
  5080  	c.Assert(err, checker.IsNil)
  5081  	c.Assert(string(b), checker.Not(checker.Contains), "\"auth\":")
  5082  
  5083  	dockerCmd(c, "--config", tmp, "tag", "busybox", repoName)
  5084  	dockerCmd(c, "--config", tmp, "push", repoName)
  5085  
  5086  	// make sure the image is pulled when building
  5087  	dockerCmd(c, "rmi", repoName)
  5088  
  5089  	icmd.RunCmd(icmd.Cmd{
  5090  		Command: []string{dockerBinary, "--config", tmp, "build", "-"},
  5091  		Stdin:   strings.NewReader(fmt.Sprintf("FROM %s", repoName)),
  5092  	}).Assert(c, icmd.Success)
  5093  }
  5094  
  5095  // Test cases in #22036
  5096  func (s *DockerSuite) TestBuildLabelsOverride(c *check.C) {
  5097  	// Command line option labels will always override
  5098  	name := "scratchy"
  5099  	expected := `{"bar":"from-flag","foo":"from-flag"}`
  5100  	buildImageSuccessfully(c, name, withBuildFlags("--label", "foo=from-flag", "--label", "bar=from-flag"),
  5101  		withDockerfile(`FROM `+minimalBaseImage()+`
  5102                  LABEL foo=from-dockerfile`))
  5103  	res := inspectFieldJSON(c, name, "Config.Labels")
  5104  	if res != expected {
  5105  		c.Fatalf("Labels %s, expected %s", res, expected)
  5106  	}
  5107  
  5108  	name = "from"
  5109  	expected = `{"foo":"from-dockerfile"}`
  5110  	buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+`
  5111                  LABEL foo from-dockerfile`))
  5112  	res = inspectFieldJSON(c, name, "Config.Labels")
  5113  	if res != expected {
  5114  		c.Fatalf("Labels %s, expected %s", res, expected)
  5115  	}
  5116  
  5117  	// Command line option label will override even via `FROM`
  5118  	name = "new"
  5119  	expected = `{"bar":"from-dockerfile2","foo":"new"}`
  5120  	buildImageSuccessfully(c, name, withBuildFlags("--label", "foo=new"),
  5121  		withDockerfile(`FROM from
  5122                  LABEL bar from-dockerfile2`))
  5123  	res = inspectFieldJSON(c, name, "Config.Labels")
  5124  	if res != expected {
  5125  		c.Fatalf("Labels %s, expected %s", res, expected)
  5126  	}
  5127  
  5128  	// Command line option without a value set (--label foo, --label bar=)
  5129  	// will be treated as --label foo="", --label bar=""
  5130  	name = "scratchy2"
  5131  	expected = `{"bar":"","foo":""}`
  5132  	buildImageSuccessfully(c, name, withBuildFlags("--label", "foo", "--label", "bar="),
  5133  		withDockerfile(`FROM `+minimalBaseImage()+`
  5134                  LABEL foo=from-dockerfile`))
  5135  	res = inspectFieldJSON(c, name, "Config.Labels")
  5136  	if res != expected {
  5137  		c.Fatalf("Labels %s, expected %s", res, expected)
  5138  	}
  5139  
  5140  	// Command line option without a value set (--label foo, --label bar=)
  5141  	// will be treated as --label foo="", --label bar=""
  5142  	// This time is for inherited images
  5143  	name = "new2"
  5144  	expected = `{"bar":"","foo":""}`
  5145  	buildImageSuccessfully(c, name, withBuildFlags("--label", "foo=", "--label", "bar"),
  5146  		withDockerfile(`FROM from
  5147                  LABEL bar from-dockerfile2`))
  5148  	res = inspectFieldJSON(c, name, "Config.Labels")
  5149  	if res != expected {
  5150  		c.Fatalf("Labels %s, expected %s", res, expected)
  5151  	}
  5152  
  5153  	// Command line option labels with only `FROM`
  5154  	name = "scratchy"
  5155  	expected = `{"bar":"from-flag","foo":"from-flag"}`
  5156  	buildImageSuccessfully(c, name, withBuildFlags("--label", "foo=from-flag", "--label", "bar=from-flag"),
  5157  		withDockerfile(`FROM `+minimalBaseImage()))
  5158  	res = inspectFieldJSON(c, name, "Config.Labels")
  5159  	if res != expected {
  5160  		c.Fatalf("Labels %s, expected %s", res, expected)
  5161  	}
  5162  
  5163  	// Command line option labels with env var
  5164  	name = "scratchz"
  5165  	expected = `{"bar":"$PATH"}`
  5166  	buildImageSuccessfully(c, name, withBuildFlags("--label", "bar=$PATH"),
  5167  		withDockerfile(`FROM `+minimalBaseImage()))
  5168  	res = inspectFieldJSON(c, name, "Config.Labels")
  5169  	if res != expected {
  5170  		c.Fatalf("Labels %s, expected %s", res, expected)
  5171  	}
  5172  }
  5173  
  5174  // Test case for #22855
  5175  func (s *DockerSuite) TestBuildDeleteCommittedFile(c *check.C) {
  5176  	name := "test-delete-committed-file"
  5177  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  5178  		RUN echo test > file
  5179  		RUN test -e file
  5180  		RUN rm file
  5181  		RUN sh -c "! test -e file"`))
  5182  }
  5183  
  5184  // #20083
  5185  func (s *DockerSuite) TestBuildDockerignoreComment(c *check.C) {
  5186  	// TODO Windows: Figure out why this test is flakey on TP5. If you add
  5187  	// something like RUN sleep 5, or even RUN ls /tmp after the ADD line,
  5188  	// it is more reliable, but that's not a good fix.
  5189  	testRequires(c, DaemonIsLinux)
  5190  
  5191  	name := "testbuilddockerignorecleanpaths"
  5192  	dockerfile := `
  5193          FROM busybox
  5194          ADD . /tmp/
  5195          RUN sh -c "(ls -la /tmp/#1)"
  5196          RUN sh -c "(! ls -la /tmp/#2)"
  5197          RUN sh -c "(! ls /tmp/foo) && (! ls /tmp/foo2) && (ls /tmp/dir1/foo)"`
  5198  	buildImageSuccessfully(c, name, withBuildContext(c,
  5199  		withFile("Dockerfile", dockerfile),
  5200  		withFile("foo", "foo"),
  5201  		withFile("foo2", "foo2"),
  5202  		withFile("dir1/foo", "foo in dir1"),
  5203  		withFile("#1", "# file 1"),
  5204  		withFile("#2", "# file 2"),
  5205  		withFile(".dockerignore", `# Visual C++ cache files
  5206  # because we have git ;-)
  5207  # The above comment is from #20083
  5208  foo
  5209  #dir1/foo
  5210  foo2
  5211  # The following is considered as comment as # is at the beginning
  5212  #1
  5213  # The following is not considered as comment as # is not at the beginning
  5214    #2
  5215  `)))
  5216  }
  5217  
  5218  // Test case for #23221
  5219  func (s *DockerSuite) TestBuildWithUTF8BOM(c *check.C) {
  5220  	name := "test-with-utf8-bom"
  5221  	dockerfile := []byte(`FROM busybox`)
  5222  	bomDockerfile := append([]byte{0xEF, 0xBB, 0xBF}, dockerfile...)
  5223  	buildImageSuccessfully(c, name, withBuildContext(c,
  5224  		withFile("Dockerfile", string(bomDockerfile)),
  5225  	))
  5226  }
  5227  
  5228  // Test case for UTF-8 BOM in .dockerignore, related to #23221
  5229  func (s *DockerSuite) TestBuildWithUTF8BOMDockerignore(c *check.C) {
  5230  	name := "test-with-utf8-bom-dockerignore"
  5231  	dockerfile := `
  5232          FROM busybox
  5233  		ADD . /tmp/
  5234  		RUN ls -la /tmp
  5235  		RUN sh -c "! ls /tmp/Dockerfile"
  5236  		RUN ls /tmp/.dockerignore`
  5237  	dockerignore := []byte("./Dockerfile\n")
  5238  	bomDockerignore := append([]byte{0xEF, 0xBB, 0xBF}, dockerignore...)
  5239  	buildImageSuccessfully(c, name, withBuildContext(c,
  5240  		withFile("Dockerfile", dockerfile),
  5241  		withFile(".dockerignore", string(bomDockerignore)),
  5242  	))
  5243  }
  5244  
  5245  // #22489 Shell test to confirm config gets updated correctly
  5246  func (s *DockerSuite) TestBuildShellUpdatesConfig(c *check.C) {
  5247  	name := "testbuildshellupdatesconfig"
  5248  
  5249  	buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+`
  5250          SHELL ["foo", "-bar"]`))
  5251  	expected := `["foo","-bar","#(nop) ","SHELL [foo -bar]"]`
  5252  	res := inspectFieldJSON(c, name, "ContainerConfig.Cmd")
  5253  	if res != expected {
  5254  		c.Fatalf("%s, expected %s", res, expected)
  5255  	}
  5256  	res = inspectFieldJSON(c, name, "ContainerConfig.Shell")
  5257  	if res != `["foo","-bar"]` {
  5258  		c.Fatalf(`%s, expected ["foo","-bar"]`, res)
  5259  	}
  5260  }
  5261  
  5262  // #22489 Changing the shell multiple times and CMD after.
  5263  func (s *DockerSuite) TestBuildShellMultiple(c *check.C) {
  5264  	name := "testbuildshellmultiple"
  5265  
  5266  	result := buildImage(name, withDockerfile(`FROM busybox
  5267  		RUN echo defaultshell
  5268  		SHELL ["echo"]
  5269  		RUN echoshell
  5270  		SHELL ["ls"]
  5271  		RUN -l
  5272  		CMD -l`))
  5273  	result.Assert(c, icmd.Success)
  5274  
  5275  	// Must contain 'defaultshell' twice
  5276  	if len(strings.Split(result.Combined(), "defaultshell")) != 3 {
  5277  		c.Fatalf("defaultshell should have appeared twice in %s", result.Combined())
  5278  	}
  5279  
  5280  	// Must contain 'echoshell' twice
  5281  	if len(strings.Split(result.Combined(), "echoshell")) != 3 {
  5282  		c.Fatalf("echoshell should have appeared twice in %s", result.Combined())
  5283  	}
  5284  
  5285  	// Must contain "total " (part of ls -l)
  5286  	if !strings.Contains(result.Combined(), "total ") {
  5287  		c.Fatalf("%s should have contained 'total '", result.Combined())
  5288  	}
  5289  
  5290  	// A container started from the image uses the shell-form CMD.
  5291  	// Last shell is ls. CMD is -l. So should contain 'total '.
  5292  	outrun, _ := dockerCmd(c, "run", "--rm", name)
  5293  	if !strings.Contains(outrun, "total ") {
  5294  		c.Fatalf("Expected started container to run ls -l. %s", outrun)
  5295  	}
  5296  }
  5297  
  5298  // #22489. Changed SHELL with ENTRYPOINT
  5299  func (s *DockerSuite) TestBuildShellEntrypoint(c *check.C) {
  5300  	name := "testbuildshellentrypoint"
  5301  
  5302  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  5303  		SHELL ["ls"]
  5304  		ENTRYPOINT -l`))
  5305  	// A container started from the image uses the shell-form ENTRYPOINT.
  5306  	// Shell is ls. ENTRYPOINT is -l. So should contain 'total '.
  5307  	outrun, _ := dockerCmd(c, "run", "--rm", name)
  5308  	if !strings.Contains(outrun, "total ") {
  5309  		c.Fatalf("Expected started container to run ls -l. %s", outrun)
  5310  	}
  5311  }
  5312  
  5313  // #22489 Shell test to confirm shell is inherited in a subsequent build
  5314  func (s *DockerSuite) TestBuildShellInherited(c *check.C) {
  5315  	name1 := "testbuildshellinherited1"
  5316  	buildImageSuccessfully(c, name1, withDockerfile(`FROM busybox
  5317          SHELL ["ls"]`))
  5318  	name2 := "testbuildshellinherited2"
  5319  	buildImage(name2, withDockerfile(`FROM `+name1+`
  5320          RUN -l`)).Assert(c, icmd.Expected{
  5321  		// ls -l has "total " followed by some number in it, ls without -l does not.
  5322  		Out: "total ",
  5323  	})
  5324  }
  5325  
  5326  // #22489 Shell test to confirm non-JSON doesn't work
  5327  func (s *DockerSuite) TestBuildShellNotJSON(c *check.C) {
  5328  	name := "testbuildshellnotjson"
  5329  
  5330  	buildImage(name, withDockerfile(`FROM `+minimalBaseImage()+`
  5331          sHeLl exec -form`, // Casing explicit to ensure error is upper-cased.
  5332  	)).Assert(c, icmd.Expected{
  5333  		ExitCode: 1,
  5334  		Err:      "SHELL requires the arguments to be in JSON form",
  5335  	})
  5336  }
  5337  
  5338  // #22489 Windows shell test to confirm native is powershell if executing a PS command
  5339  // This would error if the default shell were still cmd.
  5340  func (s *DockerSuite) TestBuildShellWindowsPowershell(c *check.C) {
  5341  	testRequires(c, DaemonIsWindows)
  5342  	name := "testbuildshellpowershell"
  5343  	buildImage(name, withDockerfile(`FROM `+minimalBaseImage()+`
  5344          SHELL ["powershell", "-command"]
  5345  		RUN Write-Host John`)).Assert(c, icmd.Expected{
  5346  		Out: "\nJohn\n",
  5347  	})
  5348  }
  5349  
  5350  // Verify that escape is being correctly applied to words when escape directive is not \.
  5351  // Tests WORKDIR, ADD
  5352  func (s *DockerSuite) TestBuildEscapeNotBackslashWordTest(c *check.C) {
  5353  	testRequires(c, DaemonIsWindows)
  5354  	name := "testbuildescapenotbackslashwordtesta"
  5355  	buildImage(name, withDockerfile(`# escape= `+"`"+`
  5356  		FROM `+minimalBaseImage()+`
  5357          WORKDIR c:\windows
  5358  		RUN dir /w`)).Assert(c, icmd.Expected{
  5359  		Out: "[System32]",
  5360  	})
  5361  
  5362  	name = "testbuildescapenotbackslashwordtestb"
  5363  	buildImage(name, withDockerfile(`# escape= `+"`"+`
  5364  		FROM `+minimalBaseImage()+`
  5365  		SHELL ["powershell.exe"]
  5366          WORKDIR c:\foo
  5367  		ADD Dockerfile c:\foo\
  5368  		RUN dir Dockerfile`)).Assert(c, icmd.Expected{
  5369  		Out: "-a----",
  5370  	})
  5371  }
  5372  
  5373  // #22868. Make sure shell-form CMD is marked as escaped in the config of the image
  5374  func (s *DockerSuite) TestBuildCmdShellArgsEscaped(c *check.C) {
  5375  	testRequires(c, DaemonIsWindows)
  5376  	name := "testbuildcmdshellescaped"
  5377  	buildImageSuccessfully(c, name, withDockerfile(`
  5378    FROM `+minimalBaseImage()+`
  5379    CMD "ipconfig"
  5380    `))
  5381  	res := inspectFieldJSON(c, name, "Config.ArgsEscaped")
  5382  	if res != "true" {
  5383  		c.Fatalf("CMD did not update Config.ArgsEscaped on image: %v", res)
  5384  	}
  5385  	dockerCmd(c, "run", "--name", "inspectme", name)
  5386  	dockerCmd(c, "wait", "inspectme")
  5387  	res = inspectFieldJSON(c, name, "Config.Cmd")
  5388  
  5389  	if res != `["cmd","/S","/C","\"ipconfig\""]` {
  5390  		c.Fatalf("CMD was not escaped Config.Cmd: got %v", res)
  5391  	}
  5392  }
  5393  
  5394  // Test case for #24912.
  5395  func (s *DockerSuite) TestBuildStepsWithProgress(c *check.C) {
  5396  	name := "testbuildstepswithprogress"
  5397  	totalRun := 5
  5398  	result := buildImage(name, withDockerfile("FROM busybox\n"+strings.Repeat("RUN echo foo\n", totalRun)))
  5399  	result.Assert(c, icmd.Success)
  5400  	c.Assert(result.Combined(), checker.Contains, fmt.Sprintf("Step 1/%d : FROM busybox", 1+totalRun))
  5401  	for i := 2; i <= 1+totalRun; i++ {
  5402  		c.Assert(result.Combined(), checker.Contains, fmt.Sprintf("Step %d/%d : RUN echo foo", i, 1+totalRun))
  5403  	}
  5404  }
  5405  
  5406  func (s *DockerSuite) TestBuildWithFailure(c *check.C) {
  5407  	name := "testbuildwithfailure"
  5408  
  5409  	// First test case can only detect `nobody` in runtime so all steps will show up
  5410  	dockerfile := "FROM busybox\nRUN nobody"
  5411  	result := buildImage(name, withDockerfile(dockerfile))
  5412  	c.Assert(result.Error, checker.NotNil)
  5413  	c.Assert(result.Stdout(), checker.Contains, "Step 1/2 : FROM busybox")
  5414  	c.Assert(result.Stdout(), checker.Contains, "Step 2/2 : RUN nobody")
  5415  
  5416  	// Second test case `FFOM` should have been detected before build runs so no steps
  5417  	dockerfile = "FFOM nobody\nRUN nobody"
  5418  	result = buildImage(name, withDockerfile(dockerfile))
  5419  	c.Assert(result.Error, checker.NotNil)
  5420  	c.Assert(result.Stdout(), checker.Not(checker.Contains), "Step 1/2 : FROM busybox")
  5421  	c.Assert(result.Stdout(), checker.Not(checker.Contains), "Step 2/2 : RUN nobody")
  5422  }
  5423  
  5424  func (s *DockerSuite) TestBuildCacheFromEqualDiffIDsLength(c *check.C) {
  5425  	dockerfile := `
  5426  		FROM busybox
  5427  		RUN echo "test"
  5428  		ENTRYPOINT ["sh"]`
  5429  	ctx := fakeContext(c, dockerfile, map[string]string{
  5430  		"Dockerfile": dockerfile,
  5431  	})
  5432  	defer ctx.Close()
  5433  
  5434  	buildImageSuccessfully(c, "build1", withExternalBuildContext(ctx))
  5435  	id1 := getIDByName(c, "build1")
  5436  
  5437  	// rebuild with cache-from
  5438  	result := buildImage("build2", withBuildFlags("--cache-from=build1"), withExternalBuildContext(ctx))
  5439  	result.Assert(c, icmd.Success)
  5440  	id2 := getIDByName(c, "build2")
  5441  	c.Assert(id1, checker.Equals, id2)
  5442  	c.Assert(strings.Count(result.Combined(), "Using cache"), checker.Equals, 2)
  5443  }
  5444  
  5445  func (s *DockerSuite) TestBuildCacheFrom(c *check.C) {
  5446  	testRequires(c, DaemonIsLinux) // All tests that do save are skipped in windows
  5447  	dockerfile := `
  5448  		FROM busybox
  5449  		ENV FOO=bar
  5450  		ADD baz /
  5451  		RUN touch bax`
  5452  	ctx := fakeContext(c, dockerfile, map[string]string{
  5453  		"Dockerfile": dockerfile,
  5454  		"baz":        "baz",
  5455  	})
  5456  	defer ctx.Close()
  5457  
  5458  	buildImageSuccessfully(c, "build1", withExternalBuildContext(ctx))
  5459  	id1 := getIDByName(c, "build1")
  5460  
  5461  	// rebuild with cache-from
  5462  	result := buildImage("build2", withBuildFlags("--cache-from=build1"), withExternalBuildContext(ctx))
  5463  	result.Assert(c, icmd.Success)
  5464  	id2 := getIDByName(c, "build2")
  5465  	c.Assert(id1, checker.Equals, id2)
  5466  	c.Assert(strings.Count(result.Combined(), "Using cache"), checker.Equals, 3)
  5467  	dockerCmd(c, "rmi", "build2")
  5468  
  5469  	// no cache match with unknown source
  5470  	result = buildImage("build2", withBuildFlags("--cache-from=nosuchtag"), withExternalBuildContext(ctx))
  5471  	result.Assert(c, icmd.Success)
  5472  	id2 = getIDByName(c, "build2")
  5473  	c.Assert(id1, checker.Not(checker.Equals), id2)
  5474  	c.Assert(strings.Count(result.Combined(), "Using cache"), checker.Equals, 0)
  5475  	dockerCmd(c, "rmi", "build2")
  5476  
  5477  	// clear parent images
  5478  	tempDir, err := ioutil.TempDir("", "test-build-cache-from-")
  5479  	if err != nil {
  5480  		c.Fatalf("failed to create temporary directory: %s", tempDir)
  5481  	}
  5482  	defer os.RemoveAll(tempDir)
  5483  	tempFile := filepath.Join(tempDir, "img.tar")
  5484  	dockerCmd(c, "save", "-o", tempFile, "build1")
  5485  	dockerCmd(c, "rmi", "build1")
  5486  	dockerCmd(c, "load", "-i", tempFile)
  5487  	parentID, _ := dockerCmd(c, "inspect", "-f", "{{.Parent}}", "build1")
  5488  	c.Assert(strings.TrimSpace(parentID), checker.Equals, "")
  5489  
  5490  	// cache still applies without parents
  5491  	result = buildImage("build2", withBuildFlags("--cache-from=build1"), withExternalBuildContext(ctx))
  5492  	result.Assert(c, icmd.Success)
  5493  	id2 = getIDByName(c, "build2")
  5494  	c.Assert(id1, checker.Equals, id2)
  5495  	c.Assert(strings.Count(result.Combined(), "Using cache"), checker.Equals, 3)
  5496  	history1, _ := dockerCmd(c, "history", "-q", "build2")
  5497  
  5498  	// Retry, no new intermediate images
  5499  	result = buildImage("build3", withBuildFlags("--cache-from=build1"), withExternalBuildContext(ctx))
  5500  	result.Assert(c, icmd.Success)
  5501  	id3 := getIDByName(c, "build3")
  5502  	c.Assert(id1, checker.Equals, id3)
  5503  	c.Assert(strings.Count(result.Combined(), "Using cache"), checker.Equals, 3)
  5504  	history2, _ := dockerCmd(c, "history", "-q", "build3")
  5505  
  5506  	c.Assert(history1, checker.Equals, history2)
  5507  	dockerCmd(c, "rmi", "build2")
  5508  	dockerCmd(c, "rmi", "build3")
  5509  	dockerCmd(c, "rmi", "build1")
  5510  	dockerCmd(c, "load", "-i", tempFile)
  5511  
  5512  	// Modify file, everything up to last command and layers are reused
  5513  	dockerfile = `
  5514  		FROM busybox
  5515  		ENV FOO=bar
  5516  		ADD baz /
  5517  		RUN touch newfile`
  5518  	err = ioutil.WriteFile(filepath.Join(ctx.Dir, "Dockerfile"), []byte(dockerfile), 0644)
  5519  	c.Assert(err, checker.IsNil)
  5520  
  5521  	result = buildImage("build2", withBuildFlags("--cache-from=build1"), withExternalBuildContext(ctx))
  5522  	result.Assert(c, icmd.Success)
  5523  	id2 = getIDByName(c, "build2")
  5524  	c.Assert(id1, checker.Not(checker.Equals), id2)
  5525  	c.Assert(strings.Count(result.Combined(), "Using cache"), checker.Equals, 2)
  5526  
  5527  	layers1Str, _ := dockerCmd(c, "inspect", "-f", "{{json .RootFS.Layers}}", "build1")
  5528  	layers2Str, _ := dockerCmd(c, "inspect", "-f", "{{json .RootFS.Layers}}", "build2")
  5529  
  5530  	var layers1 []string
  5531  	var layers2 []string
  5532  	c.Assert(json.Unmarshal([]byte(layers1Str), &layers1), checker.IsNil)
  5533  	c.Assert(json.Unmarshal([]byte(layers2Str), &layers2), checker.IsNil)
  5534  
  5535  	c.Assert(len(layers1), checker.Equals, len(layers2))
  5536  	for i := 0; i < len(layers1)-1; i++ {
  5537  		c.Assert(layers1[i], checker.Equals, layers2[i])
  5538  	}
  5539  	c.Assert(layers1[len(layers1)-1], checker.Not(checker.Equals), layers2[len(layers1)-1])
  5540  }
  5541  
  5542  func (s *DockerSuite) TestBuildNetNone(c *check.C) {
  5543  	testRequires(c, DaemonIsLinux)
  5544  	name := "testbuildnetnone"
  5545  	buildImage(name, withBuildFlags("--network=none"), withDockerfile(`
  5546    FROM busybox
  5547    RUN ping -c 1 8.8.8.8
  5548    `)).Assert(c, icmd.Expected{
  5549  		ExitCode: 1,
  5550  		Out:      "unreachable",
  5551  	})
  5552  }
  5553  
  5554  func (s *DockerSuite) TestBuildNetContainer(c *check.C) {
  5555  	testRequires(c, DaemonIsLinux)
  5556  
  5557  	id, _ := dockerCmd(c, "run", "--hostname", "foobar", "-d", "busybox", "nc", "-ll", "-p", "1234", "-e", "hostname")
  5558  
  5559  	name := "testbuildnetcontainer"
  5560  	buildImageSuccessfully(c, name, withBuildFlags("--network=container:"+strings.TrimSpace(id)),
  5561  		withDockerfile(`
  5562    FROM busybox
  5563    RUN nc localhost 1234 > /otherhost
  5564    `))
  5565  
  5566  	host, _ := dockerCmd(c, "run", "testbuildnetcontainer", "cat", "/otherhost")
  5567  	c.Assert(strings.TrimSpace(host), check.Equals, "foobar")
  5568  }
  5569  
  5570  func (s *DockerSuite) TestBuildSquashParent(c *check.C) {
  5571  	testRequires(c, ExperimentalDaemon)
  5572  	dockerFile := `
  5573  		FROM busybox
  5574  		RUN echo hello > /hello
  5575  		RUN echo world >> /hello
  5576  		RUN echo hello > /remove_me
  5577  		ENV HELLO world
  5578  		RUN rm /remove_me
  5579  		`
  5580  	// build and get the ID that we can use later for history comparison
  5581  	name := "test"
  5582  	buildImageSuccessfully(c, name, withDockerfile(dockerFile))
  5583  	origID := getIDByName(c, name)
  5584  
  5585  	// build with squash
  5586  	buildImageSuccessfully(c, name, withBuildFlags("--squash"), withDockerfile(dockerFile))
  5587  	id := getIDByName(c, name)
  5588  
  5589  	out, _ := dockerCmd(c, "run", "--rm", id, "/bin/sh", "-c", "cat /hello")
  5590  	c.Assert(strings.TrimSpace(out), checker.Equals, "hello\nworld")
  5591  
  5592  	dockerCmd(c, "run", "--rm", id, "/bin/sh", "-c", "[ ! -f /remove_me ]")
  5593  	dockerCmd(c, "run", "--rm", id, "/bin/sh", "-c", `[ "$(echo $HELLO)" == "world" ]`)
  5594  
  5595  	// make sure the ID produced is the ID of the tag we specified
  5596  	inspectID := inspectImage(c, "test", ".ID")
  5597  	c.Assert(inspectID, checker.Equals, id)
  5598  
  5599  	origHistory, _ := dockerCmd(c, "history", origID)
  5600  	testHistory, _ := dockerCmd(c, "history", "test")
  5601  
  5602  	splitOrigHistory := strings.Split(strings.TrimSpace(origHistory), "\n")
  5603  	splitTestHistory := strings.Split(strings.TrimSpace(testHistory), "\n")
  5604  	c.Assert(len(splitTestHistory), checker.Equals, len(splitOrigHistory)+1)
  5605  
  5606  	out = inspectImage(c, id, "len .RootFS.Layers")
  5607  	c.Assert(strings.TrimSpace(out), checker.Equals, "3")
  5608  }
  5609  
  5610  func (s *DockerSuite) TestBuildContChar(c *check.C) {
  5611  	name := "testbuildcontchar"
  5612  
  5613  	buildImage(name, withDockerfile(`FROM busybox\`)).Assert(c, icmd.Expected{
  5614  		Out: "Step 1/1 : FROM busybox",
  5615  	})
  5616  
  5617  	result := buildImage(name, withDockerfile(`FROM busybox
  5618  		 RUN echo hi \`))
  5619  	result.Assert(c, icmd.Success)
  5620  	c.Assert(result.Combined(), checker.Contains, "Step 1/2 : FROM busybox")
  5621  	c.Assert(result.Combined(), checker.Contains, "Step 2/2 : RUN echo hi\n")
  5622  
  5623  	result = buildImage(name, withDockerfile(`FROM busybox
  5624  		 RUN echo hi \\`))
  5625  	result.Assert(c, icmd.Success)
  5626  	c.Assert(result.Combined(), checker.Contains, "Step 1/2 : FROM busybox")
  5627  	c.Assert(result.Combined(), checker.Contains, "Step 2/2 : RUN echo hi \\\n")
  5628  
  5629  	result = buildImage(name, withDockerfile(`FROM busybox
  5630  		 RUN echo hi \\\`))
  5631  	result.Assert(c, icmd.Success)
  5632  	c.Assert(result.Combined(), checker.Contains, "Step 1/2 : FROM busybox")
  5633  	c.Assert(result.Combined(), checker.Contains, "Step 2/2 : RUN echo hi \\\\\n")
  5634  }
  5635  
  5636  // TestBuildOpaqueDirectory tests that a build succeeds which
  5637  // creates opaque directories.
  5638  // See https://github.com/docker/docker/issues/25244
  5639  func (s *DockerSuite) TestBuildOpaqueDirectory(c *check.C) {
  5640  	testRequires(c, DaemonIsLinux)
  5641  	dockerFile := `
  5642  		FROM busybox
  5643  		RUN mkdir /dir1 && touch /dir1/f1
  5644  		RUN rm -rf /dir1 && mkdir /dir1 && touch /dir1/f2
  5645  		RUN touch /dir1/f3
  5646  		RUN [ -f /dir1/f2 ]
  5647  		`
  5648  	// Test that build succeeds, last command fails if opaque directory
  5649  	// was not handled correctly
  5650  	buildImageSuccessfully(c, "testopaquedirectory", withDockerfile(dockerFile))
  5651  }
  5652  
  5653  // Windows test for USER in dockerfile
  5654  func (s *DockerSuite) TestBuildWindowsUser(c *check.C) {
  5655  	testRequires(c, DaemonIsWindows)
  5656  	name := "testbuildwindowsuser"
  5657  	buildImage(name, withDockerfile(`FROM `+testEnv.MinimalBaseImage()+`
  5658  		RUN net user user /add
  5659  		USER user
  5660  		RUN set username
  5661  		`)).Assert(c, icmd.Expected{
  5662  		Out: "USERNAME=user",
  5663  	})
  5664  }
  5665  
  5666  // Verifies if COPY file . when WORKDIR is set to a non-existing directory,
  5667  // the directory is created and the file is copied into the directory,
  5668  // as opposed to the file being copied as a file with the name of the
  5669  // directory. Fix for 27545 (found on Windows, but regression good for Linux too).
  5670  // Note 27545 was reverted in 28505, but a new fix was added subsequently in 28514.
  5671  func (s *DockerSuite) TestBuildCopyFileDotWithWorkdir(c *check.C) {
  5672  	name := "testbuildcopyfiledotwithworkdir"
  5673  	buildImageSuccessfully(c, name, withBuildContext(c,
  5674  		withFile("Dockerfile", `FROM busybox
  5675  WORKDIR /foo
  5676  COPY file .
  5677  RUN ["cat", "/foo/file"]
  5678  `),
  5679  		withFile("file", "content"),
  5680  	))
  5681  }
  5682  
  5683  // Case-insensitive environment variables on Windows
  5684  func (s *DockerSuite) TestBuildWindowsEnvCaseInsensitive(c *check.C) {
  5685  	testRequires(c, DaemonIsWindows)
  5686  	name := "testbuildwindowsenvcaseinsensitive"
  5687  	buildImageSuccessfully(c, name, withDockerfile(`
  5688  		FROM `+testEnv.MinimalBaseImage()+`
  5689  		ENV FOO=bar foo=baz
  5690    `))
  5691  	res := inspectFieldJSON(c, name, "Config.Env")
  5692  	if res != `["foo=baz"]` { // Should not have FOO=bar in it - takes the last one processed. And only one entry as deduped.
  5693  		c.Fatalf("Case insensitive environment variables on Windows failed. Got %s", res)
  5694  	}
  5695  }
  5696  
  5697  // Test case for 29667
  5698  func (s *DockerSuite) TestBuildWorkdirImageCmd(c *check.C) {
  5699  	image := "testworkdirimagecmd"
  5700  	buildImageSuccessfully(c, image, withDockerfile(`
  5701  FROM busybox
  5702  WORKDIR /foo/bar
  5703  `))
  5704  	out, _ := dockerCmd(c, "inspect", "--format", "{{ json .Config.Cmd }}", image)
  5705  
  5706  	// The Windows busybox image has a blank `cmd`
  5707  	lookingFor := `["sh"]`
  5708  	if testEnv.DaemonPlatform() == "windows" {
  5709  		lookingFor = "null"
  5710  	}
  5711  	c.Assert(strings.TrimSpace(out), checker.Equals, lookingFor)
  5712  
  5713  	image = "testworkdirlabelimagecmd"
  5714  	buildImageSuccessfully(c, image, withDockerfile(`
  5715  FROM busybox
  5716  WORKDIR /foo/bar
  5717  LABEL a=b
  5718  `))
  5719  
  5720  	out, _ = dockerCmd(c, "inspect", "--format", "{{ json .Config.Cmd }}", image)
  5721  	c.Assert(strings.TrimSpace(out), checker.Equals, lookingFor)
  5722  }
  5723  
  5724  // Test case for 28902/28909
  5725  func (s *DockerSuite) TestBuildWorkdirCmd(c *check.C) {
  5726  	testRequires(c, DaemonIsLinux)
  5727  	name := "testbuildworkdircmd"
  5728  	dockerFile := `
  5729                  FROM busybox
  5730                  WORKDIR /
  5731                  `
  5732  	buildImageSuccessfully(c, name, withDockerfile(dockerFile))
  5733  	result := buildImage(name, withDockerfile(dockerFile))
  5734  	result.Assert(c, icmd.Success)
  5735  	c.Assert(strings.Count(result.Combined(), "Using cache"), checker.Equals, 1)
  5736  }
  5737  
  5738  // FIXME(vdemeester) should be a unit test
  5739  func (s *DockerSuite) TestBuildLineErrorOnBuild(c *check.C) {
  5740  	name := "test_build_line_error_onbuild"
  5741  	buildImage(name, withDockerfile(`FROM busybox
  5742    ONBUILD
  5743    `)).Assert(c, icmd.Expected{
  5744  		ExitCode: 1,
  5745  		Err:      "Dockerfile parse error line 2: ONBUILD requires at least one argument",
  5746  	})
  5747  }
  5748  
  5749  // FIXME(vdemeester) should be a unit test
  5750  func (s *DockerSuite) TestBuildLineErrorUknownInstruction(c *check.C) {
  5751  	name := "test_build_line_error_unknown_instruction"
  5752  	buildImage(name, withDockerfile(`FROM busybox
  5753    RUN echo hello world
  5754    NOINSTRUCTION echo ba
  5755    RUN echo hello
  5756    ERROR
  5757    `)).Assert(c, icmd.Expected{
  5758  		ExitCode: 1,
  5759  		Err:      "Dockerfile parse error line 3: Unknown instruction: NOINSTRUCTION",
  5760  	})
  5761  }
  5762  
  5763  // FIXME(vdemeester) should be a unit test
  5764  func (s *DockerSuite) TestBuildLineErrorWithEmptyLines(c *check.C) {
  5765  	name := "test_build_line_error_with_empty_lines"
  5766  	buildImage(name, withDockerfile(`
  5767    FROM busybox
  5768  
  5769    RUN echo hello world
  5770  
  5771    NOINSTRUCTION echo ba
  5772  
  5773    CMD ["/bin/init"]
  5774    `)).Assert(c, icmd.Expected{
  5775  		ExitCode: 1,
  5776  		Err:      "Dockerfile parse error line 6: Unknown instruction: NOINSTRUCTION",
  5777  	})
  5778  }
  5779  
  5780  // FIXME(vdemeester) should be a unit test
  5781  func (s *DockerSuite) TestBuildLineErrorWithComments(c *check.C) {
  5782  	name := "test_build_line_error_with_comments"
  5783  	buildImage(name, withDockerfile(`FROM busybox
  5784    # This will print hello world
  5785    # and then ba
  5786    RUN echo hello world
  5787    NOINSTRUCTION echo ba
  5788    `)).Assert(c, icmd.Expected{
  5789  		ExitCode: 1,
  5790  		Err:      "Dockerfile parse error line 5: Unknown instruction: NOINSTRUCTION",
  5791  	})
  5792  }