github.com/guilhermebr/docker@v1.4.2-0.20150428121140-67da055cebca/integration-cli/docker_cli_build_test.go (about)

     1  package main
     2  
     3  import (
     4  	"archive/tar"
     5  	"bufio"
     6  	"bytes"
     7  	"encoding/json"
     8  	"fmt"
     9  	"io/ioutil"
    10  	"os"
    11  	"os/exec"
    12  	"path/filepath"
    13  	"reflect"
    14  	"regexp"
    15  	"runtime"
    16  	"strconv"
    17  	"strings"
    18  	"sync"
    19  	"text/template"
    20  	"time"
    21  
    22  	"github.com/docker/docker/builder/command"
    23  	"github.com/docker/docker/pkg/archive"
    24  	"github.com/docker/docker/pkg/stringutils"
    25  	"github.com/go-check/check"
    26  )
    27  
    28  func (s *DockerSuite) TestBuildJSONEmptyRun(c *check.C) {
    29  	name := "testbuildjsonemptyrun"
    30  
    31  	_, err := buildImage(
    32  		name,
    33  		`
    34      FROM busybox
    35      RUN []
    36      `,
    37  		true)
    38  
    39  	if err != nil {
    40  		c.Fatal("error when dealing with a RUN statement with empty JSON array")
    41  	}
    42  
    43  }
    44  
    45  func (s *DockerSuite) TestBuildEmptyWhitespace(c *check.C) {
    46  	name := "testbuildemptywhitespace"
    47  
    48  	_, err := buildImage(
    49  		name,
    50  		`
    51      FROM busybox
    52      COPY
    53        quux \
    54        bar
    55      `,
    56  		true)
    57  
    58  	if err == nil {
    59  		c.Fatal("no error when dealing with a COPY statement with no content on the same line")
    60  	}
    61  
    62  }
    63  
    64  func (s *DockerSuite) TestBuildShCmdJSONEntrypoint(c *check.C) {
    65  	name := "testbuildshcmdjsonentrypoint"
    66  
    67  	_, err := buildImage(
    68  		name,
    69  		`
    70      FROM busybox
    71      ENTRYPOINT ["/bin/echo"]
    72      CMD echo test
    73      `,
    74  		true)
    75  
    76  	if err != nil {
    77  		c.Fatal(err)
    78  	}
    79  
    80  	out, _, err := runCommandWithOutput(
    81  		exec.Command(
    82  			dockerBinary,
    83  			"run",
    84  			"--rm",
    85  			name))
    86  
    87  	if err != nil {
    88  		c.Fatal(err)
    89  	}
    90  
    91  	if strings.TrimSpace(out) != "/bin/sh -c echo test" {
    92  		c.Fatal("CMD did not contain /bin/sh -c")
    93  	}
    94  
    95  }
    96  
    97  func (s *DockerSuite) TestBuildEnvironmentReplacementUser(c *check.C) {
    98  	name := "testbuildenvironmentreplacement"
    99  
   100  	_, err := buildImage(name, `
   101    FROM scratch
   102    ENV user foo
   103    USER ${user}
   104    `, true)
   105  	if err != nil {
   106  		c.Fatal(err)
   107  	}
   108  
   109  	res, err := inspectFieldJSON(name, "Config.User")
   110  	if err != nil {
   111  		c.Fatal(err)
   112  	}
   113  
   114  	if res != `"foo"` {
   115  		c.Fatal("User foo from environment not in Config.User on image")
   116  	}
   117  
   118  }
   119  
   120  func (s *DockerSuite) TestBuildEnvironmentReplacementVolume(c *check.C) {
   121  	name := "testbuildenvironmentreplacement"
   122  
   123  	_, err := buildImage(name, `
   124    FROM scratch
   125    ENV volume /quux
   126    VOLUME ${volume}
   127    `, true)
   128  	if err != nil {
   129  		c.Fatal(err)
   130  	}
   131  
   132  	res, err := inspectFieldJSON(name, "Config.Volumes")
   133  	if err != nil {
   134  		c.Fatal(err)
   135  	}
   136  
   137  	var volumes map[string]interface{}
   138  
   139  	if err := json.Unmarshal([]byte(res), &volumes); err != nil {
   140  		c.Fatal(err)
   141  	}
   142  
   143  	if _, ok := volumes["/quux"]; !ok {
   144  		c.Fatal("Volume /quux from environment not in Config.Volumes on image")
   145  	}
   146  
   147  }
   148  
   149  func (s *DockerSuite) TestBuildEnvironmentReplacementExpose(c *check.C) {
   150  	name := "testbuildenvironmentreplacement"
   151  
   152  	_, err := buildImage(name, `
   153    FROM scratch
   154    ENV port 80
   155    EXPOSE ${port}
   156    `, true)
   157  	if err != nil {
   158  		c.Fatal(err)
   159  	}
   160  
   161  	res, err := inspectFieldJSON(name, "Config.ExposedPorts")
   162  	if err != nil {
   163  		c.Fatal(err)
   164  	}
   165  
   166  	var exposedPorts map[string]interface{}
   167  
   168  	if err := json.Unmarshal([]byte(res), &exposedPorts); err != nil {
   169  		c.Fatal(err)
   170  	}
   171  
   172  	if _, ok := exposedPorts["80/tcp"]; !ok {
   173  		c.Fatal("Exposed port 80 from environment not in Config.ExposedPorts on image")
   174  	}
   175  
   176  }
   177  
   178  func (s *DockerSuite) TestBuildEnvironmentReplacementWorkdir(c *check.C) {
   179  	name := "testbuildenvironmentreplacement"
   180  
   181  	_, err := buildImage(name, `
   182    FROM busybox
   183    ENV MYWORKDIR /work
   184    RUN mkdir ${MYWORKDIR}
   185    WORKDIR ${MYWORKDIR}
   186    `, true)
   187  
   188  	if err != nil {
   189  		c.Fatal(err)
   190  	}
   191  
   192  }
   193  
   194  func (s *DockerSuite) TestBuildEnvironmentReplacementAddCopy(c *check.C) {
   195  	name := "testbuildenvironmentreplacement"
   196  
   197  	ctx, err := fakeContext(`
   198    FROM scratch
   199    ENV baz foo
   200    ENV quux bar
   201    ENV dot .
   202    ENV fee fff
   203    ENV gee ggg
   204  
   205    ADD ${baz} ${dot}
   206    COPY ${quux} ${dot}
   207    ADD ${zzz:-${fee}} ${dot}
   208    COPY ${zzz:-${gee}} ${dot}
   209    `,
   210  		map[string]string{
   211  			"foo": "test1",
   212  			"bar": "test2",
   213  			"fff": "test3",
   214  			"ggg": "test4",
   215  		})
   216  
   217  	if err != nil {
   218  		c.Fatal(err)
   219  	}
   220  	defer ctx.Close()
   221  
   222  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   223  		c.Fatal(err)
   224  	}
   225  
   226  }
   227  
   228  func (s *DockerSuite) TestBuildEnvironmentReplacementEnv(c *check.C) {
   229  	name := "testbuildenvironmentreplacement"
   230  
   231  	_, err := buildImage(name,
   232  		`
   233    FROM busybox
   234    ENV foo zzz
   235    ENV bar ${foo}
   236    ENV abc1='$foo'
   237    ENV env1=$foo env2=${foo} env3="$foo" env4="${foo}"
   238    RUN [ "$abc1" = '$foo' ] && (echo "$abc1" | grep -q foo)
   239    ENV abc2="\$foo"
   240    RUN [ "$abc2" = '$foo' ] && (echo "$abc2" | grep -q foo)
   241    ENV abc3 '$foo'
   242    RUN [ "$abc3" = '$foo' ] && (echo "$abc3" | grep -q foo)
   243    ENV abc4 "\$foo"
   244    RUN [ "$abc4" = '$foo' ] && (echo "$abc4" | grep -q foo)
   245    `, true)
   246  
   247  	if err != nil {
   248  		c.Fatal(err)
   249  	}
   250  
   251  	res, err := inspectFieldJSON(name, "Config.Env")
   252  	if err != nil {
   253  		c.Fatal(err)
   254  	}
   255  
   256  	envResult := []string{}
   257  
   258  	if err = unmarshalJSON([]byte(res), &envResult); err != nil {
   259  		c.Fatal(err)
   260  	}
   261  
   262  	found := false
   263  	envCount := 0
   264  
   265  	for _, env := range envResult {
   266  		parts := strings.SplitN(env, "=", 2)
   267  		if parts[0] == "bar" {
   268  			found = true
   269  			if parts[1] != "zzz" {
   270  				c.Fatalf("Could not find replaced var for env `bar`: got %q instead of `zzz`", parts[1])
   271  			}
   272  		} else if strings.HasPrefix(parts[0], "env") {
   273  			envCount++
   274  			if parts[1] != "zzz" {
   275  				c.Fatalf("%s should be 'foo' but instead its %q", parts[0], parts[1])
   276  			}
   277  		} else if strings.HasPrefix(parts[0], "env") {
   278  			envCount++
   279  			if parts[1] != "foo" {
   280  				c.Fatalf("%s should be 'foo' but instead its %q", parts[0], parts[1])
   281  			}
   282  		}
   283  	}
   284  
   285  	if !found {
   286  		c.Fatal("Never found the `bar` env variable")
   287  	}
   288  
   289  	if envCount != 4 {
   290  		c.Fatalf("Didn't find all env vars - only saw %d\n%s", envCount, envResult)
   291  	}
   292  
   293  }
   294  
   295  func (s *DockerSuite) TestBuildHandleEscapes(c *check.C) {
   296  	name := "testbuildhandleescapes"
   297  
   298  	_, err := buildImage(name,
   299  		`
   300    FROM scratch
   301    ENV FOO bar
   302    VOLUME ${FOO}
   303    `, true)
   304  
   305  	if err != nil {
   306  		c.Fatal(err)
   307  	}
   308  
   309  	var result map[string]map[string]struct{}
   310  
   311  	res, err := inspectFieldJSON(name, "Config.Volumes")
   312  	if err != nil {
   313  		c.Fatal(err)
   314  	}
   315  
   316  	if err = unmarshalJSON([]byte(res), &result); err != nil {
   317  		c.Fatal(err)
   318  	}
   319  
   320  	if _, ok := result["bar"]; !ok {
   321  		c.Fatal("Could not find volume bar set from env foo in volumes table")
   322  	}
   323  
   324  	deleteImages(name)
   325  
   326  	_, err = buildImage(name,
   327  		`
   328    FROM scratch
   329    ENV FOO bar
   330    VOLUME \${FOO}
   331    `, true)
   332  
   333  	if err != nil {
   334  		c.Fatal(err)
   335  	}
   336  
   337  	res, err = inspectFieldJSON(name, "Config.Volumes")
   338  	if err != nil {
   339  		c.Fatal(err)
   340  	}
   341  
   342  	if err = unmarshalJSON([]byte(res), &result); err != nil {
   343  		c.Fatal(err)
   344  	}
   345  
   346  	if _, ok := result["${FOO}"]; !ok {
   347  		c.Fatal("Could not find volume ${FOO} set from env foo in volumes table")
   348  	}
   349  
   350  	deleteImages(name)
   351  
   352  	// this test in particular provides *7* backslashes and expects 6 to come back.
   353  	// Like above, the first escape is swallowed and the rest are treated as
   354  	// literals, this one is just less obvious because of all the character noise.
   355  
   356  	_, err = buildImage(name,
   357  		`
   358    FROM scratch
   359    ENV FOO bar
   360    VOLUME \\\\\\\${FOO}
   361    `, true)
   362  
   363  	if err != nil {
   364  		c.Fatal(err)
   365  	}
   366  
   367  	res, err = inspectFieldJSON(name, "Config.Volumes")
   368  	if err != nil {
   369  		c.Fatal(err)
   370  	}
   371  
   372  	if err = unmarshalJSON([]byte(res), &result); err != nil {
   373  		c.Fatal(err)
   374  	}
   375  
   376  	if _, ok := result[`\\\${FOO}`]; !ok {
   377  		c.Fatal(`Could not find volume \\\${FOO} set from env foo in volumes table`, result)
   378  	}
   379  
   380  }
   381  
   382  func (s *DockerSuite) TestBuildOnBuildLowercase(c *check.C) {
   383  	name := "testbuildonbuildlowercase"
   384  	name2 := "testbuildonbuildlowercase2"
   385  
   386  	_, err := buildImage(name,
   387  		`
   388    FROM busybox
   389    onbuild run echo quux
   390    `, true)
   391  
   392  	if err != nil {
   393  		c.Fatal(err)
   394  	}
   395  
   396  	_, out, err := buildImageWithOut(name2, fmt.Sprintf(`
   397    FROM %s
   398    `, name), true)
   399  
   400  	if err != nil {
   401  		c.Fatal(err)
   402  	}
   403  
   404  	if !strings.Contains(out, "quux") {
   405  		c.Fatalf("Did not receive the expected echo text, got %s", out)
   406  	}
   407  
   408  	if strings.Contains(out, "ONBUILD ONBUILD") {
   409  		c.Fatalf("Got an ONBUILD ONBUILD error with no error: got %s", out)
   410  	}
   411  
   412  }
   413  
   414  func (s *DockerSuite) TestBuildEnvEscapes(c *check.C) {
   415  	name := "testbuildenvescapes"
   416  	_, err := buildImage(name,
   417  		`
   418      FROM busybox
   419      ENV TEST foo
   420      CMD echo \$
   421      `,
   422  		true)
   423  
   424  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-t", name))
   425  
   426  	if err != nil {
   427  		c.Fatal(err)
   428  	}
   429  
   430  	if strings.TrimSpace(out) != "$" {
   431  		c.Fatalf("Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q", strings.TrimSpace(out))
   432  	}
   433  
   434  }
   435  
   436  func (s *DockerSuite) TestBuildEnvOverwrite(c *check.C) {
   437  	name := "testbuildenvoverwrite"
   438  
   439  	_, err := buildImage(name,
   440  		`
   441      FROM busybox
   442      ENV TEST foo
   443      CMD echo ${TEST}
   444      `,
   445  		true)
   446  
   447  	if err != nil {
   448  		c.Fatal(err)
   449  	}
   450  
   451  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-e", "TEST=bar", "-t", name))
   452  
   453  	if err != nil {
   454  		c.Fatal(err)
   455  	}
   456  
   457  	if strings.TrimSpace(out) != "bar" {
   458  		c.Fatalf("Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q", strings.TrimSpace(out))
   459  	}
   460  
   461  }
   462  
   463  func (s *DockerSuite) TestBuildOnBuildForbiddenMaintainerInSourceImage(c *check.C) {
   464  	name := "testbuildonbuildforbiddenmaintainerinsourceimage"
   465  
   466  	createCmd := exec.Command(dockerBinary, "create", "busybox", "true")
   467  	out, _, _, err := runCommandWithStdoutStderr(createCmd)
   468  	if err != nil {
   469  		c.Fatal(out, err)
   470  	}
   471  
   472  	cleanedContainerID := strings.TrimSpace(out)
   473  
   474  	commitCmd := exec.Command(dockerBinary, "commit", "--run", "{\"OnBuild\":[\"MAINTAINER docker.io\"]}", cleanedContainerID, "onbuild")
   475  
   476  	if _, err := runCommand(commitCmd); err != nil {
   477  		c.Fatal(err)
   478  	}
   479  
   480  	_, err = buildImage(name,
   481  		`FROM onbuild`,
   482  		true)
   483  	if err != nil {
   484  		if !strings.Contains(err.Error(), "maintainer isn't allowed as an ONBUILD trigger") {
   485  			c.Fatalf("Wrong error %v, must be about MAINTAINER and ONBUILD in source image", err)
   486  		}
   487  	} else {
   488  		c.Fatal("Error must not be nil")
   489  	}
   490  
   491  }
   492  
   493  func (s *DockerSuite) TestBuildOnBuildForbiddenFromInSourceImage(c *check.C) {
   494  	name := "testbuildonbuildforbiddenfrominsourceimage"
   495  
   496  	createCmd := exec.Command(dockerBinary, "create", "busybox", "true")
   497  	out, _, _, err := runCommandWithStdoutStderr(createCmd)
   498  	if err != nil {
   499  		c.Fatal(out, err)
   500  	}
   501  
   502  	cleanedContainerID := strings.TrimSpace(out)
   503  
   504  	commitCmd := exec.Command(dockerBinary, "commit", "--run", "{\"OnBuild\":[\"FROM busybox\"]}", cleanedContainerID, "onbuild")
   505  
   506  	if _, err := runCommand(commitCmd); err != nil {
   507  		c.Fatal(err)
   508  	}
   509  
   510  	_, err = buildImage(name,
   511  		`FROM onbuild`,
   512  		true)
   513  	if err != nil {
   514  		if !strings.Contains(err.Error(), "from isn't allowed as an ONBUILD trigger") {
   515  			c.Fatalf("Wrong error %v, must be about FROM and ONBUILD in source image", err)
   516  		}
   517  	} else {
   518  		c.Fatal("Error must not be nil")
   519  	}
   520  
   521  }
   522  
   523  func (s *DockerSuite) TestBuildOnBuildForbiddenChainedInSourceImage(c *check.C) {
   524  	name := "testbuildonbuildforbiddenchainedinsourceimage"
   525  
   526  	createCmd := exec.Command(dockerBinary, "create", "busybox", "true")
   527  	out, _, _, err := runCommandWithStdoutStderr(createCmd)
   528  	if err != nil {
   529  		c.Fatal(out, err)
   530  	}
   531  
   532  	cleanedContainerID := strings.TrimSpace(out)
   533  
   534  	commitCmd := exec.Command(dockerBinary, "commit", "--run", "{\"OnBuild\":[\"ONBUILD RUN ls\"]}", cleanedContainerID, "onbuild")
   535  
   536  	if _, err := runCommand(commitCmd); err != nil {
   537  		c.Fatal(err)
   538  	}
   539  
   540  	_, err = buildImage(name,
   541  		`FROM onbuild`,
   542  		true)
   543  	if err != nil {
   544  		if !strings.Contains(err.Error(), "Chaining ONBUILD via `ONBUILD ONBUILD` isn't allowed") {
   545  			c.Fatalf("Wrong error %v, must be about chaining ONBUILD in source image", err)
   546  		}
   547  	} else {
   548  		c.Fatal("Error must not be nil")
   549  	}
   550  
   551  }
   552  
   553  func (s *DockerSuite) TestBuildOnBuildCmdEntrypointJSON(c *check.C) {
   554  	name1 := "onbuildcmd"
   555  	name2 := "onbuildgenerated"
   556  
   557  	_, err := buildImage(name1, `
   558  FROM busybox
   559  ONBUILD CMD ["hello world"]
   560  ONBUILD ENTRYPOINT ["echo"]
   561  ONBUILD RUN ["true"]`,
   562  		false)
   563  
   564  	if err != nil {
   565  		c.Fatal(err)
   566  	}
   567  
   568  	_, err = buildImage(name2, fmt.Sprintf(`FROM %s`, name1), false)
   569  
   570  	if err != nil {
   571  		c.Fatal(err)
   572  	}
   573  
   574  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-t", name2))
   575  	if err != nil {
   576  		c.Fatal(err)
   577  	}
   578  
   579  	if !regexp.MustCompile(`(?m)^hello world`).MatchString(out) {
   580  		c.Fatal("did not get echo output from onbuild", out)
   581  	}
   582  
   583  }
   584  
   585  func (s *DockerSuite) TestBuildOnBuildEntrypointJSON(c *check.C) {
   586  	name1 := "onbuildcmd"
   587  	name2 := "onbuildgenerated"
   588  
   589  	_, err := buildImage(name1, `
   590  FROM busybox
   591  ONBUILD ENTRYPOINT ["echo"]`,
   592  		false)
   593  
   594  	if err != nil {
   595  		c.Fatal(err)
   596  	}
   597  
   598  	_, err = buildImage(name2, fmt.Sprintf("FROM %s\nCMD [\"hello world\"]\n", name1), false)
   599  
   600  	if err != nil {
   601  		c.Fatal(err)
   602  	}
   603  
   604  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-t", name2))
   605  	if err != nil {
   606  		c.Fatal(err)
   607  	}
   608  
   609  	if !regexp.MustCompile(`(?m)^hello world`).MatchString(out) {
   610  		c.Fatal("got malformed output from onbuild", out)
   611  	}
   612  
   613  }
   614  
   615  func (s *DockerSuite) TestBuildCacheADD(c *check.C) {
   616  	name := "testbuildtwoimageswithadd"
   617  	server, err := fakeStorage(map[string]string{
   618  		"robots.txt": "hello",
   619  		"index.html": "world",
   620  	})
   621  	if err != nil {
   622  		c.Fatal(err)
   623  	}
   624  	defer server.Close()
   625  
   626  	if _, err := buildImage(name,
   627  		fmt.Sprintf(`FROM scratch
   628  		ADD %s/robots.txt /`, server.URL()),
   629  		true); err != nil {
   630  		c.Fatal(err)
   631  	}
   632  	if err != nil {
   633  		c.Fatal(err)
   634  	}
   635  	deleteImages(name)
   636  	_, out, err := buildImageWithOut(name,
   637  		fmt.Sprintf(`FROM scratch
   638  		ADD %s/index.html /`, server.URL()),
   639  		true)
   640  	if err != nil {
   641  		c.Fatal(err)
   642  	}
   643  	if strings.Contains(out, "Using cache") {
   644  		c.Fatal("2nd build used cache on ADD, it shouldn't")
   645  	}
   646  
   647  }
   648  
   649  func (s *DockerSuite) TestBuildLastModified(c *check.C) {
   650  	name := "testbuildlastmodified"
   651  
   652  	server, err := fakeStorage(map[string]string{
   653  		"file": "hello",
   654  	})
   655  	if err != nil {
   656  		c.Fatal(err)
   657  	}
   658  	defer server.Close()
   659  
   660  	var out, out2 string
   661  
   662  	dFmt := `FROM busybox
   663  ADD %s/file /
   664  RUN ls -le /file`
   665  
   666  	dockerfile := fmt.Sprintf(dFmt, server.URL())
   667  
   668  	if _, out, err = buildImageWithOut(name, dockerfile, false); err != nil {
   669  		c.Fatal(err)
   670  	}
   671  
   672  	originMTime := regexp.MustCompile(`root.*/file.*\n`).FindString(out)
   673  	// Make sure our regexp is correct
   674  	if strings.Index(originMTime, "/file") < 0 {
   675  		c.Fatalf("Missing ls info on 'file':\n%s", out)
   676  	}
   677  
   678  	// Build it again and make sure the mtime of the file didn't change.
   679  	// Wait a few seconds to make sure the time changed enough to notice
   680  	time.Sleep(2 * time.Second)
   681  
   682  	if _, out2, err = buildImageWithOut(name, dockerfile, false); err != nil {
   683  		c.Fatal(err)
   684  	}
   685  
   686  	newMTime := regexp.MustCompile(`root.*/file.*\n`).FindString(out2)
   687  	if newMTime != originMTime {
   688  		c.Fatalf("MTime changed:\nOrigin:%s\nNew:%s", originMTime, newMTime)
   689  	}
   690  
   691  	// Now 'touch' the file and make sure the timestamp DID change this time
   692  	// Create a new fakeStorage instead of just using Add() to help windows
   693  	server, err = fakeStorage(map[string]string{
   694  		"file": "hello",
   695  	})
   696  	if err != nil {
   697  		c.Fatal(err)
   698  	}
   699  	defer server.Close()
   700  
   701  	dockerfile = fmt.Sprintf(dFmt, server.URL())
   702  
   703  	if _, out2, err = buildImageWithOut(name, dockerfile, false); err != nil {
   704  		c.Fatal(err)
   705  	}
   706  
   707  	newMTime = regexp.MustCompile(`root.*/file.*\n`).FindString(out2)
   708  	if newMTime == originMTime {
   709  		c.Fatalf("MTime didn't change:\nOrigin:%s\nNew:%s", originMTime, newMTime)
   710  	}
   711  
   712  }
   713  
   714  func (s *DockerSuite) TestBuildSixtySteps(c *check.C) {
   715  	name := "foobuildsixtysteps"
   716  	ctx, err := fakeContext("FROM scratch\n"+strings.Repeat("ADD foo /\n", 60),
   717  		map[string]string{
   718  			"foo": "test1",
   719  		})
   720  	if err != nil {
   721  		c.Fatal(err)
   722  	}
   723  	defer ctx.Close()
   724  
   725  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   726  		c.Fatal(err)
   727  	}
   728  }
   729  
   730  func (s *DockerSuite) TestBuildAddSingleFileToRoot(c *check.C) {
   731  	name := "testaddimg"
   732  	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
   733  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   734  RUN echo 'dockerio:x:1001:' >> /etc/group
   735  RUN touch /exists
   736  RUN chown dockerio.dockerio /exists
   737  ADD test_file /
   738  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
   739  RUN [ $(ls -l /test_file | awk '{print $1}') = '%s' ]
   740  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod),
   741  		map[string]string{
   742  			"test_file": "test1",
   743  		})
   744  	if err != nil {
   745  		c.Fatal(err)
   746  	}
   747  	defer ctx.Close()
   748  
   749  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   750  		c.Fatal(err)
   751  	}
   752  }
   753  
   754  // Issue #3960: "ADD src ." hangs
   755  func (s *DockerSuite) TestBuildAddSingleFileToWorkdir(c *check.C) {
   756  	name := "testaddsinglefiletoworkdir"
   757  	ctx, err := fakeContext(`FROM busybox
   758  ADD test_file .`,
   759  		map[string]string{
   760  			"test_file": "test1",
   761  		})
   762  	if err != nil {
   763  		c.Fatal(err)
   764  	}
   765  	defer ctx.Close()
   766  
   767  	done := make(chan struct{})
   768  	go func() {
   769  		if _, err := buildImageFromContext(name, ctx, true); err != nil {
   770  			c.Fatal(err)
   771  		}
   772  		close(done)
   773  	}()
   774  	select {
   775  	case <-time.After(5 * time.Second):
   776  		c.Fatal("Build with adding to workdir timed out")
   777  	case <-done:
   778  	}
   779  }
   780  
   781  func (s *DockerSuite) TestBuildAddSingleFileToExistDir(c *check.C) {
   782  	name := "testaddsinglefiletoexistdir"
   783  	ctx, err := fakeContext(`FROM busybox
   784  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   785  RUN echo 'dockerio:x:1001:' >> /etc/group
   786  RUN mkdir /exists
   787  RUN touch /exists/exists_file
   788  RUN chown -R dockerio.dockerio /exists
   789  ADD test_file /exists/
   790  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   791  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]
   792  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
   793  		map[string]string{
   794  			"test_file": "test1",
   795  		})
   796  	if err != nil {
   797  		c.Fatal(err)
   798  	}
   799  	defer ctx.Close()
   800  
   801  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   802  		c.Fatal(err)
   803  	}
   804  }
   805  
   806  func (s *DockerSuite) TestBuildCopyAddMultipleFiles(c *check.C) {
   807  	server, err := fakeStorage(map[string]string{
   808  		"robots.txt": "hello",
   809  	})
   810  	if err != nil {
   811  		c.Fatal(err)
   812  	}
   813  	defer server.Close()
   814  
   815  	name := "testcopymultiplefilestofile"
   816  	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
   817  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   818  RUN echo 'dockerio:x:1001:' >> /etc/group
   819  RUN mkdir /exists
   820  RUN touch /exists/exists_file
   821  RUN chown -R dockerio.dockerio /exists
   822  COPY test_file1 test_file2 /exists/
   823  ADD test_file3 test_file4 %s/robots.txt /exists/
   824  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   825  RUN [ $(ls -l /exists/test_file1 | awk '{print $3":"$4}') = 'root:root' ]
   826  RUN [ $(ls -l /exists/test_file2 | awk '{print $3":"$4}') = 'root:root' ]
   827  
   828  RUN [ $(ls -l /exists/test_file3 | awk '{print $3":"$4}') = 'root:root' ]
   829  RUN [ $(ls -l /exists/test_file4 | awk '{print $3":"$4}') = 'root:root' ]
   830  RUN [ $(ls -l /exists/robots.txt | awk '{print $3":"$4}') = 'root:root' ]
   831  
   832  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   833  `, server.URL()),
   834  		map[string]string{
   835  			"test_file1": "test1",
   836  			"test_file2": "test2",
   837  			"test_file3": "test3",
   838  			"test_file4": "test4",
   839  		})
   840  	defer ctx.Close()
   841  	if err != nil {
   842  		c.Fatal(err)
   843  	}
   844  
   845  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   846  		c.Fatal(err)
   847  	}
   848  }
   849  
   850  func (s *DockerSuite) TestBuildAddMultipleFilesToFile(c *check.C) {
   851  	name := "testaddmultiplefilestofile"
   852  	ctx, err := fakeContext(`FROM scratch
   853  	ADD file1.txt file2.txt test
   854  	`,
   855  		map[string]string{
   856  			"file1.txt": "test1",
   857  			"file2.txt": "test1",
   858  		})
   859  	defer ctx.Close()
   860  	if err != nil {
   861  		c.Fatal(err)
   862  	}
   863  
   864  	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
   865  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
   866  		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
   867  	}
   868  
   869  }
   870  
   871  func (s *DockerSuite) TestBuildJSONAddMultipleFilesToFile(c *check.C) {
   872  	name := "testjsonaddmultiplefilestofile"
   873  	ctx, err := fakeContext(`FROM scratch
   874  	ADD ["file1.txt", "file2.txt", "test"]
   875  	`,
   876  		map[string]string{
   877  			"file1.txt": "test1",
   878  			"file2.txt": "test1",
   879  		})
   880  	defer ctx.Close()
   881  	if err != nil {
   882  		c.Fatal(err)
   883  	}
   884  
   885  	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
   886  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
   887  		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
   888  	}
   889  
   890  }
   891  
   892  func (s *DockerSuite) TestBuildAddMultipleFilesToFileWild(c *check.C) {
   893  	name := "testaddmultiplefilestofilewild"
   894  	ctx, err := fakeContext(`FROM scratch
   895  	ADD file*.txt test
   896  	`,
   897  		map[string]string{
   898  			"file1.txt": "test1",
   899  			"file2.txt": "test1",
   900  		})
   901  	defer ctx.Close()
   902  	if err != nil {
   903  		c.Fatal(err)
   904  	}
   905  
   906  	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
   907  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
   908  		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
   909  	}
   910  
   911  }
   912  
   913  func (s *DockerSuite) TestBuildJSONAddMultipleFilesToFileWild(c *check.C) {
   914  	name := "testjsonaddmultiplefilestofilewild"
   915  	ctx, err := fakeContext(`FROM scratch
   916  	ADD ["file*.txt", "test"]
   917  	`,
   918  		map[string]string{
   919  			"file1.txt": "test1",
   920  			"file2.txt": "test1",
   921  		})
   922  	defer ctx.Close()
   923  	if err != nil {
   924  		c.Fatal(err)
   925  	}
   926  
   927  	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
   928  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
   929  		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
   930  	}
   931  
   932  }
   933  
   934  func (s *DockerSuite) TestBuildCopyMultipleFilesToFile(c *check.C) {
   935  	name := "testcopymultiplefilestofile"
   936  	ctx, err := fakeContext(`FROM scratch
   937  	COPY file1.txt file2.txt test
   938  	`,
   939  		map[string]string{
   940  			"file1.txt": "test1",
   941  			"file2.txt": "test1",
   942  		})
   943  	defer ctx.Close()
   944  	if err != nil {
   945  		c.Fatal(err)
   946  	}
   947  
   948  	expected := "When using COPY with more than one source file, the destination must be a directory and end with a /"
   949  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
   950  		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
   951  	}
   952  
   953  }
   954  
   955  func (s *DockerSuite) TestBuildJSONCopyMultipleFilesToFile(c *check.C) {
   956  	name := "testjsoncopymultiplefilestofile"
   957  	ctx, err := fakeContext(`FROM scratch
   958  	COPY ["file1.txt", "file2.txt", "test"]
   959  	`,
   960  		map[string]string{
   961  			"file1.txt": "test1",
   962  			"file2.txt": "test1",
   963  		})
   964  	defer ctx.Close()
   965  	if err != nil {
   966  		c.Fatal(err)
   967  	}
   968  
   969  	expected := "When using COPY with more than one source file, the destination must be a directory and end with a /"
   970  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
   971  		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
   972  	}
   973  
   974  }
   975  
   976  func (s *DockerSuite) TestBuildAddFileWithWhitespace(c *check.C) {
   977  	name := "testaddfilewithwhitespace"
   978  	ctx, err := fakeContext(`FROM busybox
   979  RUN mkdir "/test dir"
   980  RUN mkdir "/test_dir"
   981  ADD [ "test file1", "/test_file1" ]
   982  ADD [ "test_file2", "/test file2" ]
   983  ADD [ "test file3", "/test file3" ]
   984  ADD [ "test dir/test_file4", "/test_dir/test_file4" ]
   985  ADD [ "test_dir/test_file5", "/test dir/test_file5" ]
   986  ADD [ "test dir/test_file6", "/test dir/test_file6" ]
   987  RUN [ $(cat "/test_file1") = 'test1' ]
   988  RUN [ $(cat "/test file2") = 'test2' ]
   989  RUN [ $(cat "/test file3") = 'test3' ]
   990  RUN [ $(cat "/test_dir/test_file4") = 'test4' ]
   991  RUN [ $(cat "/test dir/test_file5") = 'test5' ]
   992  RUN [ $(cat "/test dir/test_file6") = 'test6' ]`,
   993  		map[string]string{
   994  			"test file1":          "test1",
   995  			"test_file2":          "test2",
   996  			"test file3":          "test3",
   997  			"test dir/test_file4": "test4",
   998  			"test_dir/test_file5": "test5",
   999  			"test dir/test_file6": "test6",
  1000  		})
  1001  	defer ctx.Close()
  1002  	if err != nil {
  1003  		c.Fatal(err)
  1004  	}
  1005  
  1006  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1007  		c.Fatal(err)
  1008  	}
  1009  }
  1010  
  1011  func (s *DockerSuite) TestBuildCopyFileWithWhitespace(c *check.C) {
  1012  	name := "testcopyfilewithwhitespace"
  1013  	ctx, err := fakeContext(`FROM busybox
  1014  RUN mkdir "/test dir"
  1015  RUN mkdir "/test_dir"
  1016  COPY [ "test file1", "/test_file1" ]
  1017  COPY [ "test_file2", "/test file2" ]
  1018  COPY [ "test file3", "/test file3" ]
  1019  COPY [ "test dir/test_file4", "/test_dir/test_file4" ]
  1020  COPY [ "test_dir/test_file5", "/test dir/test_file5" ]
  1021  COPY [ "test dir/test_file6", "/test dir/test_file6" ]
  1022  RUN [ $(cat "/test_file1") = 'test1' ]
  1023  RUN [ $(cat "/test file2") = 'test2' ]
  1024  RUN [ $(cat "/test file3") = 'test3' ]
  1025  RUN [ $(cat "/test_dir/test_file4") = 'test4' ]
  1026  RUN [ $(cat "/test dir/test_file5") = 'test5' ]
  1027  RUN [ $(cat "/test dir/test_file6") = 'test6' ]`,
  1028  		map[string]string{
  1029  			"test file1":          "test1",
  1030  			"test_file2":          "test2",
  1031  			"test file3":          "test3",
  1032  			"test dir/test_file4": "test4",
  1033  			"test_dir/test_file5": "test5",
  1034  			"test dir/test_file6": "test6",
  1035  		})
  1036  	defer ctx.Close()
  1037  	if err != nil {
  1038  		c.Fatal(err)
  1039  	}
  1040  
  1041  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1042  		c.Fatal(err)
  1043  	}
  1044  }
  1045  
  1046  func (s *DockerSuite) TestBuildAddMultipleFilesToFileWithWhitespace(c *check.C) {
  1047  	name := "testaddmultiplefilestofilewithwhitespace"
  1048  	ctx, err := fakeContext(`FROM busybox
  1049  	ADD [ "test file1", "test file2", "test" ]
  1050      `,
  1051  		map[string]string{
  1052  			"test file1": "test1",
  1053  			"test file2": "test2",
  1054  		})
  1055  	defer ctx.Close()
  1056  	if err != nil {
  1057  		c.Fatal(err)
  1058  	}
  1059  
  1060  	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
  1061  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
  1062  		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
  1063  	}
  1064  
  1065  }
  1066  
  1067  func (s *DockerSuite) TestBuildCopyMultipleFilesToFileWithWhitespace(c *check.C) {
  1068  	name := "testcopymultiplefilestofilewithwhitespace"
  1069  	ctx, err := fakeContext(`FROM busybox
  1070  	COPY [ "test file1", "test file2", "test" ]
  1071          `,
  1072  		map[string]string{
  1073  			"test file1": "test1",
  1074  			"test file2": "test2",
  1075  		})
  1076  	defer ctx.Close()
  1077  	if err != nil {
  1078  		c.Fatal(err)
  1079  	}
  1080  
  1081  	expected := "When using COPY with more than one source file, the destination must be a directory and end with a /"
  1082  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
  1083  		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
  1084  	}
  1085  
  1086  }
  1087  
  1088  func (s *DockerSuite) TestBuildCopyWildcard(c *check.C) {
  1089  	name := "testcopywildcard"
  1090  	server, err := fakeStorage(map[string]string{
  1091  		"robots.txt": "hello",
  1092  		"index.html": "world",
  1093  	})
  1094  	if err != nil {
  1095  		c.Fatal(err)
  1096  	}
  1097  	defer server.Close()
  1098  
  1099  	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
  1100  	COPY file*.txt /tmp/
  1101  	RUN ls /tmp/file1.txt /tmp/file2.txt
  1102  	RUN mkdir /tmp1
  1103  	COPY dir* /tmp1/
  1104  	RUN ls /tmp1/dirt /tmp1/nested_file /tmp1/nested_dir/nest_nest_file
  1105  	RUN mkdir /tmp2
  1106          ADD dir/*dir %s/robots.txt /tmp2/
  1107  	RUN ls /tmp2/nest_nest_file /tmp2/robots.txt
  1108  	`, server.URL()),
  1109  		map[string]string{
  1110  			"file1.txt":                     "test1",
  1111  			"file2.txt":                     "test2",
  1112  			"dir/nested_file":               "nested file",
  1113  			"dir/nested_dir/nest_nest_file": "2 times nested",
  1114  			"dirt": "dirty",
  1115  		})
  1116  	defer ctx.Close()
  1117  	if err != nil {
  1118  		c.Fatal(err)
  1119  	}
  1120  
  1121  	id1, err := buildImageFromContext(name, ctx, true)
  1122  	if err != nil {
  1123  		c.Fatal(err)
  1124  	}
  1125  
  1126  	// Now make sure we use a cache the 2nd time
  1127  	id2, err := buildImageFromContext(name, ctx, true)
  1128  	if err != nil {
  1129  		c.Fatal(err)
  1130  	}
  1131  
  1132  	if id1 != id2 {
  1133  		c.Fatal("didn't use the cache")
  1134  	}
  1135  
  1136  }
  1137  
  1138  func (s *DockerSuite) TestBuildCopyWildcardNoFind(c *check.C) {
  1139  	name := "testcopywildcardnofind"
  1140  	ctx, err := fakeContext(`FROM busybox
  1141  	COPY file*.txt /tmp/
  1142  	`, nil)
  1143  	defer ctx.Close()
  1144  	if err != nil {
  1145  		c.Fatal(err)
  1146  	}
  1147  
  1148  	_, err = buildImageFromContext(name, ctx, true)
  1149  	if err == nil {
  1150  		c.Fatal("should have failed to find a file")
  1151  	}
  1152  	if !strings.Contains(err.Error(), "No source files were specified") {
  1153  		c.Fatalf("Wrong error %v, must be about no source files", err)
  1154  	}
  1155  
  1156  }
  1157  
  1158  func (s *DockerSuite) TestBuildCopyWildcardCache(c *check.C) {
  1159  	name := "testcopywildcardcache"
  1160  	ctx, err := fakeContext(`FROM busybox
  1161  	COPY file1.txt /tmp/`,
  1162  		map[string]string{
  1163  			"file1.txt": "test1",
  1164  		})
  1165  	defer ctx.Close()
  1166  	if err != nil {
  1167  		c.Fatal(err)
  1168  	}
  1169  
  1170  	id1, err := buildImageFromContext(name, ctx, true)
  1171  	if err != nil {
  1172  		c.Fatal(err)
  1173  	}
  1174  
  1175  	// Now make sure we use a cache the 2nd time even with wild cards.
  1176  	// Use the same context so the file is the same and the checksum will match
  1177  	ctx.Add("Dockerfile", `FROM busybox
  1178  	COPY file*.txt /tmp/`)
  1179  
  1180  	id2, err := buildImageFromContext(name, ctx, true)
  1181  	if err != nil {
  1182  		c.Fatal(err)
  1183  	}
  1184  
  1185  	if id1 != id2 {
  1186  		c.Fatal("didn't use the cache")
  1187  	}
  1188  
  1189  }
  1190  
  1191  func (s *DockerSuite) TestBuildAddSingleFileToNonExistingDir(c *check.C) {
  1192  	name := "testaddsinglefiletononexistingdir"
  1193  	ctx, err := fakeContext(`FROM busybox
  1194  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1195  RUN echo 'dockerio:x:1001:' >> /etc/group
  1196  RUN touch /exists
  1197  RUN chown dockerio.dockerio /exists
  1198  ADD test_file /test_dir/
  1199  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
  1200  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
  1201  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
  1202  		map[string]string{
  1203  			"test_file": "test1",
  1204  		})
  1205  	if err != nil {
  1206  		c.Fatal(err)
  1207  	}
  1208  	defer ctx.Close()
  1209  
  1210  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1211  		c.Fatal(err)
  1212  	}
  1213  
  1214  }
  1215  
  1216  func (s *DockerSuite) TestBuildAddDirContentToRoot(c *check.C) {
  1217  	name := "testadddircontenttoroot"
  1218  	ctx, err := fakeContext(`FROM busybox
  1219  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1220  RUN echo 'dockerio:x:1001:' >> /etc/group
  1221  RUN touch /exists
  1222  RUN chown dockerio.dockerio exists
  1223  ADD test_dir /
  1224  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
  1225  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
  1226  		map[string]string{
  1227  			"test_dir/test_file": "test1",
  1228  		})
  1229  	if err != nil {
  1230  		c.Fatal(err)
  1231  	}
  1232  	defer ctx.Close()
  1233  
  1234  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1235  		c.Fatal(err)
  1236  	}
  1237  }
  1238  
  1239  func (s *DockerSuite) TestBuildAddDirContentToExistingDir(c *check.C) {
  1240  	name := "testadddircontenttoexistingdir"
  1241  	ctx, err := fakeContext(`FROM busybox
  1242  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1243  RUN echo 'dockerio:x:1001:' >> /etc/group
  1244  RUN mkdir /exists
  1245  RUN touch /exists/exists_file
  1246  RUN chown -R dockerio.dockerio /exists
  1247  ADD test_dir/ /exists/
  1248  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
  1249  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
  1250  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]`,
  1251  		map[string]string{
  1252  			"test_dir/test_file": "test1",
  1253  		})
  1254  	if err != nil {
  1255  		c.Fatal(err)
  1256  	}
  1257  	defer ctx.Close()
  1258  
  1259  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1260  		c.Fatal(err)
  1261  	}
  1262  }
  1263  
  1264  func (s *DockerSuite) TestBuildAddWholeDirToRoot(c *check.C) {
  1265  	name := "testaddwholedirtoroot"
  1266  	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
  1267  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1268  RUN echo 'dockerio:x:1001:' >> /etc/group
  1269  RUN touch /exists
  1270  RUN chown dockerio.dockerio exists
  1271  ADD test_dir /test_dir
  1272  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
  1273  RUN [ $(ls -l / | grep test_dir | awk '{print $1}') = 'drwxr-xr-x' ]
  1274  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
  1275  RUN [ $(ls -l /test_dir/test_file | awk '{print $1}') = '%s' ]
  1276  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod),
  1277  		map[string]string{
  1278  			"test_dir/test_file": "test1",
  1279  		})
  1280  	if err != nil {
  1281  		c.Fatal(err)
  1282  	}
  1283  	defer ctx.Close()
  1284  
  1285  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1286  		c.Fatal(err)
  1287  	}
  1288  }
  1289  
  1290  // Testing #5941
  1291  func (s *DockerSuite) TestBuildAddEtcToRoot(c *check.C) {
  1292  	name := "testaddetctoroot"
  1293  	ctx, err := fakeContext(`FROM scratch
  1294  ADD . /`,
  1295  		map[string]string{
  1296  			"etc/test_file": "test1",
  1297  		})
  1298  	if err != nil {
  1299  		c.Fatal(err)
  1300  	}
  1301  	defer ctx.Close()
  1302  
  1303  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1304  		c.Fatal(err)
  1305  	}
  1306  }
  1307  
  1308  // Testing #9401
  1309  func (s *DockerSuite) TestBuildAddPreservesFilesSpecialBits(c *check.C) {
  1310  	name := "testaddpreservesfilesspecialbits"
  1311  	ctx, err := fakeContext(`FROM busybox
  1312  ADD suidbin /usr/bin/suidbin
  1313  RUN chmod 4755 /usr/bin/suidbin
  1314  RUN [ $(ls -l /usr/bin/suidbin | awk '{print $1}') = '-rwsr-xr-x' ]
  1315  ADD ./data/ /
  1316  RUN [ $(ls -l /usr/bin/suidbin | awk '{print $1}') = '-rwsr-xr-x' ]`,
  1317  		map[string]string{
  1318  			"suidbin":             "suidbin",
  1319  			"/data/usr/test_file": "test1",
  1320  		})
  1321  	if err != nil {
  1322  		c.Fatal(err)
  1323  	}
  1324  	defer ctx.Close()
  1325  
  1326  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1327  		c.Fatal(err)
  1328  	}
  1329  }
  1330  
  1331  func (s *DockerSuite) TestBuildCopySingleFileToRoot(c *check.C) {
  1332  	name := "testcopysinglefiletoroot"
  1333  	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
  1334  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1335  RUN echo 'dockerio:x:1001:' >> /etc/group
  1336  RUN touch /exists
  1337  RUN chown dockerio.dockerio /exists
  1338  COPY test_file /
  1339  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
  1340  RUN [ $(ls -l /test_file | awk '{print $1}') = '%s' ]
  1341  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod),
  1342  		map[string]string{
  1343  			"test_file": "test1",
  1344  		})
  1345  	if err != nil {
  1346  		c.Fatal(err)
  1347  	}
  1348  	defer ctx.Close()
  1349  
  1350  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1351  		c.Fatal(err)
  1352  	}
  1353  }
  1354  
  1355  // Issue #3960: "ADD src ." hangs - adapted for COPY
  1356  func (s *DockerSuite) TestBuildCopySingleFileToWorkdir(c *check.C) {
  1357  	name := "testcopysinglefiletoworkdir"
  1358  	ctx, err := fakeContext(`FROM busybox
  1359  COPY test_file .`,
  1360  		map[string]string{
  1361  			"test_file": "test1",
  1362  		})
  1363  	if err != nil {
  1364  		c.Fatal(err)
  1365  	}
  1366  	defer ctx.Close()
  1367  
  1368  	done := make(chan struct{})
  1369  	go func() {
  1370  		if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1371  			c.Fatal(err)
  1372  		}
  1373  		close(done)
  1374  	}()
  1375  	select {
  1376  	case <-time.After(5 * time.Second):
  1377  		c.Fatal("Build with adding to workdir timed out")
  1378  	case <-done:
  1379  	}
  1380  }
  1381  
  1382  func (s *DockerSuite) TestBuildCopySingleFileToExistDir(c *check.C) {
  1383  	name := "testcopysinglefiletoexistdir"
  1384  	ctx, err := fakeContext(`FROM busybox
  1385  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1386  RUN echo 'dockerio:x:1001:' >> /etc/group
  1387  RUN mkdir /exists
  1388  RUN touch /exists/exists_file
  1389  RUN chown -R dockerio.dockerio /exists
  1390  COPY test_file /exists/
  1391  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
  1392  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]
  1393  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
  1394  		map[string]string{
  1395  			"test_file": "test1",
  1396  		})
  1397  	if err != nil {
  1398  		c.Fatal(err)
  1399  	}
  1400  	defer ctx.Close()
  1401  
  1402  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1403  		c.Fatal(err)
  1404  	}
  1405  }
  1406  
  1407  func (s *DockerSuite) TestBuildCopySingleFileToNonExistDir(c *check.C) {
  1408  	name := "testcopysinglefiletononexistdir"
  1409  	ctx, err := fakeContext(`FROM busybox
  1410  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1411  RUN echo 'dockerio:x:1001:' >> /etc/group
  1412  RUN touch /exists
  1413  RUN chown dockerio.dockerio /exists
  1414  COPY test_file /test_dir/
  1415  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
  1416  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
  1417  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
  1418  		map[string]string{
  1419  			"test_file": "test1",
  1420  		})
  1421  	if err != nil {
  1422  		c.Fatal(err)
  1423  	}
  1424  	defer ctx.Close()
  1425  
  1426  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1427  		c.Fatal(err)
  1428  	}
  1429  }
  1430  
  1431  func (s *DockerSuite) TestBuildCopyDirContentToRoot(c *check.C) {
  1432  	name := "testcopydircontenttoroot"
  1433  	ctx, err := fakeContext(`FROM busybox
  1434  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1435  RUN echo 'dockerio:x:1001:' >> /etc/group
  1436  RUN touch /exists
  1437  RUN chown dockerio.dockerio exists
  1438  COPY test_dir /
  1439  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
  1440  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
  1441  		map[string]string{
  1442  			"test_dir/test_file": "test1",
  1443  		})
  1444  	if err != nil {
  1445  		c.Fatal(err)
  1446  	}
  1447  	defer ctx.Close()
  1448  
  1449  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1450  		c.Fatal(err)
  1451  	}
  1452  }
  1453  
  1454  func (s *DockerSuite) TestBuildCopyDirContentToExistDir(c *check.C) {
  1455  	name := "testcopydircontenttoexistdir"
  1456  	ctx, err := fakeContext(`FROM busybox
  1457  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1458  RUN echo 'dockerio:x:1001:' >> /etc/group
  1459  RUN mkdir /exists
  1460  RUN touch /exists/exists_file
  1461  RUN chown -R dockerio.dockerio /exists
  1462  COPY test_dir/ /exists/
  1463  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
  1464  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
  1465  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]`,
  1466  		map[string]string{
  1467  			"test_dir/test_file": "test1",
  1468  		})
  1469  	if err != nil {
  1470  		c.Fatal(err)
  1471  	}
  1472  	defer ctx.Close()
  1473  
  1474  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1475  		c.Fatal(err)
  1476  	}
  1477  }
  1478  
  1479  func (s *DockerSuite) TestBuildCopyWholeDirToRoot(c *check.C) {
  1480  	name := "testcopywholedirtoroot"
  1481  	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
  1482  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1483  RUN echo 'dockerio:x:1001:' >> /etc/group
  1484  RUN touch /exists
  1485  RUN chown dockerio.dockerio exists
  1486  COPY test_dir /test_dir
  1487  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
  1488  RUN [ $(ls -l / | grep test_dir | awk '{print $1}') = 'drwxr-xr-x' ]
  1489  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
  1490  RUN [ $(ls -l /test_dir/test_file | awk '{print $1}') = '%s' ]
  1491  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod),
  1492  		map[string]string{
  1493  			"test_dir/test_file": "test1",
  1494  		})
  1495  	if err != nil {
  1496  		c.Fatal(err)
  1497  	}
  1498  	defer ctx.Close()
  1499  
  1500  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1501  		c.Fatal(err)
  1502  	}
  1503  }
  1504  
  1505  func (s *DockerSuite) TestBuildCopyEtcToRoot(c *check.C) {
  1506  	name := "testcopyetctoroot"
  1507  	ctx, err := fakeContext(`FROM scratch
  1508  COPY . /`,
  1509  		map[string]string{
  1510  			"etc/test_file": "test1",
  1511  		})
  1512  	if err != nil {
  1513  		c.Fatal(err)
  1514  	}
  1515  	defer ctx.Close()
  1516  
  1517  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1518  		c.Fatal(err)
  1519  	}
  1520  }
  1521  
  1522  func (s *DockerSuite) TestBuildCopyDisallowRemote(c *check.C) {
  1523  	name := "testcopydisallowremote"
  1524  	_, out, err := buildImageWithOut(name, `FROM scratch
  1525  COPY https://index.docker.io/robots.txt /`,
  1526  		true)
  1527  	if err == nil || !strings.Contains(out, "Source can't be a URL for COPY") {
  1528  		c.Fatalf("Error should be about disallowed remote source, got err: %s, out: %q", err, out)
  1529  	}
  1530  }
  1531  
  1532  func (s *DockerSuite) TestBuildAddBadLinks(c *check.C) {
  1533  	const (
  1534  		dockerfile = `
  1535  			FROM scratch
  1536  			ADD links.tar /
  1537  			ADD foo.txt /symlink/
  1538  			`
  1539  		targetFile = "foo.txt"
  1540  	)
  1541  	var (
  1542  		name = "test-link-absolute"
  1543  	)
  1544  	ctx, err := fakeContext(dockerfile, nil)
  1545  	if err != nil {
  1546  		c.Fatal(err)
  1547  	}
  1548  	defer ctx.Close()
  1549  
  1550  	tempDir, err := ioutil.TempDir("", "test-link-absolute-temp-")
  1551  	if err != nil {
  1552  		c.Fatalf("failed to create temporary directory: %s", tempDir)
  1553  	}
  1554  	defer os.RemoveAll(tempDir)
  1555  
  1556  	var symlinkTarget string
  1557  	if runtime.GOOS == "windows" {
  1558  		var driveLetter string
  1559  		if abs, err := filepath.Abs(tempDir); err != nil {
  1560  			c.Fatal(err)
  1561  		} else {
  1562  			driveLetter = abs[:1]
  1563  		}
  1564  		tempDirWithoutDrive := tempDir[2:]
  1565  		symlinkTarget = fmt.Sprintf(`%s:\..\..\..\..\..\..\..\..\..\..\..\..%s`, driveLetter, tempDirWithoutDrive)
  1566  	} else {
  1567  		symlinkTarget = fmt.Sprintf("/../../../../../../../../../../../..%s", tempDir)
  1568  	}
  1569  
  1570  	tarPath := filepath.Join(ctx.Dir, "links.tar")
  1571  	nonExistingFile := filepath.Join(tempDir, targetFile)
  1572  	fooPath := filepath.Join(ctx.Dir, targetFile)
  1573  
  1574  	tarOut, err := os.Create(tarPath)
  1575  	if err != nil {
  1576  		c.Fatal(err)
  1577  	}
  1578  
  1579  	tarWriter := tar.NewWriter(tarOut)
  1580  
  1581  	header := &tar.Header{
  1582  		Name:     "symlink",
  1583  		Typeflag: tar.TypeSymlink,
  1584  		Linkname: symlinkTarget,
  1585  		Mode:     0755,
  1586  		Uid:      0,
  1587  		Gid:      0,
  1588  	}
  1589  
  1590  	err = tarWriter.WriteHeader(header)
  1591  	if err != nil {
  1592  		c.Fatal(err)
  1593  	}
  1594  
  1595  	tarWriter.Close()
  1596  	tarOut.Close()
  1597  
  1598  	foo, err := os.Create(fooPath)
  1599  	if err != nil {
  1600  		c.Fatal(err)
  1601  	}
  1602  	defer foo.Close()
  1603  
  1604  	if _, err := foo.WriteString("test"); err != nil {
  1605  		c.Fatal(err)
  1606  	}
  1607  
  1608  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1609  		c.Fatal(err)
  1610  	}
  1611  
  1612  	if _, err := os.Stat(nonExistingFile); err == nil || err != nil && !os.IsNotExist(err) {
  1613  		c.Fatalf("%s shouldn't have been written and it shouldn't exist", nonExistingFile)
  1614  	}
  1615  
  1616  }
  1617  
  1618  func (s *DockerSuite) TestBuildAddBadLinksVolume(c *check.C) {
  1619  	const (
  1620  		dockerfileTemplate = `
  1621  		FROM busybox
  1622  		RUN ln -s /../../../../../../../../%s /x
  1623  		VOLUME /x
  1624  		ADD foo.txt /x/`
  1625  		targetFile = "foo.txt"
  1626  	)
  1627  	var (
  1628  		name       = "test-link-absolute-volume"
  1629  		dockerfile = ""
  1630  	)
  1631  
  1632  	tempDir, err := ioutil.TempDir("", "test-link-absolute-volume-temp-")
  1633  	if err != nil {
  1634  		c.Fatalf("failed to create temporary directory: %s", tempDir)
  1635  	}
  1636  	defer os.RemoveAll(tempDir)
  1637  
  1638  	dockerfile = fmt.Sprintf(dockerfileTemplate, tempDir)
  1639  	nonExistingFile := filepath.Join(tempDir, targetFile)
  1640  
  1641  	ctx, err := fakeContext(dockerfile, nil)
  1642  	if err != nil {
  1643  		c.Fatal(err)
  1644  	}
  1645  	defer ctx.Close()
  1646  	fooPath := filepath.Join(ctx.Dir, targetFile)
  1647  
  1648  	foo, err := os.Create(fooPath)
  1649  	if err != nil {
  1650  		c.Fatal(err)
  1651  	}
  1652  	defer foo.Close()
  1653  
  1654  	if _, err := foo.WriteString("test"); err != nil {
  1655  		c.Fatal(err)
  1656  	}
  1657  
  1658  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1659  		c.Fatal(err)
  1660  	}
  1661  
  1662  	if _, err := os.Stat(nonExistingFile); err == nil || err != nil && !os.IsNotExist(err) {
  1663  		c.Fatalf("%s shouldn't have been written and it shouldn't exist", nonExistingFile)
  1664  	}
  1665  
  1666  }
  1667  
  1668  // Issue #5270 - ensure we throw a better error than "unexpected EOF"
  1669  // when we can't access files in the context.
  1670  func (s *DockerSuite) TestBuildWithInaccessibleFilesInContext(c *check.C) {
  1671  	testRequires(c, UnixCli) // test uses chown/chmod: not available on windows
  1672  
  1673  	{
  1674  		name := "testbuildinaccessiblefiles"
  1675  		ctx, err := fakeContext("FROM scratch\nADD . /foo/", map[string]string{"fileWithoutReadAccess": "foo"})
  1676  		if err != nil {
  1677  			c.Fatal(err)
  1678  		}
  1679  		defer ctx.Close()
  1680  		// This is used to ensure we detect inaccessible files early during build in the cli client
  1681  		pathToFileWithoutReadAccess := filepath.Join(ctx.Dir, "fileWithoutReadAccess")
  1682  
  1683  		if err = os.Chown(pathToFileWithoutReadAccess, 0, 0); err != nil {
  1684  			c.Fatalf("failed to chown file to root: %s", err)
  1685  		}
  1686  		if err = os.Chmod(pathToFileWithoutReadAccess, 0700); err != nil {
  1687  			c.Fatalf("failed to chmod file to 700: %s", err)
  1688  		}
  1689  		buildCmd := exec.Command("su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name))
  1690  		buildCmd.Dir = ctx.Dir
  1691  		out, _, err := runCommandWithOutput(buildCmd)
  1692  		if err == nil {
  1693  			c.Fatalf("build should have failed: %s %s", err, out)
  1694  		}
  1695  
  1696  		// check if we've detected the failure before we started building
  1697  		if !strings.Contains(out, "no permission to read from ") {
  1698  			c.Fatalf("output should've contained the string: no permission to read from but contained: %s", out)
  1699  		}
  1700  
  1701  		if !strings.Contains(out, "Error checking context is accessible") {
  1702  			c.Fatalf("output should've contained the string: Error checking context is accessible")
  1703  		}
  1704  	}
  1705  	{
  1706  		name := "testbuildinaccessibledirectory"
  1707  		ctx, err := fakeContext("FROM scratch\nADD . /foo/", map[string]string{"directoryWeCantStat/bar": "foo"})
  1708  		if err != nil {
  1709  			c.Fatal(err)
  1710  		}
  1711  		defer ctx.Close()
  1712  		// This is used to ensure we detect inaccessible directories early during build in the cli client
  1713  		pathToDirectoryWithoutReadAccess := filepath.Join(ctx.Dir, "directoryWeCantStat")
  1714  		pathToFileInDirectoryWithoutReadAccess := filepath.Join(pathToDirectoryWithoutReadAccess, "bar")
  1715  
  1716  		if err = os.Chown(pathToDirectoryWithoutReadAccess, 0, 0); err != nil {
  1717  			c.Fatalf("failed to chown directory to root: %s", err)
  1718  		}
  1719  		if err = os.Chmod(pathToDirectoryWithoutReadAccess, 0444); err != nil {
  1720  			c.Fatalf("failed to chmod directory to 444: %s", err)
  1721  		}
  1722  		if err = os.Chmod(pathToFileInDirectoryWithoutReadAccess, 0700); err != nil {
  1723  			c.Fatalf("failed to chmod file to 700: %s", err)
  1724  		}
  1725  
  1726  		buildCmd := exec.Command("su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name))
  1727  		buildCmd.Dir = ctx.Dir
  1728  		out, _, err := runCommandWithOutput(buildCmd)
  1729  		if err == nil {
  1730  			c.Fatalf("build should have failed: %s %s", err, out)
  1731  		}
  1732  
  1733  		// check if we've detected the failure before we started building
  1734  		if !strings.Contains(out, "can't stat") {
  1735  			c.Fatalf("output should've contained the string: can't access %s", out)
  1736  		}
  1737  
  1738  		if !strings.Contains(out, "Error checking context is accessible") {
  1739  			c.Fatalf("output should've contained the string: Error checking context is accessible")
  1740  		}
  1741  
  1742  	}
  1743  	{
  1744  		name := "testlinksok"
  1745  		ctx, err := fakeContext("FROM scratch\nADD . /foo/", nil)
  1746  		if err != nil {
  1747  			c.Fatal(err)
  1748  		}
  1749  		defer ctx.Close()
  1750  
  1751  		target := "../../../../../../../../../../../../../../../../../../../azA"
  1752  		if err := os.Symlink(filepath.Join(ctx.Dir, "g"), target); err != nil {
  1753  			c.Fatal(err)
  1754  		}
  1755  		defer os.Remove(target)
  1756  		// This is used to ensure we don't follow links when checking if everything in the context is accessible
  1757  		// This test doesn't require that we run commands as an unprivileged user
  1758  		if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1759  			c.Fatal(err)
  1760  		}
  1761  	}
  1762  	{
  1763  		name := "testbuildignoredinaccessible"
  1764  		ctx, err := fakeContext("FROM scratch\nADD . /foo/",
  1765  			map[string]string{
  1766  				"directoryWeCantStat/bar": "foo",
  1767  				".dockerignore":           "directoryWeCantStat",
  1768  			})
  1769  		if err != nil {
  1770  			c.Fatal(err)
  1771  		}
  1772  		defer ctx.Close()
  1773  		// This is used to ensure we don't try to add inaccessible files when they are ignored by a .dockerignore pattern
  1774  		pathToDirectoryWithoutReadAccess := filepath.Join(ctx.Dir, "directoryWeCantStat")
  1775  		pathToFileInDirectoryWithoutReadAccess := filepath.Join(pathToDirectoryWithoutReadAccess, "bar")
  1776  		if err = os.Chown(pathToDirectoryWithoutReadAccess, 0, 0); err != nil {
  1777  			c.Fatalf("failed to chown directory to root: %s", err)
  1778  		}
  1779  		if err = os.Chmod(pathToDirectoryWithoutReadAccess, 0444); err != nil {
  1780  			c.Fatalf("failed to chmod directory to 755: %s", err)
  1781  		}
  1782  		if err = os.Chmod(pathToFileInDirectoryWithoutReadAccess, 0700); err != nil {
  1783  			c.Fatalf("failed to chmod file to 444: %s", err)
  1784  		}
  1785  
  1786  		buildCmd := exec.Command("su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name))
  1787  		buildCmd.Dir = ctx.Dir
  1788  		if out, _, err := runCommandWithOutput(buildCmd); err != nil {
  1789  			c.Fatalf("build should have worked: %s %s", err, out)
  1790  		}
  1791  
  1792  	}
  1793  }
  1794  
  1795  func (s *DockerSuite) TestBuildForceRm(c *check.C) {
  1796  	containerCountBefore, err := getContainerCount()
  1797  	if err != nil {
  1798  		c.Fatalf("failed to get the container count: %s", err)
  1799  	}
  1800  	name := "testbuildforcerm"
  1801  	ctx, err := fakeContext("FROM scratch\nRUN true\nRUN thiswillfail", nil)
  1802  	if err != nil {
  1803  		c.Fatal(err)
  1804  	}
  1805  	defer ctx.Close()
  1806  
  1807  	buildCmd := exec.Command(dockerBinary, "build", "-t", name, "--force-rm", ".")
  1808  	buildCmd.Dir = ctx.Dir
  1809  	if out, _, err := runCommandWithOutput(buildCmd); err == nil {
  1810  		c.Fatalf("failed to build the image: %s, %v", out, err)
  1811  	}
  1812  
  1813  	containerCountAfter, err := getContainerCount()
  1814  	if err != nil {
  1815  		c.Fatalf("failed to get the container count: %s", err)
  1816  	}
  1817  
  1818  	if containerCountBefore != containerCountAfter {
  1819  		c.Fatalf("--force-rm shouldn't have left containers behind")
  1820  	}
  1821  
  1822  }
  1823  
  1824  // Test that an infinite sleep during a build is killed if the client disconnects.
  1825  // This test is fairly hairy because there are lots of ways to race.
  1826  // Strategy:
  1827  // * Monitor the output of docker events starting from before
  1828  // * Run a 1-year-long sleep from a docker build.
  1829  // * When docker events sees container start, close the "docker build" command
  1830  // * Wait for docker events to emit a dying event.
  1831  func (s *DockerSuite) TestBuildCancelationKillsSleep(c *check.C) {
  1832  	var wg sync.WaitGroup
  1833  	defer wg.Wait()
  1834  
  1835  	name := "testbuildcancelation"
  1836  
  1837  	// (Note: one year, will never finish)
  1838  	ctx, err := fakeContext("FROM busybox\nRUN sleep 31536000", nil)
  1839  	if err != nil {
  1840  		c.Fatal(err)
  1841  	}
  1842  	defer ctx.Close()
  1843  
  1844  	finish := make(chan struct{})
  1845  	defer close(finish)
  1846  
  1847  	eventStart := make(chan struct{})
  1848  	eventDie := make(chan struct{})
  1849  	containerID := make(chan string)
  1850  
  1851  	startEpoch := daemonTime(c).Unix()
  1852  
  1853  	wg.Add(1)
  1854  	// Goroutine responsible for watching start/die events from `docker events`
  1855  	go func() {
  1856  		defer wg.Done()
  1857  		// Watch for events since epoch.
  1858  		eventsCmd := exec.Command(
  1859  			dockerBinary, "events",
  1860  			"--since", strconv.FormatInt(startEpoch, 10))
  1861  		stdout, err := eventsCmd.StdoutPipe()
  1862  		err = eventsCmd.Start()
  1863  		if err != nil {
  1864  			c.Fatalf("failed to start 'docker events': %s", err)
  1865  		}
  1866  
  1867  		go func() {
  1868  			<-finish
  1869  			eventsCmd.Process.Kill()
  1870  		}()
  1871  
  1872  		cid := <-containerID
  1873  
  1874  		matchStart := regexp.MustCompile(cid + `(.*) start$`)
  1875  		matchDie := regexp.MustCompile(cid + `(.*) die$`)
  1876  
  1877  		//
  1878  		// Read lines of `docker events` looking for container start and stop.
  1879  		//
  1880  		scanner := bufio.NewScanner(stdout)
  1881  		for scanner.Scan() {
  1882  			switch {
  1883  			case matchStart.MatchString(scanner.Text()):
  1884  				close(eventStart)
  1885  			case matchDie.MatchString(scanner.Text()):
  1886  				close(eventDie)
  1887  			}
  1888  		}
  1889  
  1890  		err = eventsCmd.Wait()
  1891  		if err != nil && !IsKilled(err) {
  1892  			c.Fatalf("docker events had bad exit status: %s", err)
  1893  		}
  1894  	}()
  1895  
  1896  	buildCmd := exec.Command(dockerBinary, "build", "-t", name, ".")
  1897  	buildCmd.Dir = ctx.Dir
  1898  
  1899  	stdoutBuild, err := buildCmd.StdoutPipe()
  1900  	err = buildCmd.Start()
  1901  	if err != nil {
  1902  		c.Fatalf("failed to run build: %s", err)
  1903  	}
  1904  
  1905  	matchCID := regexp.MustCompile("Running in ")
  1906  	scanner := bufio.NewScanner(stdoutBuild)
  1907  	for scanner.Scan() {
  1908  		line := scanner.Text()
  1909  		if ok := matchCID.MatchString(line); ok {
  1910  			containerID <- line[len(line)-12:]
  1911  			break
  1912  		}
  1913  	}
  1914  
  1915  	select {
  1916  	case <-time.After(5 * time.Second):
  1917  		c.Fatal("failed to observe build container start in timely fashion")
  1918  	case <-eventStart:
  1919  		// Proceeds from here when we see the container fly past in the
  1920  		// output of "docker events".
  1921  		// Now we know the container is running.
  1922  	}
  1923  
  1924  	// Send a kill to the `docker build` command.
  1925  	// Causes the underlying build to be cancelled due to socket close.
  1926  	err = buildCmd.Process.Kill()
  1927  	if err != nil {
  1928  		c.Fatalf("error killing build command: %s", err)
  1929  	}
  1930  
  1931  	// Get the exit status of `docker build`, check it exited because killed.
  1932  	err = buildCmd.Wait()
  1933  	if err != nil && !IsKilled(err) {
  1934  		c.Fatalf("wait failed during build run: %T %s", err, err)
  1935  	}
  1936  
  1937  	select {
  1938  	case <-time.After(5 * time.Second):
  1939  		// If we don't get here in a timely fashion, it wasn't killed.
  1940  		c.Fatal("container cancel did not succeed")
  1941  	case <-eventDie:
  1942  		// We saw the container shut down in the `docker events` stream,
  1943  		// as expected.
  1944  	}
  1945  
  1946  }
  1947  
  1948  func (s *DockerSuite) TestBuildRm(c *check.C) {
  1949  	name := "testbuildrm"
  1950  	ctx, err := fakeContext("FROM scratch\nADD foo /\nADD foo /", map[string]string{"foo": "bar"})
  1951  	if err != nil {
  1952  		c.Fatal(err)
  1953  	}
  1954  	defer ctx.Close()
  1955  	{
  1956  		containerCountBefore, err := getContainerCount()
  1957  		if err != nil {
  1958  			c.Fatalf("failed to get the container count: %s", err)
  1959  		}
  1960  
  1961  		out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "--rm", "-t", name, ".")
  1962  
  1963  		if err != nil {
  1964  			c.Fatal("failed to build the image", out)
  1965  		}
  1966  
  1967  		containerCountAfter, err := getContainerCount()
  1968  		if err != nil {
  1969  			c.Fatalf("failed to get the container count: %s", err)
  1970  		}
  1971  
  1972  		if containerCountBefore != containerCountAfter {
  1973  			c.Fatalf("-rm shouldn't have left containers behind")
  1974  		}
  1975  		deleteImages(name)
  1976  	}
  1977  
  1978  	{
  1979  		containerCountBefore, err := getContainerCount()
  1980  		if err != nil {
  1981  			c.Fatalf("failed to get the container count: %s", err)
  1982  		}
  1983  
  1984  		out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-t", name, ".")
  1985  
  1986  		if err != nil {
  1987  			c.Fatal("failed to build the image", out)
  1988  		}
  1989  
  1990  		containerCountAfter, err := getContainerCount()
  1991  		if err != nil {
  1992  			c.Fatalf("failed to get the container count: %s", err)
  1993  		}
  1994  
  1995  		if containerCountBefore != containerCountAfter {
  1996  			c.Fatalf("--rm shouldn't have left containers behind")
  1997  		}
  1998  		deleteImages(name)
  1999  	}
  2000  
  2001  	{
  2002  		containerCountBefore, err := getContainerCount()
  2003  		if err != nil {
  2004  			c.Fatalf("failed to get the container count: %s", err)
  2005  		}
  2006  
  2007  		out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "--rm=false", "-t", name, ".")
  2008  
  2009  		if err != nil {
  2010  			c.Fatal("failed to build the image", out)
  2011  		}
  2012  
  2013  		containerCountAfter, err := getContainerCount()
  2014  		if err != nil {
  2015  			c.Fatalf("failed to get the container count: %s", err)
  2016  		}
  2017  
  2018  		if containerCountBefore == containerCountAfter {
  2019  			c.Fatalf("--rm=false should have left containers behind")
  2020  		}
  2021  		deleteImages(name)
  2022  
  2023  	}
  2024  
  2025  }
  2026  
  2027  func (s *DockerSuite) TestBuildWithVolumes(c *check.C) {
  2028  	var (
  2029  		result   map[string]map[string]struct{}
  2030  		name     = "testbuildvolumes"
  2031  		emptyMap = make(map[string]struct{})
  2032  		expected = map[string]map[string]struct{}{
  2033  			"/test1":  emptyMap,
  2034  			"/test2":  emptyMap,
  2035  			"/test3":  emptyMap,
  2036  			"/test4":  emptyMap,
  2037  			"/test5":  emptyMap,
  2038  			"/test6":  emptyMap,
  2039  			"[/test7": emptyMap,
  2040  			"/test8]": emptyMap,
  2041  		}
  2042  	)
  2043  	_, err := buildImage(name,
  2044  		`FROM scratch
  2045  		VOLUME /test1
  2046  		VOLUME /test2
  2047      VOLUME /test3 /test4
  2048      VOLUME ["/test5", "/test6"]
  2049      VOLUME [/test7 /test8]
  2050      `,
  2051  		true)
  2052  	if err != nil {
  2053  		c.Fatal(err)
  2054  	}
  2055  	res, err := inspectFieldJSON(name, "Config.Volumes")
  2056  	if err != nil {
  2057  		c.Fatal(err)
  2058  	}
  2059  
  2060  	err = unmarshalJSON([]byte(res), &result)
  2061  	if err != nil {
  2062  		c.Fatal(err)
  2063  	}
  2064  
  2065  	equal := reflect.DeepEqual(&result, &expected)
  2066  
  2067  	if !equal {
  2068  		c.Fatalf("Volumes %s, expected %s", result, expected)
  2069  	}
  2070  
  2071  }
  2072  
  2073  func (s *DockerSuite) TestBuildMaintainer(c *check.C) {
  2074  	name := "testbuildmaintainer"
  2075  	expected := "dockerio"
  2076  	_, err := buildImage(name,
  2077  		`FROM scratch
  2078          MAINTAINER dockerio`,
  2079  		true)
  2080  	if err != nil {
  2081  		c.Fatal(err)
  2082  	}
  2083  	res, err := inspectField(name, "Author")
  2084  	if err != nil {
  2085  		c.Fatal(err)
  2086  	}
  2087  	if res != expected {
  2088  		c.Fatalf("Maintainer %s, expected %s", res, expected)
  2089  	}
  2090  }
  2091  
  2092  func (s *DockerSuite) TestBuildUser(c *check.C) {
  2093  	name := "testbuilduser"
  2094  	expected := "dockerio"
  2095  	_, err := buildImage(name,
  2096  		`FROM busybox
  2097  		RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  2098  		USER dockerio
  2099  		RUN [ $(whoami) = 'dockerio' ]`,
  2100  		true)
  2101  	if err != nil {
  2102  		c.Fatal(err)
  2103  	}
  2104  	res, err := inspectField(name, "Config.User")
  2105  	if err != nil {
  2106  		c.Fatal(err)
  2107  	}
  2108  	if res != expected {
  2109  		c.Fatalf("User %s, expected %s", res, expected)
  2110  	}
  2111  }
  2112  
  2113  func (s *DockerSuite) TestBuildRelativeWorkdir(c *check.C) {
  2114  	name := "testbuildrelativeworkdir"
  2115  	expected := "/test2/test3"
  2116  	_, err := buildImage(name,
  2117  		`FROM busybox
  2118  		RUN [ "$PWD" = '/' ]
  2119  		WORKDIR test1
  2120  		RUN [ "$PWD" = '/test1' ]
  2121  		WORKDIR /test2
  2122  		RUN [ "$PWD" = '/test2' ]
  2123  		WORKDIR test3
  2124  		RUN [ "$PWD" = '/test2/test3' ]`,
  2125  		true)
  2126  	if err != nil {
  2127  		c.Fatal(err)
  2128  	}
  2129  	res, err := inspectField(name, "Config.WorkingDir")
  2130  	if err != nil {
  2131  		c.Fatal(err)
  2132  	}
  2133  	if res != expected {
  2134  		c.Fatalf("Workdir %s, expected %s", res, expected)
  2135  	}
  2136  }
  2137  
  2138  func (s *DockerSuite) TestBuildWorkdirWithEnvVariables(c *check.C) {
  2139  	name := "testbuildworkdirwithenvvariables"
  2140  	expected := "/test1/test2"
  2141  	_, err := buildImage(name,
  2142  		`FROM busybox
  2143  		ENV DIRPATH /test1
  2144  		ENV SUBDIRNAME test2
  2145  		WORKDIR $DIRPATH
  2146  		WORKDIR $SUBDIRNAME/$MISSING_VAR`,
  2147  		true)
  2148  	if err != nil {
  2149  		c.Fatal(err)
  2150  	}
  2151  	res, err := inspectField(name, "Config.WorkingDir")
  2152  	if err != nil {
  2153  		c.Fatal(err)
  2154  	}
  2155  	if res != expected {
  2156  		c.Fatalf("Workdir %s, expected %s", res, expected)
  2157  	}
  2158  }
  2159  
  2160  func (s *DockerSuite) TestBuildRelativeCopy(c *check.C) {
  2161  	name := "testbuildrelativecopy"
  2162  	dockerfile := `
  2163  		FROM busybox
  2164  			WORKDIR /test1
  2165  			WORKDIR test2
  2166  			RUN [ "$PWD" = '/test1/test2' ]
  2167  			COPY foo ./
  2168  			RUN [ "$(cat /test1/test2/foo)" = 'hello' ]
  2169  			ADD foo ./bar/baz
  2170  			RUN [ "$(cat /test1/test2/bar/baz)" = 'hello' ]
  2171  			COPY foo ./bar/baz2
  2172  			RUN [ "$(cat /test1/test2/bar/baz2)" = 'hello' ]
  2173  			WORKDIR ..
  2174  			COPY foo ./
  2175  			RUN [ "$(cat /test1/foo)" = 'hello' ]
  2176  			COPY foo /test3/
  2177  			RUN [ "$(cat /test3/foo)" = 'hello' ]
  2178  			WORKDIR /test4
  2179  			COPY . .
  2180  			RUN [ "$(cat /test4/foo)" = 'hello' ]
  2181  			WORKDIR /test5/test6
  2182  			COPY foo ../
  2183  			RUN [ "$(cat /test5/foo)" = 'hello' ]
  2184  			`
  2185  	ctx, err := fakeContext(dockerfile, map[string]string{
  2186  		"foo": "hello",
  2187  	})
  2188  	defer ctx.Close()
  2189  	if err != nil {
  2190  		c.Fatal(err)
  2191  	}
  2192  	_, err = buildImageFromContext(name, ctx, false)
  2193  	if err != nil {
  2194  		c.Fatal(err)
  2195  	}
  2196  }
  2197  
  2198  func (s *DockerSuite) TestBuildEnv(c *check.C) {
  2199  	name := "testbuildenv"
  2200  	expected := "[PATH=/test:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PORT=2375]"
  2201  	_, err := buildImage(name,
  2202  		`FROM busybox
  2203  		ENV PATH /test:$PATH
  2204          ENV PORT 2375
  2205  		RUN [ $(env | grep PORT) = 'PORT=2375' ]`,
  2206  		true)
  2207  	if err != nil {
  2208  		c.Fatal(err)
  2209  	}
  2210  	res, err := inspectField(name, "Config.Env")
  2211  	if err != nil {
  2212  		c.Fatal(err)
  2213  	}
  2214  	if res != expected {
  2215  		c.Fatalf("Env %s, expected %s", res, expected)
  2216  	}
  2217  }
  2218  
  2219  func (s *DockerSuite) TestBuildContextCleanup(c *check.C) {
  2220  	testRequires(c, SameHostDaemon)
  2221  
  2222  	name := "testbuildcontextcleanup"
  2223  	entries, err := ioutil.ReadDir("/var/lib/docker/tmp")
  2224  	if err != nil {
  2225  		c.Fatalf("failed to list contents of tmp dir: %s", err)
  2226  	}
  2227  	_, err = buildImage(name,
  2228  		`FROM scratch
  2229          ENTRYPOINT ["/bin/echo"]`,
  2230  		true)
  2231  	if err != nil {
  2232  		c.Fatal(err)
  2233  	}
  2234  	entriesFinal, err := ioutil.ReadDir("/var/lib/docker/tmp")
  2235  	if err != nil {
  2236  		c.Fatalf("failed to list contents of tmp dir: %s", err)
  2237  	}
  2238  	if err = compareDirectoryEntries(entries, entriesFinal); err != nil {
  2239  		c.Fatalf("context should have been deleted, but wasn't")
  2240  	}
  2241  
  2242  }
  2243  
  2244  func (s *DockerSuite) TestBuildContextCleanupFailedBuild(c *check.C) {
  2245  	testRequires(c, SameHostDaemon)
  2246  
  2247  	name := "testbuildcontextcleanup"
  2248  	entries, err := ioutil.ReadDir("/var/lib/docker/tmp")
  2249  	if err != nil {
  2250  		c.Fatalf("failed to list contents of tmp dir: %s", err)
  2251  	}
  2252  	_, err = buildImage(name,
  2253  		`FROM scratch
  2254  	RUN /non/existing/command`,
  2255  		true)
  2256  	if err == nil {
  2257  		c.Fatalf("expected build to fail, but it didn't")
  2258  	}
  2259  	entriesFinal, err := ioutil.ReadDir("/var/lib/docker/tmp")
  2260  	if err != nil {
  2261  		c.Fatalf("failed to list contents of tmp dir: %s", err)
  2262  	}
  2263  	if err = compareDirectoryEntries(entries, entriesFinal); err != nil {
  2264  		c.Fatalf("context should have been deleted, but wasn't")
  2265  	}
  2266  
  2267  }
  2268  
  2269  func (s *DockerSuite) TestBuildCmd(c *check.C) {
  2270  	name := "testbuildcmd"
  2271  	expected := "{[/bin/echo Hello World]}"
  2272  	_, err := buildImage(name,
  2273  		`FROM scratch
  2274          CMD ["/bin/echo", "Hello World"]`,
  2275  		true)
  2276  	if err != nil {
  2277  		c.Fatal(err)
  2278  	}
  2279  	res, err := inspectField(name, "Config.Cmd")
  2280  	if err != nil {
  2281  		c.Fatal(err)
  2282  	}
  2283  	if res != expected {
  2284  		c.Fatalf("Cmd %s, expected %s", res, expected)
  2285  	}
  2286  }
  2287  
  2288  func (s *DockerSuite) TestBuildExpose(c *check.C) {
  2289  	name := "testbuildexpose"
  2290  	expected := "map[2375/tcp:{}]"
  2291  	_, err := buildImage(name,
  2292  		`FROM scratch
  2293          EXPOSE 2375`,
  2294  		true)
  2295  	if err != nil {
  2296  		c.Fatal(err)
  2297  	}
  2298  	res, err := inspectField(name, "Config.ExposedPorts")
  2299  	if err != nil {
  2300  		c.Fatal(err)
  2301  	}
  2302  	if res != expected {
  2303  		c.Fatalf("Exposed ports %s, expected %s", res, expected)
  2304  	}
  2305  }
  2306  
  2307  func (s *DockerSuite) TestBuildExposeMorePorts(c *check.C) {
  2308  	// start building docker file with a large number of ports
  2309  	portList := make([]string, 50)
  2310  	line := make([]string, 100)
  2311  	expectedPorts := make([]int, len(portList)*len(line))
  2312  	for i := 0; i < len(portList); i++ {
  2313  		for j := 0; j < len(line); j++ {
  2314  			p := i*len(line) + j + 1
  2315  			line[j] = strconv.Itoa(p)
  2316  			expectedPorts[p-1] = p
  2317  		}
  2318  		if i == len(portList)-1 {
  2319  			portList[i] = strings.Join(line, " ")
  2320  		} else {
  2321  			portList[i] = strings.Join(line, " ") + ` \`
  2322  		}
  2323  	}
  2324  
  2325  	dockerfile := `FROM scratch
  2326  	EXPOSE {{range .}} {{.}}
  2327  	{{end}}`
  2328  	tmpl := template.Must(template.New("dockerfile").Parse(dockerfile))
  2329  	buf := bytes.NewBuffer(nil)
  2330  	tmpl.Execute(buf, portList)
  2331  
  2332  	name := "testbuildexpose"
  2333  	_, err := buildImage(name, buf.String(), true)
  2334  	if err != nil {
  2335  		c.Fatal(err)
  2336  	}
  2337  
  2338  	// check if all the ports are saved inside Config.ExposedPorts
  2339  	res, err := inspectFieldJSON(name, "Config.ExposedPorts")
  2340  	if err != nil {
  2341  		c.Fatal(err)
  2342  	}
  2343  	var exposedPorts map[string]interface{}
  2344  	if err := json.Unmarshal([]byte(res), &exposedPorts); err != nil {
  2345  		c.Fatal(err)
  2346  	}
  2347  
  2348  	for _, p := range expectedPorts {
  2349  		ep := fmt.Sprintf("%d/tcp", p)
  2350  		if _, ok := exposedPorts[ep]; !ok {
  2351  			c.Errorf("Port(%s) is not exposed", ep)
  2352  		} else {
  2353  			delete(exposedPorts, ep)
  2354  		}
  2355  	}
  2356  	if len(exposedPorts) != 0 {
  2357  		c.Errorf("Unexpected extra exposed ports %v", exposedPorts)
  2358  	}
  2359  }
  2360  
  2361  func (s *DockerSuite) TestBuildExposeOrder(c *check.C) {
  2362  	buildID := func(name, exposed string) string {
  2363  		_, err := buildImage(name, fmt.Sprintf(`FROM scratch
  2364  		EXPOSE %s`, exposed), true)
  2365  		if err != nil {
  2366  			c.Fatal(err)
  2367  		}
  2368  		id, err := inspectField(name, "Id")
  2369  		if err != nil {
  2370  			c.Fatal(err)
  2371  		}
  2372  		return id
  2373  	}
  2374  
  2375  	id1 := buildID("testbuildexpose1", "80 2375")
  2376  	id2 := buildID("testbuildexpose2", "2375 80")
  2377  	if id1 != id2 {
  2378  		c.Errorf("EXPOSE should invalidate the cache only when ports actually changed")
  2379  	}
  2380  }
  2381  
  2382  func (s *DockerSuite) TestBuildExposeUpperCaseProto(c *check.C) {
  2383  	name := "testbuildexposeuppercaseproto"
  2384  	expected := "map[5678/udp:{}]"
  2385  	_, err := buildImage(name,
  2386  		`FROM scratch
  2387          EXPOSE 5678/UDP`,
  2388  		true)
  2389  	if err != nil {
  2390  		c.Fatal(err)
  2391  	}
  2392  	res, err := inspectField(name, "Config.ExposedPorts")
  2393  	if err != nil {
  2394  		c.Fatal(err)
  2395  	}
  2396  	if res != expected {
  2397  		c.Fatalf("Exposed ports %s, expected %s", res, expected)
  2398  	}
  2399  }
  2400  
  2401  func (s *DockerSuite) TestBuildExposeHostPort(c *check.C) {
  2402  	// start building docker file with ip:hostPort:containerPort
  2403  	name := "testbuildexpose"
  2404  	expected := "map[5678/tcp:{}]"
  2405  	_, out, err := buildImageWithOut(name,
  2406  		`FROM scratch
  2407          EXPOSE 192.168.1.2:2375:5678`,
  2408  		true)
  2409  	if err != nil {
  2410  		c.Fatal(err)
  2411  	}
  2412  
  2413  	if !strings.Contains(out, "to map host ports to container ports (ip:hostPort:containerPort) is deprecated.") {
  2414  		c.Fatal("Missing warning message")
  2415  	}
  2416  
  2417  	res, err := inspectField(name, "Config.ExposedPorts")
  2418  	if err != nil {
  2419  		c.Fatal(err)
  2420  	}
  2421  	if res != expected {
  2422  		c.Fatalf("Exposed ports %s, expected %s", res, expected)
  2423  	}
  2424  }
  2425  
  2426  func (s *DockerSuite) TestBuildEmptyEntrypointInheritance(c *check.C) {
  2427  	name := "testbuildentrypointinheritance"
  2428  	name2 := "testbuildentrypointinheritance2"
  2429  
  2430  	_, err := buildImage(name,
  2431  		`FROM busybox
  2432          ENTRYPOINT ["/bin/echo"]`,
  2433  		true)
  2434  	if err != nil {
  2435  		c.Fatal(err)
  2436  	}
  2437  	res, err := inspectField(name, "Config.Entrypoint")
  2438  	if err != nil {
  2439  		c.Fatal(err)
  2440  	}
  2441  
  2442  	expected := "{[/bin/echo]}"
  2443  	if res != expected {
  2444  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  2445  	}
  2446  
  2447  	_, err = buildImage(name2,
  2448  		fmt.Sprintf(`FROM %s
  2449          ENTRYPOINT []`, name),
  2450  		true)
  2451  	if err != nil {
  2452  		c.Fatal(err)
  2453  	}
  2454  	res, err = inspectField(name2, "Config.Entrypoint")
  2455  	if err != nil {
  2456  		c.Fatal(err)
  2457  	}
  2458  
  2459  	expected = "{[]}"
  2460  
  2461  	if res != expected {
  2462  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  2463  	}
  2464  
  2465  }
  2466  
  2467  func (s *DockerSuite) TestBuildEmptyEntrypoint(c *check.C) {
  2468  	name := "testbuildentrypoint"
  2469  	expected := "{[]}"
  2470  
  2471  	_, err := buildImage(name,
  2472  		`FROM busybox
  2473          ENTRYPOINT []`,
  2474  		true)
  2475  	if err != nil {
  2476  		c.Fatal(err)
  2477  	}
  2478  	res, err := inspectField(name, "Config.Entrypoint")
  2479  	if err != nil {
  2480  		c.Fatal(err)
  2481  	}
  2482  	if res != expected {
  2483  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  2484  	}
  2485  
  2486  }
  2487  
  2488  func (s *DockerSuite) TestBuildEntrypoint(c *check.C) {
  2489  	name := "testbuildentrypoint"
  2490  	expected := "{[/bin/echo]}"
  2491  	_, err := buildImage(name,
  2492  		`FROM scratch
  2493          ENTRYPOINT ["/bin/echo"]`,
  2494  		true)
  2495  	if err != nil {
  2496  		c.Fatal(err)
  2497  	}
  2498  	res, err := inspectField(name, "Config.Entrypoint")
  2499  	if err != nil {
  2500  		c.Fatal(err)
  2501  	}
  2502  	if res != expected {
  2503  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  2504  	}
  2505  
  2506  }
  2507  
  2508  // #6445 ensure ONBUILD triggers aren't committed to grandchildren
  2509  func (s *DockerSuite) TestBuildOnBuildLimitedInheritence(c *check.C) {
  2510  	var (
  2511  		out2, out3 string
  2512  	)
  2513  	{
  2514  		name1 := "testonbuildtrigger1"
  2515  		dockerfile1 := `
  2516  		FROM busybox
  2517  		RUN echo "GRANDPARENT"
  2518  		ONBUILD RUN echo "ONBUILD PARENT"
  2519  		`
  2520  		ctx, err := fakeContext(dockerfile1, nil)
  2521  		if err != nil {
  2522  			c.Fatal(err)
  2523  		}
  2524  		defer ctx.Close()
  2525  
  2526  		out1, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-t", name1, ".")
  2527  		if err != nil {
  2528  			c.Fatalf("build failed to complete: %s, %v", out1, err)
  2529  		}
  2530  	}
  2531  	{
  2532  		name2 := "testonbuildtrigger2"
  2533  		dockerfile2 := `
  2534  		FROM testonbuildtrigger1
  2535  		`
  2536  		ctx, err := fakeContext(dockerfile2, nil)
  2537  		if err != nil {
  2538  			c.Fatal(err)
  2539  		}
  2540  		defer ctx.Close()
  2541  
  2542  		out2, _, err = dockerCmdInDir(c, ctx.Dir, "build", "-t", name2, ".")
  2543  		if err != nil {
  2544  			c.Fatalf("build failed to complete: %s, %v", out2, err)
  2545  		}
  2546  	}
  2547  	{
  2548  		name3 := "testonbuildtrigger3"
  2549  		dockerfile3 := `
  2550  		FROM testonbuildtrigger2
  2551  		`
  2552  		ctx, err := fakeContext(dockerfile3, nil)
  2553  		if err != nil {
  2554  			c.Fatal(err)
  2555  		}
  2556  		defer ctx.Close()
  2557  
  2558  		out3, _, err = dockerCmdInDir(c, ctx.Dir, "build", "-t", name3, ".")
  2559  		if err != nil {
  2560  			c.Fatalf("build failed to complete: %s, %v", out3, err)
  2561  		}
  2562  
  2563  	}
  2564  
  2565  	// ONBUILD should be run in second build.
  2566  	if !strings.Contains(out2, "ONBUILD PARENT") {
  2567  		c.Fatalf("ONBUILD instruction did not run in child of ONBUILD parent")
  2568  	}
  2569  
  2570  	// ONBUILD should *not* be run in third build.
  2571  	if strings.Contains(out3, "ONBUILD PARENT") {
  2572  		c.Fatalf("ONBUILD instruction ran in grandchild of ONBUILD parent")
  2573  	}
  2574  
  2575  }
  2576  
  2577  func (s *DockerSuite) TestBuildWithCache(c *check.C) {
  2578  	name := "testbuildwithcache"
  2579  	id1, err := buildImage(name,
  2580  		`FROM scratch
  2581  		MAINTAINER dockerio
  2582  		EXPOSE 5432
  2583          ENTRYPOINT ["/bin/echo"]`,
  2584  		true)
  2585  	if err != nil {
  2586  		c.Fatal(err)
  2587  	}
  2588  	id2, err := buildImage(name,
  2589  		`FROM scratch
  2590  		MAINTAINER dockerio
  2591  		EXPOSE 5432
  2592          ENTRYPOINT ["/bin/echo"]`,
  2593  		true)
  2594  	if err != nil {
  2595  		c.Fatal(err)
  2596  	}
  2597  	if id1 != id2 {
  2598  		c.Fatal("The cache should have been used but hasn't.")
  2599  	}
  2600  }
  2601  
  2602  func (s *DockerSuite) TestBuildWithoutCache(c *check.C) {
  2603  	name := "testbuildwithoutcache"
  2604  	name2 := "testbuildwithoutcache2"
  2605  	id1, err := buildImage(name,
  2606  		`FROM scratch
  2607  		MAINTAINER dockerio
  2608  		EXPOSE 5432
  2609          ENTRYPOINT ["/bin/echo"]`,
  2610  		true)
  2611  	if err != nil {
  2612  		c.Fatal(err)
  2613  	}
  2614  
  2615  	id2, err := buildImage(name2,
  2616  		`FROM scratch
  2617  		MAINTAINER dockerio
  2618  		EXPOSE 5432
  2619          ENTRYPOINT ["/bin/echo"]`,
  2620  		false)
  2621  	if err != nil {
  2622  		c.Fatal(err)
  2623  	}
  2624  	if id1 == id2 {
  2625  		c.Fatal("The cache should have been invalided but hasn't.")
  2626  	}
  2627  }
  2628  
  2629  func (s *DockerSuite) TestBuildConditionalCache(c *check.C) {
  2630  	name := "testbuildconditionalcache"
  2631  
  2632  	dockerfile := `
  2633  		FROM busybox
  2634          ADD foo /tmp/`
  2635  	ctx, err := fakeContext(dockerfile, map[string]string{
  2636  		"foo": "hello",
  2637  	})
  2638  	if err != nil {
  2639  		c.Fatal(err)
  2640  	}
  2641  	defer ctx.Close()
  2642  
  2643  	id1, err := buildImageFromContext(name, ctx, true)
  2644  	if err != nil {
  2645  		c.Fatalf("Error building #1: %s", err)
  2646  	}
  2647  
  2648  	if err := ctx.Add("foo", "bye"); err != nil {
  2649  		c.Fatalf("Error modifying foo: %s", err)
  2650  	}
  2651  
  2652  	id2, err := buildImageFromContext(name, ctx, false)
  2653  	if err != nil {
  2654  		c.Fatalf("Error building #2: %s", err)
  2655  	}
  2656  	if id2 == id1 {
  2657  		c.Fatal("Should not have used the cache")
  2658  	}
  2659  
  2660  	id3, err := buildImageFromContext(name, ctx, true)
  2661  	if err != nil {
  2662  		c.Fatalf("Error building #3: %s", err)
  2663  	}
  2664  	if id3 != id2 {
  2665  		c.Fatal("Should have used the cache")
  2666  	}
  2667  }
  2668  
  2669  func (s *DockerSuite) TestBuildADDLocalFileWithCache(c *check.C) {
  2670  	name := "testbuildaddlocalfilewithcache"
  2671  	name2 := "testbuildaddlocalfilewithcache2"
  2672  	dockerfile := `
  2673  		FROM busybox
  2674          MAINTAINER dockerio
  2675          ADD foo /usr/lib/bla/bar
  2676  		RUN [ "$(cat /usr/lib/bla/bar)" = "hello" ]`
  2677  	ctx, err := fakeContext(dockerfile, map[string]string{
  2678  		"foo": "hello",
  2679  	})
  2680  	defer ctx.Close()
  2681  	if err != nil {
  2682  		c.Fatal(err)
  2683  	}
  2684  	id1, err := buildImageFromContext(name, ctx, true)
  2685  	if err != nil {
  2686  		c.Fatal(err)
  2687  	}
  2688  	id2, err := buildImageFromContext(name2, ctx, true)
  2689  	if err != nil {
  2690  		c.Fatal(err)
  2691  	}
  2692  	if id1 != id2 {
  2693  		c.Fatal("The cache should have been used but hasn't.")
  2694  	}
  2695  }
  2696  
  2697  func (s *DockerSuite) TestBuildADDMultipleLocalFileWithCache(c *check.C) {
  2698  	name := "testbuildaddmultiplelocalfilewithcache"
  2699  	name2 := "testbuildaddmultiplelocalfilewithcache2"
  2700  	dockerfile := `
  2701  		FROM busybox
  2702          MAINTAINER dockerio
  2703          ADD foo Dockerfile /usr/lib/bla/
  2704  		RUN [ "$(cat /usr/lib/bla/foo)" = "hello" ]`
  2705  	ctx, err := fakeContext(dockerfile, map[string]string{
  2706  		"foo": "hello",
  2707  	})
  2708  	defer ctx.Close()
  2709  	if err != nil {
  2710  		c.Fatal(err)
  2711  	}
  2712  	id1, err := buildImageFromContext(name, ctx, true)
  2713  	if err != nil {
  2714  		c.Fatal(err)
  2715  	}
  2716  	id2, err := buildImageFromContext(name2, ctx, true)
  2717  	if err != nil {
  2718  		c.Fatal(err)
  2719  	}
  2720  	if id1 != id2 {
  2721  		c.Fatal("The cache should have been used but hasn't.")
  2722  	}
  2723  }
  2724  
  2725  func (s *DockerSuite) TestBuildADDLocalFileWithoutCache(c *check.C) {
  2726  	name := "testbuildaddlocalfilewithoutcache"
  2727  	name2 := "testbuildaddlocalfilewithoutcache2"
  2728  	dockerfile := `
  2729  		FROM busybox
  2730          MAINTAINER dockerio
  2731          ADD foo /usr/lib/bla/bar
  2732  		RUN [ "$(cat /usr/lib/bla/bar)" = "hello" ]`
  2733  	ctx, err := fakeContext(dockerfile, map[string]string{
  2734  		"foo": "hello",
  2735  	})
  2736  	defer ctx.Close()
  2737  	if err != nil {
  2738  		c.Fatal(err)
  2739  	}
  2740  	id1, err := buildImageFromContext(name, ctx, true)
  2741  	if err != nil {
  2742  		c.Fatal(err)
  2743  	}
  2744  	id2, err := buildImageFromContext(name2, ctx, false)
  2745  	if err != nil {
  2746  		c.Fatal(err)
  2747  	}
  2748  	if id1 == id2 {
  2749  		c.Fatal("The cache should have been invalided but hasn't.")
  2750  	}
  2751  }
  2752  
  2753  func (s *DockerSuite) TestBuildCopyDirButNotFile(c *check.C) {
  2754  	name := "testbuildcopydirbutnotfile"
  2755  	name2 := "testbuildcopydirbutnotfile2"
  2756  	dockerfile := `
  2757          FROM scratch
  2758          COPY dir /tmp/`
  2759  	ctx, err := fakeContext(dockerfile, map[string]string{
  2760  		"dir/foo": "hello",
  2761  	})
  2762  	defer ctx.Close()
  2763  	if err != nil {
  2764  		c.Fatal(err)
  2765  	}
  2766  	id1, err := buildImageFromContext(name, ctx, true)
  2767  	if err != nil {
  2768  		c.Fatal(err)
  2769  	}
  2770  	// Check that adding file with similar name doesn't mess with cache
  2771  	if err := ctx.Add("dir_file", "hello2"); err != nil {
  2772  		c.Fatal(err)
  2773  	}
  2774  	id2, err := buildImageFromContext(name2, ctx, true)
  2775  	if err != nil {
  2776  		c.Fatal(err)
  2777  	}
  2778  	if id1 != id2 {
  2779  		c.Fatal("The cache should have been used but wasn't")
  2780  	}
  2781  }
  2782  
  2783  func (s *DockerSuite) TestBuildADDCurrentDirWithCache(c *check.C) {
  2784  	name := "testbuildaddcurrentdirwithcache"
  2785  	name2 := name + "2"
  2786  	name3 := name + "3"
  2787  	name4 := name + "4"
  2788  	name5 := name + "5"
  2789  	dockerfile := `
  2790          FROM scratch
  2791          MAINTAINER dockerio
  2792          ADD . /usr/lib/bla`
  2793  	ctx, err := fakeContext(dockerfile, map[string]string{
  2794  		"foo": "hello",
  2795  	})
  2796  	defer ctx.Close()
  2797  	if err != nil {
  2798  		c.Fatal(err)
  2799  	}
  2800  	id1, err := buildImageFromContext(name, ctx, true)
  2801  	if err != nil {
  2802  		c.Fatal(err)
  2803  	}
  2804  	// Check that adding file invalidate cache of "ADD ."
  2805  	if err := ctx.Add("bar", "hello2"); err != nil {
  2806  		c.Fatal(err)
  2807  	}
  2808  	id2, err := buildImageFromContext(name2, ctx, true)
  2809  	if err != nil {
  2810  		c.Fatal(err)
  2811  	}
  2812  	if id1 == id2 {
  2813  		c.Fatal("The cache should have been invalided but hasn't.")
  2814  	}
  2815  	// Check that changing file invalidate cache of "ADD ."
  2816  	if err := ctx.Add("foo", "hello1"); err != nil {
  2817  		c.Fatal(err)
  2818  	}
  2819  	id3, err := buildImageFromContext(name3, ctx, true)
  2820  	if err != nil {
  2821  		c.Fatal(err)
  2822  	}
  2823  	if id2 == id3 {
  2824  		c.Fatal("The cache should have been invalided but hasn't.")
  2825  	}
  2826  	// Check that changing file to same content invalidate cache of "ADD ."
  2827  	time.Sleep(1 * time.Second) // wait second because of mtime precision
  2828  	if err := ctx.Add("foo", "hello1"); err != nil {
  2829  		c.Fatal(err)
  2830  	}
  2831  	id4, err := buildImageFromContext(name4, ctx, true)
  2832  	if err != nil {
  2833  		c.Fatal(err)
  2834  	}
  2835  	if id3 == id4 {
  2836  		c.Fatal("The cache should have been invalided but hasn't.")
  2837  	}
  2838  	id5, err := buildImageFromContext(name5, ctx, true)
  2839  	if err != nil {
  2840  		c.Fatal(err)
  2841  	}
  2842  	if id4 != id5 {
  2843  		c.Fatal("The cache should have been used but hasn't.")
  2844  	}
  2845  }
  2846  
  2847  func (s *DockerSuite) TestBuildADDCurrentDirWithoutCache(c *check.C) {
  2848  	name := "testbuildaddcurrentdirwithoutcache"
  2849  	name2 := "testbuildaddcurrentdirwithoutcache2"
  2850  	dockerfile := `
  2851          FROM scratch
  2852          MAINTAINER dockerio
  2853          ADD . /usr/lib/bla`
  2854  	ctx, err := fakeContext(dockerfile, map[string]string{
  2855  		"foo": "hello",
  2856  	})
  2857  	defer ctx.Close()
  2858  	if err != nil {
  2859  		c.Fatal(err)
  2860  	}
  2861  	id1, err := buildImageFromContext(name, ctx, true)
  2862  	if err != nil {
  2863  		c.Fatal(err)
  2864  	}
  2865  	id2, err := buildImageFromContext(name2, ctx, false)
  2866  	if err != nil {
  2867  		c.Fatal(err)
  2868  	}
  2869  	if id1 == id2 {
  2870  		c.Fatal("The cache should have been invalided but hasn't.")
  2871  	}
  2872  }
  2873  
  2874  func (s *DockerSuite) TestBuildADDRemoteFileWithCache(c *check.C) {
  2875  	name := "testbuildaddremotefilewithcache"
  2876  	server, err := fakeStorage(map[string]string{
  2877  		"baz": "hello",
  2878  	})
  2879  	if err != nil {
  2880  		c.Fatal(err)
  2881  	}
  2882  	defer server.Close()
  2883  
  2884  	id1, err := buildImage(name,
  2885  		fmt.Sprintf(`FROM scratch
  2886          MAINTAINER dockerio
  2887          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  2888  		true)
  2889  	if err != nil {
  2890  		c.Fatal(err)
  2891  	}
  2892  	id2, err := buildImage(name,
  2893  		fmt.Sprintf(`FROM scratch
  2894          MAINTAINER dockerio
  2895          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  2896  		true)
  2897  	if err != nil {
  2898  		c.Fatal(err)
  2899  	}
  2900  	if id1 != id2 {
  2901  		c.Fatal("The cache should have been used but hasn't.")
  2902  	}
  2903  }
  2904  
  2905  func (s *DockerSuite) TestBuildADDRemoteFileWithoutCache(c *check.C) {
  2906  	name := "testbuildaddremotefilewithoutcache"
  2907  	name2 := "testbuildaddremotefilewithoutcache2"
  2908  	server, err := fakeStorage(map[string]string{
  2909  		"baz": "hello",
  2910  	})
  2911  	if err != nil {
  2912  		c.Fatal(err)
  2913  	}
  2914  	defer server.Close()
  2915  
  2916  	id1, err := buildImage(name,
  2917  		fmt.Sprintf(`FROM scratch
  2918          MAINTAINER dockerio
  2919          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  2920  		true)
  2921  	if err != nil {
  2922  		c.Fatal(err)
  2923  	}
  2924  	id2, err := buildImage(name2,
  2925  		fmt.Sprintf(`FROM scratch
  2926          MAINTAINER dockerio
  2927          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  2928  		false)
  2929  	if err != nil {
  2930  		c.Fatal(err)
  2931  	}
  2932  	if id1 == id2 {
  2933  		c.Fatal("The cache should have been invalided but hasn't.")
  2934  	}
  2935  }
  2936  
  2937  func (s *DockerSuite) TestBuildADDRemoteFileMTime(c *check.C) {
  2938  	name := "testbuildaddremotefilemtime"
  2939  	name2 := name + "2"
  2940  	name3 := name + "3"
  2941  	name4 := name + "4"
  2942  
  2943  	files := map[string]string{"baz": "hello"}
  2944  	server, err := fakeStorage(files)
  2945  	if err != nil {
  2946  		c.Fatal(err)
  2947  	}
  2948  	defer server.Close()
  2949  
  2950  	ctx, err := fakeContext(fmt.Sprintf(`FROM scratch
  2951          MAINTAINER dockerio
  2952          ADD %s/baz /usr/lib/baz/quux`, server.URL()), nil)
  2953  	if err != nil {
  2954  		c.Fatal(err)
  2955  	}
  2956  	defer ctx.Close()
  2957  
  2958  	id1, err := buildImageFromContext(name, ctx, true)
  2959  	if err != nil {
  2960  		c.Fatal(err)
  2961  	}
  2962  
  2963  	id2, err := buildImageFromContext(name2, ctx, true)
  2964  	if err != nil {
  2965  		c.Fatal(err)
  2966  	}
  2967  	if id1 != id2 {
  2968  		c.Fatal("The cache should have been used but wasn't - #1")
  2969  	}
  2970  
  2971  	// Now create a different server withsame contents (causes different mtim)
  2972  	// This time the cache should not be used
  2973  
  2974  	// allow some time for clock to pass as mtime precision is only 1s
  2975  	time.Sleep(2 * time.Second)
  2976  
  2977  	server2, err := fakeStorage(files)
  2978  	if err != nil {
  2979  		c.Fatal(err)
  2980  	}
  2981  	defer server2.Close()
  2982  
  2983  	ctx2, err := fakeContext(fmt.Sprintf(`FROM scratch
  2984          MAINTAINER dockerio
  2985          ADD %s/baz /usr/lib/baz/quux`, server2.URL()), nil)
  2986  	if err != nil {
  2987  		c.Fatal(err)
  2988  	}
  2989  	defer ctx2.Close()
  2990  	id3, err := buildImageFromContext(name3, ctx2, true)
  2991  	if err != nil {
  2992  		c.Fatal(err)
  2993  	}
  2994  	if id1 == id3 {
  2995  		c.Fatal("The cache should not have been used but was")
  2996  	}
  2997  
  2998  	// And for good measure do it again and make sure cache is used this time
  2999  	id4, err := buildImageFromContext(name4, ctx2, true)
  3000  	if err != nil {
  3001  		c.Fatal(err)
  3002  	}
  3003  	if id3 != id4 {
  3004  		c.Fatal("The cache should have been used but wasn't - #2")
  3005  	}
  3006  }
  3007  
  3008  func (s *DockerSuite) TestBuildADDLocalAndRemoteFilesWithCache(c *check.C) {
  3009  	name := "testbuildaddlocalandremotefilewithcache"
  3010  	server, err := fakeStorage(map[string]string{
  3011  		"baz": "hello",
  3012  	})
  3013  	if err != nil {
  3014  		c.Fatal(err)
  3015  	}
  3016  	defer server.Close()
  3017  
  3018  	ctx, err := fakeContext(fmt.Sprintf(`FROM scratch
  3019          MAINTAINER dockerio
  3020          ADD foo /usr/lib/bla/bar
  3021          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  3022  		map[string]string{
  3023  			"foo": "hello world",
  3024  		})
  3025  	if err != nil {
  3026  		c.Fatal(err)
  3027  	}
  3028  	defer ctx.Close()
  3029  	id1, err := buildImageFromContext(name, ctx, true)
  3030  	if err != nil {
  3031  		c.Fatal(err)
  3032  	}
  3033  	id2, err := buildImageFromContext(name, ctx, true)
  3034  	if err != nil {
  3035  		c.Fatal(err)
  3036  	}
  3037  	if id1 != id2 {
  3038  		c.Fatal("The cache should have been used but hasn't.")
  3039  	}
  3040  }
  3041  
  3042  func testContextTar(c *check.C, compression archive.Compression) {
  3043  	ctx, err := fakeContext(
  3044  		`FROM busybox
  3045  ADD foo /foo
  3046  CMD ["cat", "/foo"]`,
  3047  		map[string]string{
  3048  			"foo": "bar",
  3049  		},
  3050  	)
  3051  	defer ctx.Close()
  3052  	if err != nil {
  3053  		c.Fatal(err)
  3054  	}
  3055  	context, err := archive.Tar(ctx.Dir, compression)
  3056  	if err != nil {
  3057  		c.Fatalf("failed to build context tar: %v", err)
  3058  	}
  3059  	name := "contexttar"
  3060  	buildCmd := exec.Command(dockerBinary, "build", "-t", name, "-")
  3061  	buildCmd.Stdin = context
  3062  
  3063  	if out, _, err := runCommandWithOutput(buildCmd); err != nil {
  3064  		c.Fatalf("build failed to complete: %v %v", out, err)
  3065  	}
  3066  }
  3067  
  3068  func (s *DockerSuite) TestBuildContextTarGzip(c *check.C) {
  3069  	testContextTar(c, archive.Gzip)
  3070  }
  3071  
  3072  func (s *DockerSuite) TestBuildContextTarNoCompression(c *check.C) {
  3073  	testContextTar(c, archive.Uncompressed)
  3074  }
  3075  
  3076  func (s *DockerSuite) TestBuildNoContext(c *check.C) {
  3077  	buildCmd := exec.Command(dockerBinary, "build", "-t", "nocontext", "-")
  3078  	buildCmd.Stdin = strings.NewReader("FROM busybox\nCMD echo ok\n")
  3079  
  3080  	if out, _, err := runCommandWithOutput(buildCmd); err != nil {
  3081  		c.Fatalf("build failed to complete: %v %v", out, err)
  3082  	}
  3083  
  3084  	if out, _ := dockerCmd(c, "run", "--rm", "nocontext"); out != "ok\n" {
  3085  		c.Fatalf("run produced invalid output: %q, expected %q", out, "ok")
  3086  	}
  3087  }
  3088  
  3089  // TODO: TestCaching
  3090  func (s *DockerSuite) TestBuildADDLocalAndRemoteFilesWithoutCache(c *check.C) {
  3091  	name := "testbuildaddlocalandremotefilewithoutcache"
  3092  	name2 := "testbuildaddlocalandremotefilewithoutcache2"
  3093  	server, err := fakeStorage(map[string]string{
  3094  		"baz": "hello",
  3095  	})
  3096  	if err != nil {
  3097  		c.Fatal(err)
  3098  	}
  3099  	defer server.Close()
  3100  
  3101  	ctx, err := fakeContext(fmt.Sprintf(`FROM scratch
  3102          MAINTAINER dockerio
  3103          ADD foo /usr/lib/bla/bar
  3104          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  3105  		map[string]string{
  3106  			"foo": "hello world",
  3107  		})
  3108  	if err != nil {
  3109  		c.Fatal(err)
  3110  	}
  3111  	defer ctx.Close()
  3112  	id1, err := buildImageFromContext(name, ctx, true)
  3113  	if err != nil {
  3114  		c.Fatal(err)
  3115  	}
  3116  	id2, err := buildImageFromContext(name2, ctx, false)
  3117  	if err != nil {
  3118  		c.Fatal(err)
  3119  	}
  3120  	if id1 == id2 {
  3121  		c.Fatal("The cache should have been invalided but hasn't.")
  3122  	}
  3123  }
  3124  
  3125  func (s *DockerSuite) TestBuildWithVolumeOwnership(c *check.C) {
  3126  	name := "testbuildimg"
  3127  
  3128  	_, err := buildImage(name,
  3129  		`FROM busybox:latest
  3130          RUN mkdir /test && chown daemon:daemon /test && chmod 0600 /test
  3131          VOLUME /test`,
  3132  		true)
  3133  
  3134  	if err != nil {
  3135  		c.Fatal(err)
  3136  	}
  3137  
  3138  	cmd := exec.Command(dockerBinary, "run", "--rm", "testbuildimg", "ls", "-la", "/test")
  3139  	out, _, err := runCommandWithOutput(cmd)
  3140  	if err != nil {
  3141  		c.Fatal(out, err)
  3142  	}
  3143  
  3144  	if expected := "drw-------"; !strings.Contains(out, expected) {
  3145  		c.Fatalf("expected %s received %s", expected, out)
  3146  	}
  3147  
  3148  	if expected := "daemon   daemon"; !strings.Contains(out, expected) {
  3149  		c.Fatalf("expected %s received %s", expected, out)
  3150  	}
  3151  
  3152  }
  3153  
  3154  // testing #1405 - config.Cmd does not get cleaned up if
  3155  // utilizing cache
  3156  func (s *DockerSuite) TestBuildEntrypointRunCleanup(c *check.C) {
  3157  	name := "testbuildcmdcleanup"
  3158  	if _, err := buildImage(name,
  3159  		`FROM busybox
  3160          RUN echo "hello"`,
  3161  		true); err != nil {
  3162  		c.Fatal(err)
  3163  	}
  3164  
  3165  	ctx, err := fakeContext(`FROM busybox
  3166          RUN echo "hello"
  3167          ADD foo /foo
  3168          ENTRYPOINT ["/bin/echo"]`,
  3169  		map[string]string{
  3170  			"foo": "hello",
  3171  		})
  3172  	defer ctx.Close()
  3173  	if err != nil {
  3174  		c.Fatal(err)
  3175  	}
  3176  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3177  		c.Fatal(err)
  3178  	}
  3179  	res, err := inspectField(name, "Config.Cmd")
  3180  	if err != nil {
  3181  		c.Fatal(err)
  3182  	}
  3183  	// Cmd must be cleaned up
  3184  	if res != "<nil>" {
  3185  		c.Fatalf("Cmd %s, expected nil", res)
  3186  	}
  3187  }
  3188  
  3189  func (s *DockerSuite) TestBuildForbiddenContextPath(c *check.C) {
  3190  	name := "testbuildforbidpath"
  3191  	ctx, err := fakeContext(`FROM scratch
  3192          ADD ../../ test/
  3193          `,
  3194  		map[string]string{
  3195  			"test.txt":  "test1",
  3196  			"other.txt": "other",
  3197  		})
  3198  	defer ctx.Close()
  3199  	if err != nil {
  3200  		c.Fatal(err)
  3201  	}
  3202  
  3203  	expected := "Forbidden path outside the build context: ../../ "
  3204  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
  3205  		c.Fatalf("Wrong error: (should contain \"%s\") got:\n%v", expected, err)
  3206  	}
  3207  
  3208  }
  3209  
  3210  func (s *DockerSuite) TestBuildADDFileNotFound(c *check.C) {
  3211  	name := "testbuildaddnotfound"
  3212  	ctx, err := fakeContext(`FROM scratch
  3213          ADD foo /usr/local/bar`,
  3214  		map[string]string{"bar": "hello"})
  3215  	defer ctx.Close()
  3216  	if err != nil {
  3217  		c.Fatal(err)
  3218  	}
  3219  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3220  		if !strings.Contains(err.Error(), "foo: no such file or directory") {
  3221  			c.Fatalf("Wrong error %v, must be about missing foo file or directory", err)
  3222  		}
  3223  	} else {
  3224  		c.Fatal("Error must not be nil")
  3225  	}
  3226  }
  3227  
  3228  func (s *DockerSuite) TestBuildInheritance(c *check.C) {
  3229  	name := "testbuildinheritance"
  3230  
  3231  	_, err := buildImage(name,
  3232  		`FROM scratch
  3233  		EXPOSE 2375`,
  3234  		true)
  3235  	if err != nil {
  3236  		c.Fatal(err)
  3237  	}
  3238  	ports1, err := inspectField(name, "Config.ExposedPorts")
  3239  	if err != nil {
  3240  		c.Fatal(err)
  3241  	}
  3242  
  3243  	_, err = buildImage(name,
  3244  		fmt.Sprintf(`FROM %s
  3245  		ENTRYPOINT ["/bin/echo"]`, name),
  3246  		true)
  3247  	if err != nil {
  3248  		c.Fatal(err)
  3249  	}
  3250  
  3251  	res, err := inspectField(name, "Config.Entrypoint")
  3252  	if err != nil {
  3253  		c.Fatal(err)
  3254  	}
  3255  	if expected := "{[/bin/echo]}"; res != expected {
  3256  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  3257  	}
  3258  	ports2, err := inspectField(name, "Config.ExposedPorts")
  3259  	if err != nil {
  3260  		c.Fatal(err)
  3261  	}
  3262  	if ports1 != ports2 {
  3263  		c.Fatalf("Ports must be same: %s != %s", ports1, ports2)
  3264  	}
  3265  }
  3266  
  3267  func (s *DockerSuite) TestBuildFails(c *check.C) {
  3268  	name := "testbuildfails"
  3269  	_, err := buildImage(name,
  3270  		`FROM busybox
  3271  		RUN sh -c "exit 23"`,
  3272  		true)
  3273  	if err != nil {
  3274  		if !strings.Contains(err.Error(), "returned a non-zero code: 23") {
  3275  			c.Fatalf("Wrong error %v, must be about non-zero code 23", err)
  3276  		}
  3277  	} else {
  3278  		c.Fatal("Error must not be nil")
  3279  	}
  3280  }
  3281  
  3282  func (s *DockerSuite) TestBuildFailsDockerfileEmpty(c *check.C) {
  3283  	name := "testbuildfails"
  3284  	_, err := buildImage(name, ``, true)
  3285  	if err != nil {
  3286  		if !strings.Contains(err.Error(), "The Dockerfile (Dockerfile) cannot be empty") {
  3287  			c.Fatalf("Wrong error %v, must be about empty Dockerfile", err)
  3288  		}
  3289  	} else {
  3290  		c.Fatal("Error must not be nil")
  3291  	}
  3292  }
  3293  
  3294  func (s *DockerSuite) TestBuildOnBuild(c *check.C) {
  3295  	name := "testbuildonbuild"
  3296  	_, err := buildImage(name,
  3297  		`FROM busybox
  3298  		ONBUILD RUN touch foobar`,
  3299  		true)
  3300  	if err != nil {
  3301  		c.Fatal(err)
  3302  	}
  3303  	_, err = buildImage(name,
  3304  		fmt.Sprintf(`FROM %s
  3305  		RUN [ -f foobar ]`, name),
  3306  		true)
  3307  	if err != nil {
  3308  		c.Fatal(err)
  3309  	}
  3310  }
  3311  
  3312  func (s *DockerSuite) TestBuildOnBuildForbiddenChained(c *check.C) {
  3313  	name := "testbuildonbuildforbiddenchained"
  3314  	_, err := buildImage(name,
  3315  		`FROM busybox
  3316  		ONBUILD ONBUILD RUN touch foobar`,
  3317  		true)
  3318  	if err != nil {
  3319  		if !strings.Contains(err.Error(), "Chaining ONBUILD via `ONBUILD ONBUILD` isn't allowed") {
  3320  			c.Fatalf("Wrong error %v, must be about chaining ONBUILD", err)
  3321  		}
  3322  	} else {
  3323  		c.Fatal("Error must not be nil")
  3324  	}
  3325  }
  3326  
  3327  func (s *DockerSuite) TestBuildOnBuildForbiddenFrom(c *check.C) {
  3328  	name := "testbuildonbuildforbiddenfrom"
  3329  	_, err := buildImage(name,
  3330  		`FROM busybox
  3331  		ONBUILD FROM scratch`,
  3332  		true)
  3333  	if err != nil {
  3334  		if !strings.Contains(err.Error(), "FROM isn't allowed as an ONBUILD trigger") {
  3335  			c.Fatalf("Wrong error %v, must be about FROM forbidden", err)
  3336  		}
  3337  	} else {
  3338  		c.Fatal("Error must not be nil")
  3339  	}
  3340  }
  3341  
  3342  func (s *DockerSuite) TestBuildOnBuildForbiddenMaintainer(c *check.C) {
  3343  	name := "testbuildonbuildforbiddenmaintainer"
  3344  	_, err := buildImage(name,
  3345  		`FROM busybox
  3346  		ONBUILD MAINTAINER docker.io`,
  3347  		true)
  3348  	if err != nil {
  3349  		if !strings.Contains(err.Error(), "MAINTAINER isn't allowed as an ONBUILD trigger") {
  3350  			c.Fatalf("Wrong error %v, must be about MAINTAINER forbidden", err)
  3351  		}
  3352  	} else {
  3353  		c.Fatal("Error must not be nil")
  3354  	}
  3355  }
  3356  
  3357  // gh #2446
  3358  func (s *DockerSuite) TestBuildAddToSymlinkDest(c *check.C) {
  3359  	name := "testbuildaddtosymlinkdest"
  3360  	ctx, err := fakeContext(`FROM busybox
  3361          RUN mkdir /foo
  3362          RUN ln -s /foo /bar
  3363          ADD foo /bar/
  3364          RUN [ -f /bar/foo ]
  3365          RUN [ -f /foo/foo ]`,
  3366  		map[string]string{
  3367  			"foo": "hello",
  3368  		})
  3369  	if err != nil {
  3370  		c.Fatal(err)
  3371  	}
  3372  	defer ctx.Close()
  3373  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3374  		c.Fatal(err)
  3375  	}
  3376  }
  3377  
  3378  func (s *DockerSuite) TestBuildEscapeWhitespace(c *check.C) {
  3379  	name := "testbuildescaping"
  3380  
  3381  	_, err := buildImage(name, `
  3382    FROM busybox
  3383    MAINTAINER "Docker \
  3384  IO <io@\
  3385  docker.com>"
  3386    `, true)
  3387  
  3388  	res, err := inspectField(name, "Author")
  3389  
  3390  	if err != nil {
  3391  		c.Fatal(err)
  3392  	}
  3393  
  3394  	if res != "\"Docker IO <io@docker.com>\"" {
  3395  		c.Fatalf("Parsed string did not match the escaped string. Got: %q", res)
  3396  	}
  3397  
  3398  }
  3399  
  3400  func (s *DockerSuite) TestBuildVerifyIntString(c *check.C) {
  3401  	// Verify that strings that look like ints are still passed as strings
  3402  	name := "testbuildstringing"
  3403  
  3404  	_, err := buildImage(name, `
  3405    FROM busybox
  3406    MAINTAINER 123
  3407    `, true)
  3408  
  3409  	out, rc, err := runCommandWithOutput(exec.Command(dockerBinary, "inspect", name))
  3410  	if rc != 0 || err != nil {
  3411  		c.Fatalf("Unexpected error from inspect: rc: %v  err: %v", rc, err)
  3412  	}
  3413  
  3414  	if !strings.Contains(out, "\"123\"") {
  3415  		c.Fatalf("Output does not contain the int as a string:\n%s", out)
  3416  	}
  3417  
  3418  }
  3419  
  3420  func (s *DockerSuite) TestBuildDockerignore(c *check.C) {
  3421  	name := "testbuilddockerignore"
  3422  	dockerfile := `
  3423          FROM busybox
  3424          ADD . /bla
  3425  		RUN [[ -f /bla/src/x.go ]]
  3426  		RUN [[ -f /bla/Makefile ]]
  3427  		RUN [[ ! -e /bla/src/_vendor ]]
  3428  		RUN [[ ! -e /bla/.gitignore ]]
  3429  		RUN [[ ! -e /bla/README.md ]]
  3430  		RUN [[ ! -e /bla/.git ]]`
  3431  	ctx, err := fakeContext(dockerfile, map[string]string{
  3432  		"Makefile":         "all:",
  3433  		".git/HEAD":        "ref: foo",
  3434  		"src/x.go":         "package main",
  3435  		"src/_vendor/v.go": "package main",
  3436  		".gitignore":       "",
  3437  		"README.md":        "readme",
  3438  		".dockerignore":    ".git\npkg\n.gitignore\nsrc/_vendor\n*.md",
  3439  	})
  3440  	defer ctx.Close()
  3441  	if err != nil {
  3442  		c.Fatal(err)
  3443  	}
  3444  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3445  		c.Fatal(err)
  3446  	}
  3447  }
  3448  
  3449  func (s *DockerSuite) TestBuildDockerignoreCleanPaths(c *check.C) {
  3450  	name := "testbuilddockerignorecleanpaths"
  3451  	dockerfile := `
  3452          FROM busybox
  3453          ADD . /tmp/
  3454          RUN (! ls /tmp/foo) && (! ls /tmp/foo2) && (! ls /tmp/dir1/foo)`
  3455  	ctx, err := fakeContext(dockerfile, map[string]string{
  3456  		"foo":           "foo",
  3457  		"foo2":          "foo2",
  3458  		"dir1/foo":      "foo in dir1",
  3459  		".dockerignore": "./foo\ndir1//foo\n./dir1/../foo2",
  3460  	})
  3461  	if err != nil {
  3462  		c.Fatal(err)
  3463  	}
  3464  	defer ctx.Close()
  3465  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3466  		c.Fatal(err)
  3467  	}
  3468  }
  3469  
  3470  func (s *DockerSuite) TestBuildDockerignoringDockerfile(c *check.C) {
  3471  	name := "testbuilddockerignoredockerfile"
  3472  	dockerfile := `
  3473          FROM busybox
  3474  		ADD . /tmp/
  3475  		RUN ! ls /tmp/Dockerfile
  3476  		RUN ls /tmp/.dockerignore`
  3477  	ctx, err := fakeContext(dockerfile, map[string]string{
  3478  		"Dockerfile":    dockerfile,
  3479  		".dockerignore": "Dockerfile\n",
  3480  	})
  3481  	if err != nil {
  3482  		c.Fatal(err)
  3483  	}
  3484  	defer ctx.Close()
  3485  
  3486  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3487  		c.Fatalf("Didn't ignore Dockerfile correctly:%s", err)
  3488  	}
  3489  
  3490  	// now try it with ./Dockerfile
  3491  	ctx.Add(".dockerignore", "./Dockerfile\n")
  3492  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3493  		c.Fatalf("Didn't ignore ./Dockerfile correctly:%s", err)
  3494  	}
  3495  
  3496  }
  3497  
  3498  func (s *DockerSuite) TestBuildDockerignoringRenamedDockerfile(c *check.C) {
  3499  	name := "testbuilddockerignoredockerfile"
  3500  	dockerfile := `
  3501          FROM busybox
  3502  		ADD . /tmp/
  3503  		RUN ls /tmp/Dockerfile
  3504  		RUN ! ls /tmp/MyDockerfile
  3505  		RUN ls /tmp/.dockerignore`
  3506  	ctx, err := fakeContext(dockerfile, map[string]string{
  3507  		"Dockerfile":    "Should not use me",
  3508  		"MyDockerfile":  dockerfile,
  3509  		".dockerignore": "MyDockerfile\n",
  3510  	})
  3511  	if err != nil {
  3512  		c.Fatal(err)
  3513  	}
  3514  	defer ctx.Close()
  3515  
  3516  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3517  		c.Fatalf("Didn't ignore MyDockerfile correctly:%s", err)
  3518  	}
  3519  
  3520  	// now try it with ./MyDockerfile
  3521  	ctx.Add(".dockerignore", "./MyDockerfile\n")
  3522  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3523  		c.Fatalf("Didn't ignore ./MyDockerfile correctly:%s", err)
  3524  	}
  3525  
  3526  }
  3527  
  3528  func (s *DockerSuite) TestBuildDockerignoringDockerignore(c *check.C) {
  3529  	name := "testbuilddockerignoredockerignore"
  3530  	dockerfile := `
  3531          FROM busybox
  3532  		ADD . /tmp/
  3533  		RUN ! ls /tmp/.dockerignore
  3534  		RUN ls /tmp/Dockerfile`
  3535  	ctx, err := fakeContext(dockerfile, map[string]string{
  3536  		"Dockerfile":    dockerfile,
  3537  		".dockerignore": ".dockerignore\n",
  3538  	})
  3539  	defer ctx.Close()
  3540  	if err != nil {
  3541  		c.Fatal(err)
  3542  	}
  3543  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3544  		c.Fatalf("Didn't ignore .dockerignore correctly:%s", err)
  3545  	}
  3546  }
  3547  
  3548  func (s *DockerSuite) TestBuildDockerignoreTouchDockerfile(c *check.C) {
  3549  	var id1 string
  3550  	var id2 string
  3551  
  3552  	name := "testbuilddockerignoretouchdockerfile"
  3553  	dockerfile := `
  3554          FROM busybox
  3555  		ADD . /tmp/`
  3556  	ctx, err := fakeContext(dockerfile, map[string]string{
  3557  		"Dockerfile":    dockerfile,
  3558  		".dockerignore": "Dockerfile\n",
  3559  	})
  3560  	defer ctx.Close()
  3561  	if err != nil {
  3562  		c.Fatal(err)
  3563  	}
  3564  
  3565  	if id1, err = buildImageFromContext(name, ctx, true); err != nil {
  3566  		c.Fatalf("Didn't build it correctly:%s", err)
  3567  	}
  3568  
  3569  	if id2, err = buildImageFromContext(name, ctx, true); err != nil {
  3570  		c.Fatalf("Didn't build it correctly:%s", err)
  3571  	}
  3572  	if id1 != id2 {
  3573  		c.Fatalf("Didn't use the cache - 1")
  3574  	}
  3575  
  3576  	// Now make sure touching Dockerfile doesn't invalidate the cache
  3577  	if err = ctx.Add("Dockerfile", dockerfile+"\n# hi"); err != nil {
  3578  		c.Fatalf("Didn't add Dockerfile: %s", err)
  3579  	}
  3580  	if id2, err = buildImageFromContext(name, ctx, true); err != nil {
  3581  		c.Fatalf("Didn't build it correctly:%s", err)
  3582  	}
  3583  	if id1 != id2 {
  3584  		c.Fatalf("Didn't use the cache - 2")
  3585  	}
  3586  
  3587  	// One more time but just 'touch' it instead of changing the content
  3588  	if err = ctx.Add("Dockerfile", dockerfile+"\n# hi"); err != nil {
  3589  		c.Fatalf("Didn't add Dockerfile: %s", err)
  3590  	}
  3591  	if id2, err = buildImageFromContext(name, ctx, true); err != nil {
  3592  		c.Fatalf("Didn't build it correctly:%s", err)
  3593  	}
  3594  	if id1 != id2 {
  3595  		c.Fatalf("Didn't use the cache - 3")
  3596  	}
  3597  
  3598  }
  3599  
  3600  func (s *DockerSuite) TestBuildDockerignoringWholeDir(c *check.C) {
  3601  	name := "testbuilddockerignorewholedir"
  3602  	dockerfile := `
  3603          FROM busybox
  3604  		COPY . /
  3605  		RUN [[ ! -e /.gitignore ]]
  3606  		RUN [[ -f /Makefile ]]`
  3607  	ctx, err := fakeContext(dockerfile, map[string]string{
  3608  		"Dockerfile":    "FROM scratch",
  3609  		"Makefile":      "all:",
  3610  		".dockerignore": ".*\n",
  3611  	})
  3612  	defer ctx.Close()
  3613  	if err != nil {
  3614  		c.Fatal(err)
  3615  	}
  3616  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3617  		c.Fatal(err)
  3618  	}
  3619  }
  3620  
  3621  func (s *DockerSuite) TestBuildLineBreak(c *check.C) {
  3622  	name := "testbuildlinebreak"
  3623  	_, err := buildImage(name,
  3624  		`FROM  busybox
  3625  RUN    sh -c 'echo root:testpass \
  3626  	> /tmp/passwd'
  3627  RUN    mkdir -p /var/run/sshd
  3628  RUN    [ "$(cat /tmp/passwd)" = "root:testpass" ]
  3629  RUN    [ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]`,
  3630  		true)
  3631  	if err != nil {
  3632  		c.Fatal(err)
  3633  	}
  3634  }
  3635  
  3636  func (s *DockerSuite) TestBuildEOLInLine(c *check.C) {
  3637  	name := "testbuildeolinline"
  3638  	_, err := buildImage(name,
  3639  		`FROM   busybox
  3640  RUN    sh -c 'echo root:testpass > /tmp/passwd'
  3641  RUN    echo "foo \n bar"; echo "baz"
  3642  RUN    mkdir -p /var/run/sshd
  3643  RUN    [ "$(cat /tmp/passwd)" = "root:testpass" ]
  3644  RUN    [ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]`,
  3645  		true)
  3646  	if err != nil {
  3647  		c.Fatal(err)
  3648  	}
  3649  }
  3650  
  3651  func (s *DockerSuite) TestBuildCommentsShebangs(c *check.C) {
  3652  	name := "testbuildcomments"
  3653  	_, err := buildImage(name,
  3654  		`FROM busybox
  3655  # This is an ordinary comment.
  3656  RUN { echo '#!/bin/sh'; echo 'echo hello world'; } > /hello.sh
  3657  RUN [ ! -x /hello.sh ]
  3658  # comment with line break \
  3659  RUN chmod +x /hello.sh
  3660  RUN [ -x /hello.sh ]
  3661  RUN [ "$(cat /hello.sh)" = $'#!/bin/sh\necho hello world' ]
  3662  RUN [ "$(/hello.sh)" = "hello world" ]`,
  3663  		true)
  3664  	if err != nil {
  3665  		c.Fatal(err)
  3666  	}
  3667  }
  3668  
  3669  func (s *DockerSuite) TestBuildUsersAndGroups(c *check.C) {
  3670  	name := "testbuildusers"
  3671  	_, err := buildImage(name,
  3672  		`FROM busybox
  3673  
  3674  # Make sure our defaults work
  3675  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)" = '0:0/root:root' ]
  3676  
  3677  # 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)
  3678  USER root
  3679  RUN [ "$(id -G):$(id -Gn)" = '0 10:root wheel' ]
  3680  
  3681  # Setup dockerio user and group
  3682  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  3683  RUN echo 'dockerio:x:1001:' >> /etc/group
  3684  
  3685  # Make sure we can switch to our user and all the information is exactly as we expect it to be
  3686  USER dockerio
  3687  RUN id -G
  3688  RUN id -Gn
  3689  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3690  
  3691  # Switch back to root and double check that worked exactly as we might expect it to
  3692  USER root
  3693  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '0:0/root:root/0 10:root wheel' ]
  3694  
  3695  # Add a "supplementary" group for our dockerio user
  3696  RUN echo 'supplementary:x:1002:dockerio' >> /etc/group
  3697  
  3698  # ... and then go verify that we get it like we expect
  3699  USER dockerio
  3700  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001 1002:dockerio supplementary' ]
  3701  USER 1001
  3702  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001 1002:dockerio supplementary' ]
  3703  
  3704  # super test the new "user:group" syntax
  3705  USER dockerio:dockerio
  3706  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3707  USER 1001:dockerio
  3708  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3709  USER dockerio:1001
  3710  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3711  USER 1001:1001
  3712  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3713  USER dockerio:supplementary
  3714  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  3715  USER dockerio:1002
  3716  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  3717  USER 1001:supplementary
  3718  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  3719  USER 1001:1002
  3720  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  3721  
  3722  # make sure unknown uid/gid still works properly
  3723  USER 1042:1043
  3724  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1042:1043/1042:1043/1043:1043' ]`,
  3725  		true)
  3726  	if err != nil {
  3727  		c.Fatal(err)
  3728  	}
  3729  }
  3730  
  3731  func (s *DockerSuite) TestBuildEnvUsage(c *check.C) {
  3732  	name := "testbuildenvusage"
  3733  	dockerfile := `FROM busybox
  3734  ENV    HOME /root
  3735  ENV    PATH $HOME/bin:$PATH
  3736  ENV    PATH /tmp:$PATH
  3737  RUN    [ "$PATH" = "/tmp:$HOME/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ]
  3738  ENV    FOO /foo/baz
  3739  ENV    BAR /bar
  3740  ENV    BAZ $BAR
  3741  ENV    FOOPATH $PATH:$FOO
  3742  RUN    [ "$BAR" = "$BAZ" ]
  3743  RUN    [ "$FOOPATH" = "$PATH:/foo/baz" ]
  3744  ENV	   FROM hello/docker/world
  3745  ENV    TO /docker/world/hello
  3746  ADD    $FROM $TO
  3747  RUN    [ "$(cat $TO)" = "hello" ]
  3748  ENV    abc=def
  3749  ENV    ghi=$abc
  3750  RUN    [ "$ghi" = "def" ]
  3751  `
  3752  	ctx, err := fakeContext(dockerfile, map[string]string{
  3753  		"hello/docker/world": "hello",
  3754  	})
  3755  	if err != nil {
  3756  		c.Fatal(err)
  3757  	}
  3758  	defer ctx.Close()
  3759  
  3760  	_, err = buildImageFromContext(name, ctx, true)
  3761  	if err != nil {
  3762  		c.Fatal(err)
  3763  	}
  3764  }
  3765  
  3766  func (s *DockerSuite) TestBuildEnvUsage2(c *check.C) {
  3767  	name := "testbuildenvusage2"
  3768  	dockerfile := `FROM busybox
  3769  ENV    abc=def
  3770  RUN    [ "$abc" = "def" ]
  3771  ENV    def="hello world"
  3772  RUN    [ "$def" = "hello world" ]
  3773  ENV    def=hello\ world
  3774  RUN    [ "$def" = "hello world" ]
  3775  ENV    v1=abc v2="hi there"
  3776  RUN    [ "$v1" = "abc" ]
  3777  RUN    [ "$v2" = "hi there" ]
  3778  ENV    v3='boogie nights' v4="with'quotes too"
  3779  RUN    [ "$v3" = "boogie nights" ]
  3780  RUN    [ "$v4" = "with'quotes too" ]
  3781  ENV    abc=zzz FROM=hello/docker/world
  3782  ENV    abc=zzz TO=/docker/world/hello
  3783  ADD    $FROM $TO
  3784  RUN    [ "$(cat $TO)" = "hello" ]
  3785  ENV    abc "zzz"
  3786  RUN    [ $abc = "zzz" ]
  3787  ENV    abc 'yyy'
  3788  RUN    [ $abc = 'yyy' ]
  3789  ENV    abc=
  3790  RUN    [ "$abc" = "" ]
  3791  
  3792  # use grep to make sure if the builder substitutes \$foo by mistake
  3793  # we don't get a false positive
  3794  ENV    abc=\$foo
  3795  RUN    [ "$abc" = "\$foo" ] && (echo "$abc" | grep foo)
  3796  ENV    abc \$foo
  3797  RUN    [ "$abc" = "\$foo" ] && (echo "$abc" | grep foo)
  3798  
  3799  ENV    abc=\'foo\'
  3800  RUN    [ "$abc" = "'foo'" ]
  3801  ENV    abc=\"foo\"
  3802  RUN    [ "$abc" = "\"foo\"" ]
  3803  ENV    abc "foo"
  3804  RUN    [ "$abc" = "foo" ]
  3805  ENV    abc 'foo'
  3806  RUN    [ "$abc" = 'foo' ]
  3807  ENV    abc \'foo\'
  3808  RUN    [ "$abc" = "'foo'" ]
  3809  ENV    abc \"foo\"
  3810  RUN    [ "$abc" = '"foo"' ]
  3811  
  3812  ENV    abc=ABC
  3813  RUN    [ "$abc" = "ABC" ]
  3814  ENV    def=${abc:-DEF}
  3815  RUN    [ "$def" = "ABC" ]
  3816  ENV    def=${ccc:-DEF}
  3817  RUN    [ "$def" = "DEF" ]
  3818  ENV    def=${ccc:-${def}xx}
  3819  RUN    [ "$def" = "DEFxx" ]
  3820  ENV    def=${def:+ALT}
  3821  RUN    [ "$def" = "ALT" ]
  3822  ENV    def=${def:+${abc}:}
  3823  RUN    [ "$def" = "ABC:" ]
  3824  ENV    def=${ccc:-\$abc:}
  3825  RUN    [ "$def" = '$abc:' ]
  3826  ENV    def=${ccc:-\${abc}:}
  3827  RUN    [ "$def" = '${abc:}' ]
  3828  ENV    mypath=${mypath:+$mypath:}/home
  3829  RUN    [ "$mypath" = '/home' ]
  3830  ENV    mypath=${mypath:+$mypath:}/away
  3831  RUN    [ "$mypath" = '/home:/away' ]
  3832  
  3833  ENV    e1=bar
  3834  ENV    e2=$e1
  3835  ENV    e3=$e11
  3836  ENV    e4=\$e1
  3837  ENV    e5=\$e11
  3838  RUN    [ "$e0,$e1,$e2,$e3,$e4,$e5" = ',bar,bar,,$e1,$e11' ]
  3839  
  3840  ENV    ee1 bar
  3841  ENV    ee2 $ee1
  3842  ENV    ee3 $ee11
  3843  ENV    ee4 \$ee1
  3844  ENV    ee5 \$ee11
  3845  RUN    [ "$ee1,$ee2,$ee3,$ee4,$ee5" = 'bar,bar,,$ee1,$ee11' ]
  3846  
  3847  ENV    eee1="foo"
  3848  ENV    eee2='foo'
  3849  ENV    eee3 "foo"
  3850  ENV    eee4 'foo'
  3851  RUN    [ "$eee1,$eee2,$eee3,$eee4" = 'foo,foo,foo,foo' ]
  3852  
  3853  `
  3854  	ctx, err := fakeContext(dockerfile, map[string]string{
  3855  		"hello/docker/world": "hello",
  3856  	})
  3857  	if err != nil {
  3858  		c.Fatal(err)
  3859  	}
  3860  	defer ctx.Close()
  3861  
  3862  	_, err = buildImageFromContext(name, ctx, true)
  3863  	if err != nil {
  3864  		c.Fatal(err)
  3865  	}
  3866  }
  3867  
  3868  func (s *DockerSuite) TestBuildAddScript(c *check.C) {
  3869  	name := "testbuildaddscript"
  3870  	dockerfile := `
  3871  FROM busybox
  3872  ADD test /test
  3873  RUN ["chmod","+x","/test"]
  3874  RUN ["/test"]
  3875  RUN [ "$(cat /testfile)" = 'test!' ]`
  3876  	ctx, err := fakeContext(dockerfile, map[string]string{
  3877  		"test": "#!/bin/sh\necho 'test!' > /testfile",
  3878  	})
  3879  	if err != nil {
  3880  		c.Fatal(err)
  3881  	}
  3882  	defer ctx.Close()
  3883  
  3884  	_, err = buildImageFromContext(name, ctx, true)
  3885  	if err != nil {
  3886  		c.Fatal(err)
  3887  	}
  3888  }
  3889  
  3890  func (s *DockerSuite) TestBuildAddTar(c *check.C) {
  3891  	name := "testbuildaddtar"
  3892  
  3893  	ctx := func() *FakeContext {
  3894  		dockerfile := `
  3895  FROM busybox
  3896  ADD test.tar /
  3897  RUN cat /test/foo | grep Hi
  3898  ADD test.tar /test.tar
  3899  RUN cat /test.tar/test/foo | grep Hi
  3900  ADD test.tar /unlikely-to-exist
  3901  RUN cat /unlikely-to-exist/test/foo | grep Hi
  3902  ADD test.tar /unlikely-to-exist-trailing-slash/
  3903  RUN cat /unlikely-to-exist-trailing-slash/test/foo | grep Hi
  3904  RUN mkdir /existing-directory
  3905  ADD test.tar /existing-directory
  3906  RUN cat /existing-directory/test/foo | grep Hi
  3907  ADD test.tar /existing-directory-trailing-slash/
  3908  RUN cat /existing-directory-trailing-slash/test/foo | grep Hi`
  3909  		tmpDir, err := ioutil.TempDir("", "fake-context")
  3910  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  3911  		if err != nil {
  3912  			c.Fatalf("failed to create test.tar archive: %v", err)
  3913  		}
  3914  		defer testTar.Close()
  3915  
  3916  		tw := tar.NewWriter(testTar)
  3917  
  3918  		if err := tw.WriteHeader(&tar.Header{
  3919  			Name: "test/foo",
  3920  			Size: 2,
  3921  		}); err != nil {
  3922  			c.Fatalf("failed to write tar file header: %v", err)
  3923  		}
  3924  		if _, err := tw.Write([]byte("Hi")); err != nil {
  3925  			c.Fatalf("failed to write tar file content: %v", err)
  3926  		}
  3927  		if err := tw.Close(); err != nil {
  3928  			c.Fatalf("failed to close tar archive: %v", err)
  3929  		}
  3930  
  3931  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  3932  			c.Fatalf("failed to open destination dockerfile: %v", err)
  3933  		}
  3934  		return fakeContextFromDir(tmpDir)
  3935  	}()
  3936  	defer ctx.Close()
  3937  
  3938  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3939  		c.Fatalf("build failed to complete for TestBuildAddTar: %v", err)
  3940  	}
  3941  
  3942  }
  3943  
  3944  func (s *DockerSuite) TestBuildAddTarXz(c *check.C) {
  3945  	name := "testbuildaddtarxz"
  3946  
  3947  	ctx := func() *FakeContext {
  3948  		dockerfile := `
  3949  			FROM busybox
  3950  			ADD test.tar.xz /
  3951  			RUN cat /test/foo | grep Hi`
  3952  		tmpDir, err := ioutil.TempDir("", "fake-context")
  3953  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  3954  		if err != nil {
  3955  			c.Fatalf("failed to create test.tar archive: %v", err)
  3956  		}
  3957  		defer testTar.Close()
  3958  
  3959  		tw := tar.NewWriter(testTar)
  3960  
  3961  		if err := tw.WriteHeader(&tar.Header{
  3962  			Name: "test/foo",
  3963  			Size: 2,
  3964  		}); err != nil {
  3965  			c.Fatalf("failed to write tar file header: %v", err)
  3966  		}
  3967  		if _, err := tw.Write([]byte("Hi")); err != nil {
  3968  			c.Fatalf("failed to write tar file content: %v", err)
  3969  		}
  3970  		if err := tw.Close(); err != nil {
  3971  			c.Fatalf("failed to close tar archive: %v", err)
  3972  		}
  3973  		xzCompressCmd := exec.Command("xz", "-k", "test.tar")
  3974  		xzCompressCmd.Dir = tmpDir
  3975  		out, _, err := runCommandWithOutput(xzCompressCmd)
  3976  		if err != nil {
  3977  			c.Fatal(err, out)
  3978  		}
  3979  
  3980  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  3981  			c.Fatalf("failed to open destination dockerfile: %v", err)
  3982  		}
  3983  		return fakeContextFromDir(tmpDir)
  3984  	}()
  3985  
  3986  	defer ctx.Close()
  3987  
  3988  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3989  		c.Fatalf("build failed to complete for TestBuildAddTarXz: %v", err)
  3990  	}
  3991  
  3992  }
  3993  
  3994  func (s *DockerSuite) TestBuildAddTarXzGz(c *check.C) {
  3995  	name := "testbuildaddtarxzgz"
  3996  
  3997  	ctx := func() *FakeContext {
  3998  		dockerfile := `
  3999  			FROM busybox
  4000  			ADD test.tar.xz.gz /
  4001  			RUN ls /test.tar.xz.gz`
  4002  		tmpDir, err := ioutil.TempDir("", "fake-context")
  4003  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  4004  		if err != nil {
  4005  			c.Fatalf("failed to create test.tar archive: %v", err)
  4006  		}
  4007  		defer testTar.Close()
  4008  
  4009  		tw := tar.NewWriter(testTar)
  4010  
  4011  		if err := tw.WriteHeader(&tar.Header{
  4012  			Name: "test/foo",
  4013  			Size: 2,
  4014  		}); err != nil {
  4015  			c.Fatalf("failed to write tar file header: %v", err)
  4016  		}
  4017  		if _, err := tw.Write([]byte("Hi")); err != nil {
  4018  			c.Fatalf("failed to write tar file content: %v", err)
  4019  		}
  4020  		if err := tw.Close(); err != nil {
  4021  			c.Fatalf("failed to close tar archive: %v", err)
  4022  		}
  4023  
  4024  		xzCompressCmd := exec.Command("xz", "-k", "test.tar")
  4025  		xzCompressCmd.Dir = tmpDir
  4026  		out, _, err := runCommandWithOutput(xzCompressCmd)
  4027  		if err != nil {
  4028  			c.Fatal(err, out)
  4029  		}
  4030  
  4031  		gzipCompressCmd := exec.Command("gzip", "test.tar.xz")
  4032  		gzipCompressCmd.Dir = tmpDir
  4033  		out, _, err = runCommandWithOutput(gzipCompressCmd)
  4034  		if err != nil {
  4035  			c.Fatal(err, out)
  4036  		}
  4037  
  4038  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  4039  			c.Fatalf("failed to open destination dockerfile: %v", err)
  4040  		}
  4041  		return fakeContextFromDir(tmpDir)
  4042  	}()
  4043  
  4044  	defer ctx.Close()
  4045  
  4046  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  4047  		c.Fatalf("build failed to complete for TestBuildAddTarXz: %v", err)
  4048  	}
  4049  
  4050  }
  4051  
  4052  func (s *DockerSuite) TestBuildFromGIT(c *check.C) {
  4053  	name := "testbuildfromgit"
  4054  	git, err := fakeGIT("repo", map[string]string{
  4055  		"Dockerfile": `FROM busybox
  4056  					ADD first /first
  4057  					RUN [ -f /first ]
  4058  					MAINTAINER docker`,
  4059  		"first": "test git data",
  4060  	}, true)
  4061  	if err != nil {
  4062  		c.Fatal(err)
  4063  	}
  4064  	defer git.Close()
  4065  
  4066  	_, err = buildImageFromPath(name, git.RepoURL, true)
  4067  	if err != nil {
  4068  		c.Fatal(err)
  4069  	}
  4070  	res, err := inspectField(name, "Author")
  4071  	if err != nil {
  4072  		c.Fatal(err)
  4073  	}
  4074  	if res != "docker" {
  4075  		c.Fatalf("Maintainer should be docker, got %s", res)
  4076  	}
  4077  }
  4078  
  4079  func (s *DockerSuite) TestBuildCleanupCmdOnEntrypoint(c *check.C) {
  4080  	name := "testbuildcmdcleanuponentrypoint"
  4081  	if _, err := buildImage(name,
  4082  		`FROM scratch
  4083          CMD ["test"]
  4084  		ENTRYPOINT ["echo"]`,
  4085  		true); err != nil {
  4086  		c.Fatal(err)
  4087  	}
  4088  	if _, err := buildImage(name,
  4089  		fmt.Sprintf(`FROM %s
  4090  		ENTRYPOINT ["cat"]`, name),
  4091  		true); err != nil {
  4092  		c.Fatal(err)
  4093  	}
  4094  	res, err := inspectField(name, "Config.Cmd")
  4095  	if err != nil {
  4096  		c.Fatal(err)
  4097  	}
  4098  	if res != "<nil>" {
  4099  		c.Fatalf("Cmd %s, expected nil", res)
  4100  	}
  4101  
  4102  	res, err = inspectField(name, "Config.Entrypoint")
  4103  	if err != nil {
  4104  		c.Fatal(err)
  4105  	}
  4106  	if expected := "{[cat]}"; res != expected {
  4107  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  4108  	}
  4109  }
  4110  
  4111  func (s *DockerSuite) TestBuildClearCmd(c *check.C) {
  4112  	name := "testbuildclearcmd"
  4113  	_, err := buildImage(name,
  4114  		`From scratch
  4115     ENTRYPOINT ["/bin/bash"]
  4116     CMD []`,
  4117  		true)
  4118  	if err != nil {
  4119  		c.Fatal(err)
  4120  	}
  4121  	res, err := inspectFieldJSON(name, "Config.Cmd")
  4122  	if err != nil {
  4123  		c.Fatal(err)
  4124  	}
  4125  	if res != "[]" {
  4126  		c.Fatalf("Cmd %s, expected %s", res, "[]")
  4127  	}
  4128  }
  4129  
  4130  func (s *DockerSuite) TestBuildEmptyCmd(c *check.C) {
  4131  	name := "testbuildemptycmd"
  4132  	if _, err := buildImage(name, "FROM scratch\nMAINTAINER quux\n", true); err != nil {
  4133  		c.Fatal(err)
  4134  	}
  4135  	res, err := inspectFieldJSON(name, "Config.Cmd")
  4136  	if err != nil {
  4137  		c.Fatal(err)
  4138  	}
  4139  	if res != "null" {
  4140  		c.Fatalf("Cmd %s, expected %s", res, "null")
  4141  	}
  4142  }
  4143  
  4144  func (s *DockerSuite) TestBuildOnBuildOutput(c *check.C) {
  4145  	name := "testbuildonbuildparent"
  4146  	if _, err := buildImage(name, "FROM busybox\nONBUILD RUN echo foo\n", true); err != nil {
  4147  		c.Fatal(err)
  4148  	}
  4149  
  4150  	_, out, err := buildImageWithOut(name, "FROM "+name+"\nMAINTAINER quux\n", true)
  4151  	if err != nil {
  4152  		c.Fatal(err)
  4153  	}
  4154  
  4155  	if !strings.Contains(out, "Trigger 0, RUN echo foo") {
  4156  		c.Fatal("failed to find the ONBUILD output", out)
  4157  	}
  4158  
  4159  }
  4160  
  4161  func (s *DockerSuite) TestBuildInvalidTag(c *check.C) {
  4162  	name := "abcd:" + stringutils.GenerateRandomAlphaOnlyString(200)
  4163  	_, out, err := buildImageWithOut(name, "FROM scratch\nMAINTAINER quux\n", true)
  4164  	// if the error doesnt check for illegal tag name, or the image is built
  4165  	// then this should fail
  4166  	if !strings.Contains(out, "Illegal tag name") || strings.Contains(out, "Sending build context to Docker daemon") {
  4167  		c.Fatalf("failed to stop before building. Error: %s, Output: %s", err, out)
  4168  	}
  4169  }
  4170  
  4171  func (s *DockerSuite) TestBuildCmdShDashC(c *check.C) {
  4172  	name := "testbuildcmdshc"
  4173  	if _, err := buildImage(name, "FROM busybox\nCMD echo cmd\n", true); err != nil {
  4174  		c.Fatal(err)
  4175  	}
  4176  
  4177  	res, err := inspectFieldJSON(name, "Config.Cmd")
  4178  	if err != nil {
  4179  		c.Fatal(err, res)
  4180  	}
  4181  
  4182  	expected := `["/bin/sh","-c","echo cmd"]`
  4183  
  4184  	if res != expected {
  4185  		c.Fatalf("Expected value %s not in Config.Cmd: %s", expected, res)
  4186  	}
  4187  
  4188  }
  4189  
  4190  func (s *DockerSuite) TestBuildCmdSpaces(c *check.C) {
  4191  	// Test to make sure that when we strcat arrays we take into account
  4192  	// the arg separator to make sure ["echo","hi"] and ["echo hi"] don't
  4193  	// look the same
  4194  	name := "testbuildcmdspaces"
  4195  	var id1 string
  4196  	var id2 string
  4197  	var err error
  4198  
  4199  	if id1, err = buildImage(name, "FROM busybox\nCMD [\"echo hi\"]\n", true); err != nil {
  4200  		c.Fatal(err)
  4201  	}
  4202  
  4203  	if id2, err = buildImage(name, "FROM busybox\nCMD [\"echo\", \"hi\"]\n", true); err != nil {
  4204  		c.Fatal(err)
  4205  	}
  4206  
  4207  	if id1 == id2 {
  4208  		c.Fatal("Should not have resulted in the same CMD")
  4209  	}
  4210  
  4211  	// Now do the same with ENTRYPOINT
  4212  	if id1, err = buildImage(name, "FROM busybox\nENTRYPOINT [\"echo hi\"]\n", true); err != nil {
  4213  		c.Fatal(err)
  4214  	}
  4215  
  4216  	if id2, err = buildImage(name, "FROM busybox\nENTRYPOINT [\"echo\", \"hi\"]\n", true); err != nil {
  4217  		c.Fatal(err)
  4218  	}
  4219  
  4220  	if id1 == id2 {
  4221  		c.Fatal("Should not have resulted in the same ENTRYPOINT")
  4222  	}
  4223  
  4224  }
  4225  
  4226  func (s *DockerSuite) TestBuildCmdJSONNoShDashC(c *check.C) {
  4227  	name := "testbuildcmdjson"
  4228  	if _, err := buildImage(name, "FROM busybox\nCMD [\"echo\", \"cmd\"]", true); err != nil {
  4229  		c.Fatal(err)
  4230  	}
  4231  
  4232  	res, err := inspectFieldJSON(name, "Config.Cmd")
  4233  	if err != nil {
  4234  		c.Fatal(err, res)
  4235  	}
  4236  
  4237  	expected := `["echo","cmd"]`
  4238  
  4239  	if res != expected {
  4240  		c.Fatalf("Expected value %s not in Config.Cmd: %s", expected, res)
  4241  	}
  4242  
  4243  }
  4244  
  4245  func (s *DockerSuite) TestBuildErrorInvalidInstruction(c *check.C) {
  4246  	name := "testbuildignoreinvalidinstruction"
  4247  
  4248  	out, _, err := buildImageWithOut(name, "FROM busybox\nfoo bar", true)
  4249  	if err == nil {
  4250  		c.Fatalf("Should have failed: %s", out)
  4251  	}
  4252  
  4253  }
  4254  
  4255  func (s *DockerSuite) TestBuildEntrypointInheritance(c *check.C) {
  4256  
  4257  	if _, err := buildImage("parent", `
  4258      FROM busybox
  4259      ENTRYPOINT exit 130
  4260      `, true); err != nil {
  4261  		c.Fatal(err)
  4262  	}
  4263  
  4264  	status, _ := runCommand(exec.Command(dockerBinary, "run", "parent"))
  4265  
  4266  	if status != 130 {
  4267  		c.Fatalf("expected exit code 130 but received %d", status)
  4268  	}
  4269  
  4270  	if _, err := buildImage("child", `
  4271      FROM parent
  4272      ENTRYPOINT exit 5
  4273      `, true); err != nil {
  4274  		c.Fatal(err)
  4275  	}
  4276  
  4277  	status, _ = runCommand(exec.Command(dockerBinary, "run", "child"))
  4278  
  4279  	if status != 5 {
  4280  		c.Fatalf("expected exit code 5 but received %d", status)
  4281  	}
  4282  
  4283  }
  4284  
  4285  func (s *DockerSuite) TestBuildEntrypointInheritanceInspect(c *check.C) {
  4286  	var (
  4287  		name     = "testbuildepinherit"
  4288  		name2    = "testbuildepinherit2"
  4289  		expected = `["/bin/sh","-c","echo quux"]`
  4290  	)
  4291  
  4292  	if _, err := buildImage(name, "FROM busybox\nENTRYPOINT /foo/bar", true); err != nil {
  4293  		c.Fatal(err)
  4294  	}
  4295  
  4296  	if _, err := buildImage(name2, fmt.Sprintf("FROM %s\nENTRYPOINT echo quux", name), true); err != nil {
  4297  		c.Fatal(err)
  4298  	}
  4299  
  4300  	res, err := inspectFieldJSON(name2, "Config.Entrypoint")
  4301  	if err != nil {
  4302  		c.Fatal(err, res)
  4303  	}
  4304  
  4305  	if res != expected {
  4306  		c.Fatalf("Expected value %s not in Config.Entrypoint: %s", expected, res)
  4307  	}
  4308  
  4309  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-t", name2))
  4310  	if err != nil {
  4311  		c.Fatal(err, out)
  4312  	}
  4313  
  4314  	expected = "quux"
  4315  
  4316  	if strings.TrimSpace(out) != expected {
  4317  		c.Fatalf("Expected output is %s, got %s", expected, out)
  4318  	}
  4319  
  4320  }
  4321  
  4322  func (s *DockerSuite) TestBuildRunShEntrypoint(c *check.C) {
  4323  	name := "testbuildentrypoint"
  4324  	_, err := buildImage(name,
  4325  		`FROM busybox
  4326                                  ENTRYPOINT /bin/echo`,
  4327  		true)
  4328  	if err != nil {
  4329  		c.Fatal(err)
  4330  	}
  4331  
  4332  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--rm", name))
  4333  
  4334  	if err != nil {
  4335  		c.Fatal(err, out)
  4336  	}
  4337  
  4338  }
  4339  
  4340  func (s *DockerSuite) TestBuildExoticShellInterpolation(c *check.C) {
  4341  	name := "testbuildexoticshellinterpolation"
  4342  
  4343  	_, err := buildImage(name, `
  4344  		FROM busybox
  4345  
  4346  		ENV SOME_VAR a.b.c
  4347  
  4348  		RUN [ "$SOME_VAR"       = 'a.b.c' ]
  4349  		RUN [ "${SOME_VAR}"     = 'a.b.c' ]
  4350  		RUN [ "${SOME_VAR%.*}"  = 'a.b'   ]
  4351  		RUN [ "${SOME_VAR%%.*}" = 'a'     ]
  4352  		RUN [ "${SOME_VAR#*.}"  = 'b.c'   ]
  4353  		RUN [ "${SOME_VAR##*.}" = 'c'     ]
  4354  		RUN [ "${SOME_VAR/c/d}" = 'a.b.d' ]
  4355  		RUN [ "${#SOME_VAR}"    = '5'     ]
  4356  
  4357  		RUN [ "${SOME_UNSET_VAR:-$SOME_VAR}" = 'a.b.c' ]
  4358  		RUN [ "${SOME_VAR:+Version: ${SOME_VAR}}" = 'Version: a.b.c' ]
  4359  		RUN [ "${SOME_UNSET_VAR:+${SOME_VAR}}" = '' ]
  4360  		RUN [ "${SOME_UNSET_VAR:-${SOME_VAR:-d.e.f}}" = 'a.b.c' ]
  4361  	`, false)
  4362  	if err != nil {
  4363  		c.Fatal(err)
  4364  	}
  4365  
  4366  }
  4367  
  4368  func (s *DockerSuite) TestBuildVerifySingleQuoteFails(c *check.C) {
  4369  	// This testcase is supposed to generate an error because the
  4370  	// JSON array we're passing in on the CMD uses single quotes instead
  4371  	// of double quotes (per the JSON spec). This means we interpret it
  4372  	// as a "string" insead of "JSON array" and pass it on to "sh -c" and
  4373  	// it should barf on it.
  4374  	name := "testbuildsinglequotefails"
  4375  
  4376  	_, err := buildImage(name,
  4377  		`FROM busybox
  4378  		CMD [ '/bin/sh', '-c', 'echo hi' ]`,
  4379  		true)
  4380  	_, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "--rm", name))
  4381  
  4382  	if err == nil {
  4383  		c.Fatal("The image was not supposed to be able to run")
  4384  	}
  4385  
  4386  }
  4387  
  4388  func (s *DockerSuite) TestBuildVerboseOut(c *check.C) {
  4389  	name := "testbuildverboseout"
  4390  
  4391  	_, out, err := buildImageWithOut(name,
  4392  		`FROM busybox
  4393  RUN echo 123`,
  4394  		false)
  4395  
  4396  	if err != nil {
  4397  		c.Fatal(err)
  4398  	}
  4399  	if !strings.Contains(out, "\n123\n") {
  4400  		c.Fatalf("Output should contain %q: %q", "123", out)
  4401  	}
  4402  
  4403  }
  4404  
  4405  func (s *DockerSuite) TestBuildWithTabs(c *check.C) {
  4406  	name := "testbuildwithtabs"
  4407  	_, err := buildImage(name,
  4408  		"FROM busybox\nRUN echo\tone\t\ttwo", true)
  4409  	if err != nil {
  4410  		c.Fatal(err)
  4411  	}
  4412  	res, err := inspectFieldJSON(name, "ContainerConfig.Cmd")
  4413  	if err != nil {
  4414  		c.Fatal(err)
  4415  	}
  4416  	expected1 := `["/bin/sh","-c","echo\tone\t\ttwo"]`
  4417  	expected2 := `["/bin/sh","-c","echo\u0009one\u0009\u0009two"]` // syntactically equivalent, and what Go 1.3 generates
  4418  	if res != expected1 && res != expected2 {
  4419  		c.Fatalf("Missing tabs.\nGot: %s\nExp: %s or %s", res, expected1, expected2)
  4420  	}
  4421  }
  4422  
  4423  func (s *DockerSuite) TestBuildLabels(c *check.C) {
  4424  	name := "testbuildlabel"
  4425  	expected := `{"License":"GPL","Vendor":"Acme"}`
  4426  	_, err := buildImage(name,
  4427  		`FROM busybox
  4428  		LABEL Vendor=Acme
  4429                  LABEL License GPL`,
  4430  		true)
  4431  	if err != nil {
  4432  		c.Fatal(err)
  4433  	}
  4434  	res, err := inspectFieldJSON(name, "Config.Labels")
  4435  	if err != nil {
  4436  		c.Fatal(err)
  4437  	}
  4438  	if res != expected {
  4439  		c.Fatalf("Labels %s, expected %s", res, expected)
  4440  	}
  4441  }
  4442  
  4443  func (s *DockerSuite) TestBuildLabelsCache(c *check.C) {
  4444  	name := "testbuildlabelcache"
  4445  
  4446  	id1, err := buildImage(name,
  4447  		`FROM busybox
  4448  		LABEL Vendor=Acme`, false)
  4449  	if err != nil {
  4450  		c.Fatalf("Build 1 should have worked: %v", err)
  4451  	}
  4452  
  4453  	id2, err := buildImage(name,
  4454  		`FROM busybox
  4455  		LABEL Vendor=Acme`, true)
  4456  	if err != nil || id1 != id2 {
  4457  		c.Fatalf("Build 2 should have worked & used cache(%s,%s): %v", id1, id2, err)
  4458  	}
  4459  
  4460  	id2, err = buildImage(name,
  4461  		`FROM busybox
  4462  		LABEL Vendor=Acme1`, true)
  4463  	if err != nil || id1 == id2 {
  4464  		c.Fatalf("Build 3 should have worked & NOT used cache(%s,%s): %v", id1, id2, err)
  4465  	}
  4466  
  4467  	id2, err = buildImage(name,
  4468  		`FROM busybox
  4469  		LABEL Vendor Acme`, true) // Note: " " and "=" should be same
  4470  	if err != nil || id1 != id2 {
  4471  		c.Fatalf("Build 4 should have worked & used cache(%s,%s): %v", id1, id2, err)
  4472  	}
  4473  
  4474  	// Now make sure the cache isn't used by mistake
  4475  	id1, err = buildImage(name,
  4476  		`FROM busybox
  4477         LABEL f1=b1 f2=b2`, false)
  4478  	if err != nil {
  4479  		c.Fatalf("Build 5 should have worked: %q", err)
  4480  	}
  4481  
  4482  	id2, err = buildImage(name,
  4483  		`FROM busybox
  4484         LABEL f1="b1 f2=b2"`, true)
  4485  	if err != nil || id1 == id2 {
  4486  		c.Fatalf("Build 6 should have worked & NOT used the cache(%s,%s): %q", id1, id2, err)
  4487  	}
  4488  
  4489  }
  4490  
  4491  func (s *DockerSuite) TestBuildStderr(c *check.C) {
  4492  	// This test just makes sure that no non-error output goes
  4493  	// to stderr
  4494  	name := "testbuildstderr"
  4495  	_, _, stderr, err := buildImageWithStdoutStderr(name,
  4496  		"FROM busybox\nRUN echo one", true)
  4497  	if err != nil {
  4498  		c.Fatal(err)
  4499  	}
  4500  
  4501  	if runtime.GOOS == "windows" {
  4502  		// stderr might contain a security warning on windows
  4503  		lines := strings.Split(stderr, "\n")
  4504  		for _, v := range lines {
  4505  			if v != "" && !strings.Contains(v, "SECURITY WARNING:") {
  4506  				c.Fatalf("Stderr contains unexpected output line: %q", v)
  4507  			}
  4508  		}
  4509  	} else {
  4510  		if stderr != "" {
  4511  			c.Fatalf("Stderr should have been empty, instead its: %q", stderr)
  4512  		}
  4513  	}
  4514  }
  4515  
  4516  func (s *DockerSuite) TestBuildChownSingleFile(c *check.C) {
  4517  	testRequires(c, UnixCli) // test uses chown: not available on windows
  4518  
  4519  	name := "testbuildchownsinglefile"
  4520  
  4521  	ctx, err := fakeContext(`
  4522  FROM busybox
  4523  COPY test /
  4524  RUN ls -l /test
  4525  RUN [ $(ls -l /test | awk '{print $3":"$4}') = 'root:root' ]
  4526  `, map[string]string{
  4527  		"test": "test",
  4528  	})
  4529  	if err != nil {
  4530  		c.Fatal(err)
  4531  	}
  4532  	defer ctx.Close()
  4533  
  4534  	if err := os.Chown(filepath.Join(ctx.Dir, "test"), 4242, 4242); err != nil {
  4535  		c.Fatal(err)
  4536  	}
  4537  
  4538  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  4539  		c.Fatal(err)
  4540  	}
  4541  
  4542  }
  4543  
  4544  func (s *DockerSuite) TestBuildSymlinkBreakout(c *check.C) {
  4545  	name := "testbuildsymlinkbreakout"
  4546  	tmpdir, err := ioutil.TempDir("", name)
  4547  	if err != nil {
  4548  		c.Fatal(err)
  4549  	}
  4550  	defer os.RemoveAll(tmpdir)
  4551  	ctx := filepath.Join(tmpdir, "context")
  4552  	if err := os.MkdirAll(ctx, 0755); err != nil {
  4553  		c.Fatal(err)
  4554  	}
  4555  	if err := ioutil.WriteFile(filepath.Join(ctx, "Dockerfile"), []byte(`
  4556  	from busybox
  4557  	add symlink.tar /
  4558  	add inject /symlink/
  4559  	`), 0644); err != nil {
  4560  		c.Fatal(err)
  4561  	}
  4562  	inject := filepath.Join(ctx, "inject")
  4563  	if err := ioutil.WriteFile(inject, nil, 0644); err != nil {
  4564  		c.Fatal(err)
  4565  	}
  4566  	f, err := os.Create(filepath.Join(ctx, "symlink.tar"))
  4567  	if err != nil {
  4568  		c.Fatal(err)
  4569  	}
  4570  	w := tar.NewWriter(f)
  4571  	w.WriteHeader(&tar.Header{
  4572  		Name:     "symlink2",
  4573  		Typeflag: tar.TypeSymlink,
  4574  		Linkname: "/../../../../../../../../../../../../../../",
  4575  		Uid:      os.Getuid(),
  4576  		Gid:      os.Getgid(),
  4577  	})
  4578  	w.WriteHeader(&tar.Header{
  4579  		Name:     "symlink",
  4580  		Typeflag: tar.TypeSymlink,
  4581  		Linkname: filepath.Join("symlink2", tmpdir),
  4582  		Uid:      os.Getuid(),
  4583  		Gid:      os.Getgid(),
  4584  	})
  4585  	w.Close()
  4586  	f.Close()
  4587  	if _, err := buildImageFromContext(name, fakeContextFromDir(ctx), false); err != nil {
  4588  		c.Fatal(err)
  4589  	}
  4590  	if _, err := os.Lstat(filepath.Join(tmpdir, "inject")); err == nil {
  4591  		c.Fatal("symlink breakout - inject")
  4592  	} else if !os.IsNotExist(err) {
  4593  		c.Fatalf("unexpected error: %v", err)
  4594  	}
  4595  }
  4596  
  4597  func (s *DockerSuite) TestBuildXZHost(c *check.C) {
  4598  	name := "testbuildxzhost"
  4599  
  4600  	ctx, err := fakeContext(`
  4601  FROM busybox
  4602  ADD xz /usr/local/sbin/
  4603  RUN chmod 755 /usr/local/sbin/xz
  4604  ADD test.xz /
  4605  RUN [ ! -e /injected ]`,
  4606  		map[string]string{
  4607  			"test.xz": "\xfd\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00" +
  4608  				"\x21\x01\x16\x00\x00\x00\x74\x2f\xe5\xa3\x01\x00\x3f\xfd" +
  4609  				"\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00\x21",
  4610  			"xz": "#!/bin/sh\ntouch /injected",
  4611  		})
  4612  
  4613  	if err != nil {
  4614  		c.Fatal(err)
  4615  	}
  4616  	defer ctx.Close()
  4617  
  4618  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  4619  		c.Fatal(err)
  4620  	}
  4621  
  4622  }
  4623  
  4624  func (s *DockerSuite) TestBuildVolumesRetainContents(c *check.C) {
  4625  	var (
  4626  		name     = "testbuildvolumescontent"
  4627  		expected = "some text"
  4628  	)
  4629  	ctx, err := fakeContext(`
  4630  FROM busybox
  4631  COPY content /foo/file
  4632  VOLUME /foo
  4633  CMD cat /foo/file`,
  4634  		map[string]string{
  4635  			"content": expected,
  4636  		})
  4637  	if err != nil {
  4638  		c.Fatal(err)
  4639  	}
  4640  	defer ctx.Close()
  4641  
  4642  	if _, err := buildImageFromContext(name, ctx, false); err != nil {
  4643  		c.Fatal(err)
  4644  	}
  4645  
  4646  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--rm", name))
  4647  	if err != nil {
  4648  		c.Fatal(err)
  4649  	}
  4650  	if out != expected {
  4651  		c.Fatalf("expected file contents for /foo/file to be %q but received %q", expected, out)
  4652  	}
  4653  
  4654  }
  4655  
  4656  func (s *DockerSuite) TestBuildRenamedDockerfile(c *check.C) {
  4657  
  4658  	ctx, err := fakeContext(`FROM busybox
  4659  	RUN echo from Dockerfile`,
  4660  		map[string]string{
  4661  			"Dockerfile":       "FROM busybox\nRUN echo from Dockerfile",
  4662  			"files/Dockerfile": "FROM busybox\nRUN echo from files/Dockerfile",
  4663  			"files/dFile":      "FROM busybox\nRUN echo from files/dFile",
  4664  			"dFile":            "FROM busybox\nRUN echo from dFile",
  4665  			"files/dFile2":     "FROM busybox\nRUN echo from files/dFile2",
  4666  		})
  4667  	defer ctx.Close()
  4668  	if err != nil {
  4669  		c.Fatal(err)
  4670  	}
  4671  
  4672  	out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-t", "test1", ".")
  4673  	if err != nil {
  4674  		c.Fatalf("Failed to build: %s\n%s", out, err)
  4675  	}
  4676  	if !strings.Contains(out, "from Dockerfile") {
  4677  		c.Fatalf("test1 should have used Dockerfile, output:%s", out)
  4678  	}
  4679  
  4680  	out, _, err = dockerCmdInDir(c, ctx.Dir, "build", "-f", filepath.Join("files", "Dockerfile"), "-t", "test2", ".")
  4681  	if err != nil {
  4682  		c.Fatal(err)
  4683  	}
  4684  	if !strings.Contains(out, "from files/Dockerfile") {
  4685  		c.Fatalf("test2 should have used files/Dockerfile, output:%s", out)
  4686  	}
  4687  
  4688  	out, _, err = dockerCmdInDir(c, ctx.Dir, "build", fmt.Sprintf("--file=%s", filepath.Join("files", "dFile")), "-t", "test3", ".")
  4689  	if err != nil {
  4690  		c.Fatal(err)
  4691  	}
  4692  	if !strings.Contains(out, "from files/dFile") {
  4693  		c.Fatalf("test3 should have used files/dFile, output:%s", out)
  4694  	}
  4695  
  4696  	out, _, err = dockerCmdInDir(c, ctx.Dir, "build", "--file=dFile", "-t", "test4", ".")
  4697  	if err != nil {
  4698  		c.Fatal(err)
  4699  	}
  4700  	if !strings.Contains(out, "from dFile") {
  4701  		c.Fatalf("test4 should have used dFile, output:%s", out)
  4702  	}
  4703  
  4704  	dirWithNoDockerfile, _ := ioutil.TempDir(os.TempDir(), "test5")
  4705  	nonDockerfileFile := filepath.Join(dirWithNoDockerfile, "notDockerfile")
  4706  	if _, err = os.Create(nonDockerfileFile); err != nil {
  4707  		c.Fatal(err)
  4708  	}
  4709  	out, _, err = dockerCmdInDir(c, ctx.Dir, "build", fmt.Sprintf("--file=%s", nonDockerfileFile), "-t", "test5", ".")
  4710  
  4711  	if err == nil {
  4712  		c.Fatalf("test5 was supposed to fail to find passwd")
  4713  	}
  4714  
  4715  	if expected := fmt.Sprintf("The Dockerfile (%s) must be within the build context (.)", strings.Replace(nonDockerfileFile, `\`, `\\`, -1)); !strings.Contains(out, expected) {
  4716  		c.Fatalf("wrong error messsage:%v\nexpected to contain=%v", out, expected)
  4717  	}
  4718  
  4719  	out, _, err = dockerCmdInDir(c, filepath.Join(ctx.Dir, "files"), "build", "-f", filepath.Join("..", "Dockerfile"), "-t", "test6", "..")
  4720  	if err != nil {
  4721  		c.Fatalf("test6 failed: %s", err)
  4722  	}
  4723  	if !strings.Contains(out, "from Dockerfile") {
  4724  		c.Fatalf("test6 should have used root Dockerfile, output:%s", out)
  4725  	}
  4726  
  4727  	out, _, err = dockerCmdInDir(c, filepath.Join(ctx.Dir, "files"), "build", "-f", filepath.Join(ctx.Dir, "files", "Dockerfile"), "-t", "test7", "..")
  4728  	if err != nil {
  4729  		c.Fatalf("test7 failed: %s", err)
  4730  	}
  4731  	if !strings.Contains(out, "from files/Dockerfile") {
  4732  		c.Fatalf("test7 should have used files Dockerfile, output:%s", out)
  4733  	}
  4734  
  4735  	out, _, err = dockerCmdInDir(c, filepath.Join(ctx.Dir, "files"), "build", "-f", filepath.Join("..", "Dockerfile"), "-t", "test8", ".")
  4736  	if err == nil || !strings.Contains(out, "must be within the build context") {
  4737  		c.Fatalf("test8 should have failed with Dockerfile out of context: %s", err)
  4738  	}
  4739  
  4740  	tmpDir := os.TempDir()
  4741  	out, _, err = dockerCmdInDir(c, tmpDir, "build", "-t", "test9", ctx.Dir)
  4742  	if err != nil {
  4743  		c.Fatalf("test9 - failed: %s", err)
  4744  	}
  4745  	if !strings.Contains(out, "from Dockerfile") {
  4746  		c.Fatalf("test9 should have used root Dockerfile, output:%s", out)
  4747  	}
  4748  
  4749  	out, _, err = dockerCmdInDir(c, filepath.Join(ctx.Dir, "files"), "build", "-f", "dFile2", "-t", "test10", ".")
  4750  	if err != nil {
  4751  		c.Fatalf("test10 should have worked: %s", err)
  4752  	}
  4753  	if !strings.Contains(out, "from files/dFile2") {
  4754  		c.Fatalf("test10 should have used files/dFile2, output:%s", out)
  4755  	}
  4756  
  4757  }
  4758  
  4759  func (s *DockerSuite) TestBuildFromMixedcaseDockerfile(c *check.C) {
  4760  	testRequires(c, UnixCli) // Dockerfile overwrites dockerfile on windows
  4761  
  4762  	ctx, err := fakeContext(`FROM busybox
  4763  	RUN echo from dockerfile`,
  4764  		map[string]string{
  4765  			"dockerfile": "FROM busybox\nRUN echo from dockerfile",
  4766  		})
  4767  	defer ctx.Close()
  4768  	if err != nil {
  4769  		c.Fatal(err)
  4770  	}
  4771  
  4772  	out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-t", "test1", ".")
  4773  	if err != nil {
  4774  		c.Fatalf("Failed to build: %s\n%s", out, err)
  4775  	}
  4776  
  4777  	if !strings.Contains(out, "from dockerfile") {
  4778  		c.Fatalf("Missing proper output: %s", out)
  4779  	}
  4780  
  4781  }
  4782  
  4783  func (s *DockerSuite) TestBuildWithTwoDockerfiles(c *check.C) {
  4784  	testRequires(c, UnixCli) // Dockerfile overwrites dockerfile on windows
  4785  
  4786  	ctx, err := fakeContext(`FROM busybox
  4787  RUN echo from Dockerfile`,
  4788  		map[string]string{
  4789  			"dockerfile": "FROM busybox\nRUN echo from dockerfile",
  4790  		})
  4791  	defer ctx.Close()
  4792  	if err != nil {
  4793  		c.Fatal(err)
  4794  	}
  4795  
  4796  	out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-t", "test1", ".")
  4797  	if err != nil {
  4798  		c.Fatalf("Failed to build: %s\n%s", out, err)
  4799  	}
  4800  
  4801  	if !strings.Contains(out, "from Dockerfile") {
  4802  		c.Fatalf("Missing proper output: %s", out)
  4803  	}
  4804  
  4805  }
  4806  
  4807  func (s *DockerSuite) TestBuildFromURLWithF(c *check.C) {
  4808  
  4809  	server, err := fakeStorage(map[string]string{"baz": `FROM busybox
  4810  RUN echo from baz
  4811  COPY * /tmp/
  4812  RUN find /tmp/`})
  4813  	if err != nil {
  4814  		c.Fatal(err)
  4815  	}
  4816  	defer server.Close()
  4817  
  4818  	ctx, err := fakeContext(`FROM busybox
  4819  RUN echo from Dockerfile`,
  4820  		map[string]string{})
  4821  	defer ctx.Close()
  4822  	if err != nil {
  4823  		c.Fatal(err)
  4824  	}
  4825  
  4826  	// Make sure that -f is ignored and that we don't use the Dockerfile
  4827  	// that's in the current dir
  4828  	out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-f", "baz", "-t", "test1", server.URL()+"/baz")
  4829  	if err != nil {
  4830  		c.Fatalf("Failed to build: %s\n%s", out, err)
  4831  	}
  4832  
  4833  	if !strings.Contains(out, "from baz") ||
  4834  		strings.Contains(out, "/tmp/baz") ||
  4835  		!strings.Contains(out, "/tmp/Dockerfile") {
  4836  		c.Fatalf("Missing proper output: %s", out)
  4837  	}
  4838  
  4839  }
  4840  
  4841  func (s *DockerSuite) TestBuildFromStdinWithF(c *check.C) {
  4842  
  4843  	ctx, err := fakeContext(`FROM busybox
  4844  RUN echo from Dockerfile`,
  4845  		map[string]string{})
  4846  	defer ctx.Close()
  4847  	if err != nil {
  4848  		c.Fatal(err)
  4849  	}
  4850  
  4851  	// Make sure that -f is ignored and that we don't use the Dockerfile
  4852  	// that's in the current dir
  4853  	dockerCommand := exec.Command(dockerBinary, "build", "-f", "baz", "-t", "test1", "-")
  4854  	dockerCommand.Dir = ctx.Dir
  4855  	dockerCommand.Stdin = strings.NewReader(`FROM busybox
  4856  RUN echo from baz
  4857  COPY * /tmp/
  4858  RUN find /tmp/`)
  4859  	out, status, err := runCommandWithOutput(dockerCommand)
  4860  	if err != nil || status != 0 {
  4861  		c.Fatalf("Error building: %s", err)
  4862  	}
  4863  
  4864  	if !strings.Contains(out, "from baz") ||
  4865  		strings.Contains(out, "/tmp/baz") ||
  4866  		!strings.Contains(out, "/tmp/Dockerfile") {
  4867  		c.Fatalf("Missing proper output: %s", out)
  4868  	}
  4869  
  4870  }
  4871  
  4872  func (s *DockerSuite) TestBuildFromOfficialNames(c *check.C) {
  4873  	name := "testbuildfromofficial"
  4874  	fromNames := []string{
  4875  		"busybox",
  4876  		"docker.io/busybox",
  4877  		"index.docker.io/busybox",
  4878  		"library/busybox",
  4879  		"docker.io/library/busybox",
  4880  		"index.docker.io/library/busybox",
  4881  	}
  4882  	for idx, fromName := range fromNames {
  4883  		imgName := fmt.Sprintf("%s%d", name, idx)
  4884  		_, err := buildImage(imgName, "FROM "+fromName, true)
  4885  		if err != nil {
  4886  			c.Errorf("Build failed using FROM %s: %s", fromName, err)
  4887  		}
  4888  		deleteImages(imgName)
  4889  	}
  4890  }
  4891  
  4892  func (s *DockerSuite) TestBuildDockerfileOutsideContext(c *check.C) {
  4893  	testRequires(c, UnixCli) // uses os.Symlink: not implemented in windows at the time of writing (go-1.4.2)
  4894  
  4895  	name := "testbuilddockerfileoutsidecontext"
  4896  	tmpdir, err := ioutil.TempDir("", name)
  4897  	if err != nil {
  4898  		c.Fatal(err)
  4899  	}
  4900  	defer os.RemoveAll(tmpdir)
  4901  	ctx := filepath.Join(tmpdir, "context")
  4902  	if err := os.MkdirAll(ctx, 0755); err != nil {
  4903  		c.Fatal(err)
  4904  	}
  4905  	if err := ioutil.WriteFile(filepath.Join(ctx, "Dockerfile"), []byte("FROM scratch\nENV X Y"), 0644); err != nil {
  4906  		c.Fatal(err)
  4907  	}
  4908  	wd, err := os.Getwd()
  4909  	if err != nil {
  4910  		c.Fatal(err)
  4911  	}
  4912  	defer os.Chdir(wd)
  4913  	if err := os.Chdir(ctx); err != nil {
  4914  		c.Fatal(err)
  4915  	}
  4916  	if err := ioutil.WriteFile(filepath.Join(tmpdir, "outsideDockerfile"), []byte("FROM scratch\nENV x y"), 0644); err != nil {
  4917  		c.Fatal(err)
  4918  	}
  4919  	if err := os.Symlink(filepath.Join("..", "outsideDockerfile"), filepath.Join(ctx, "dockerfile1")); err != nil {
  4920  		c.Fatal(err)
  4921  	}
  4922  	if err := os.Symlink(filepath.Join(tmpdir, "outsideDockerfile"), filepath.Join(ctx, "dockerfile2")); err != nil {
  4923  		c.Fatal(err)
  4924  	}
  4925  
  4926  	for _, dockerfilePath := range []string{
  4927  		filepath.Join("..", "outsideDockerfile"),
  4928  		filepath.Join(ctx, "dockerfile1"),
  4929  		filepath.Join(ctx, "dockerfile2"),
  4930  	} {
  4931  		out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "build", "-t", name, "--no-cache", "-f", dockerfilePath, "."))
  4932  		if err == nil {
  4933  			c.Fatalf("Expected error with %s. Out: %s", dockerfilePath, out)
  4934  		}
  4935  		if !strings.Contains(out, "must be within the build context") && !strings.Contains(out, "Cannot locate Dockerfile") {
  4936  			c.Fatalf("Unexpected error with %s. Out: %s", dockerfilePath, out)
  4937  		}
  4938  		deleteImages(name)
  4939  	}
  4940  
  4941  	os.Chdir(tmpdir)
  4942  
  4943  	// Path to Dockerfile should be resolved relative to working directory, not relative to context.
  4944  	// There is a Dockerfile in the context, but since there is no Dockerfile in the current directory, the following should fail
  4945  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "build", "-t", name, "--no-cache", "-f", "Dockerfile", ctx))
  4946  	if err == nil {
  4947  		c.Fatalf("Expected error. Out: %s", out)
  4948  	}
  4949  }
  4950  
  4951  func (s *DockerSuite) TestBuildSpaces(c *check.C) {
  4952  	// Test to make sure that leading/trailing spaces on a command
  4953  	// doesn't change the error msg we get
  4954  	var (
  4955  		err1 error
  4956  		err2 error
  4957  	)
  4958  
  4959  	name := "testspaces"
  4960  	ctx, err := fakeContext("FROM busybox\nCOPY\n",
  4961  		map[string]string{
  4962  			"Dockerfile": "FROM busybox\nCOPY\n",
  4963  		})
  4964  	if err != nil {
  4965  		c.Fatal(err)
  4966  	}
  4967  	defer ctx.Close()
  4968  
  4969  	if _, err1 = buildImageFromContext(name, ctx, false); err1 == nil {
  4970  		c.Fatal("Build 1 was supposed to fail, but didn't")
  4971  	}
  4972  
  4973  	ctx.Add("Dockerfile", "FROM busybox\nCOPY    ")
  4974  	if _, err2 = buildImageFromContext(name, ctx, false); err2 == nil {
  4975  		c.Fatal("Build 2 was supposed to fail, but didn't")
  4976  	}
  4977  
  4978  	removeLogTimestamps := func(s string) string {
  4979  		return regexp.MustCompile(`time="(.*?)"`).ReplaceAllString(s, `time=[TIMESTAMP]`)
  4980  	}
  4981  
  4982  	// Skip over the times
  4983  	e1 := removeLogTimestamps(err1.Error())
  4984  	e2 := removeLogTimestamps(err2.Error())
  4985  
  4986  	// Ignore whitespace since that's what were verifying doesn't change stuff
  4987  	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
  4988  		c.Fatalf("Build 2's error wasn't the same as build 1's\n1:%s\n2:%s", err1, err2)
  4989  	}
  4990  
  4991  	ctx.Add("Dockerfile", "FROM busybox\n   COPY")
  4992  	if _, err2 = buildImageFromContext(name, ctx, false); err2 == nil {
  4993  		c.Fatal("Build 3 was supposed to fail, but didn't")
  4994  	}
  4995  
  4996  	// Skip over the times
  4997  	e1 = removeLogTimestamps(err1.Error())
  4998  	e2 = removeLogTimestamps(err2.Error())
  4999  
  5000  	// Ignore whitespace since that's what were verifying doesn't change stuff
  5001  	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
  5002  		c.Fatalf("Build 3's error wasn't the same as build 1's\n1:%s\n3:%s", err1, err2)
  5003  	}
  5004  
  5005  	ctx.Add("Dockerfile", "FROM busybox\n   COPY    ")
  5006  	if _, err2 = buildImageFromContext(name, ctx, false); err2 == nil {
  5007  		c.Fatal("Build 4 was supposed to fail, but didn't")
  5008  	}
  5009  
  5010  	// Skip over the times
  5011  	e1 = removeLogTimestamps(err1.Error())
  5012  	e2 = removeLogTimestamps(err2.Error())
  5013  
  5014  	// Ignore whitespace since that's what were verifying doesn't change stuff
  5015  	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
  5016  		c.Fatalf("Build 4's error wasn't the same as build 1's\n1:%s\n4:%s", err1, err2)
  5017  	}
  5018  
  5019  }
  5020  
  5021  func (s *DockerSuite) TestBuildSpacesWithQuotes(c *check.C) {
  5022  	// Test to make sure that spaces in quotes aren't lost
  5023  	name := "testspacesquotes"
  5024  
  5025  	dockerfile := `FROM busybox
  5026  RUN echo "  \
  5027    foo  "`
  5028  
  5029  	_, out, err := buildImageWithOut(name, dockerfile, false)
  5030  	if err != nil {
  5031  		c.Fatal("Build failed:", err)
  5032  	}
  5033  
  5034  	expecting := "\n    foo  \n"
  5035  	if !strings.Contains(out, expecting) {
  5036  		c.Fatalf("Bad output: %q expecting to contain %q", out, expecting)
  5037  	}
  5038  
  5039  }
  5040  
  5041  // #4393
  5042  func (s *DockerSuite) TestBuildVolumeFileExistsinContainer(c *check.C) {
  5043  	buildCmd := exec.Command(dockerBinary, "build", "-t", "docker-test-errcreatevolumewithfile", "-")
  5044  	buildCmd.Stdin = strings.NewReader(`
  5045  	FROM busybox
  5046  	RUN touch /foo
  5047  	VOLUME /foo
  5048  	`)
  5049  
  5050  	out, _, err := runCommandWithOutput(buildCmd)
  5051  	if err == nil || !strings.Contains(out, "file exists") {
  5052  		c.Fatalf("expected build to fail when file exists in container at requested volume path")
  5053  	}
  5054  
  5055  }
  5056  
  5057  func (s *DockerSuite) TestBuildMissingArgs(c *check.C) {
  5058  	// Test to make sure that all Dockerfile commands (except the ones listed
  5059  	// in skipCmds) will generate an error if no args are provided.
  5060  	// Note: INSERT is deprecated so we exclude it because of that.
  5061  	skipCmds := map[string]struct{}{
  5062  		"CMD":        {},
  5063  		"RUN":        {},
  5064  		"ENTRYPOINT": {},
  5065  		"INSERT":     {},
  5066  	}
  5067  
  5068  	for cmd := range command.Commands {
  5069  		cmd = strings.ToUpper(cmd)
  5070  		if _, ok := skipCmds[cmd]; ok {
  5071  			continue
  5072  		}
  5073  
  5074  		var dockerfile string
  5075  		if cmd == "FROM" {
  5076  			dockerfile = cmd
  5077  		} else {
  5078  			// Add FROM to make sure we don't complain about it missing
  5079  			dockerfile = "FROM busybox\n" + cmd
  5080  		}
  5081  
  5082  		ctx, err := fakeContext(dockerfile, map[string]string{})
  5083  		if err != nil {
  5084  			c.Fatal(err)
  5085  		}
  5086  		defer ctx.Close()
  5087  		var out string
  5088  		if out, err = buildImageFromContext("args", ctx, true); err == nil {
  5089  			c.Fatalf("%s was supposed to fail. Out:%s", cmd, out)
  5090  		}
  5091  		if !strings.Contains(err.Error(), cmd+" requires") {
  5092  			c.Fatalf("%s returned the wrong type of error:%s", cmd, err)
  5093  		}
  5094  	}
  5095  
  5096  }
  5097  
  5098  func (s *DockerSuite) TestBuildEmptyScratch(c *check.C) {
  5099  	_, out, err := buildImageWithOut("sc", "FROM scratch", true)
  5100  	if err == nil {
  5101  		c.Fatalf("Build was supposed to fail")
  5102  	}
  5103  	if !strings.Contains(out, "No image was generated") {
  5104  		c.Fatalf("Wrong error message: %v", out)
  5105  	}
  5106  }
  5107  
  5108  func (s *DockerSuite) TestBuildDotDotFile(c *check.C) {
  5109  	ctx, err := fakeContext("FROM busybox\n",
  5110  		map[string]string{
  5111  			"..gitme": "",
  5112  		})
  5113  	if err != nil {
  5114  		c.Fatal(err)
  5115  	}
  5116  	defer ctx.Close()
  5117  
  5118  	if _, err = buildImageFromContext("sc", ctx, false); err != nil {
  5119  		c.Fatalf("Build was supposed to work: %s", err)
  5120  	}
  5121  }
  5122  
  5123  func (s *DockerSuite) TestBuildNotVerbose(c *check.C) {
  5124  
  5125  	ctx, err := fakeContext("FROM busybox\nENV abc=hi\nRUN echo $abc there", map[string]string{})
  5126  	if err != nil {
  5127  		c.Fatal(err)
  5128  	}
  5129  	defer ctx.Close()
  5130  
  5131  	// First do it w/verbose - baseline
  5132  	buildCmd := exec.Command(dockerBinary, "build", "--no-cache", "-t", "verbose", ".")
  5133  	buildCmd.Dir = ctx.Dir
  5134  	out, _, err := runCommandWithOutput(buildCmd)
  5135  	if err != nil {
  5136  		c.Fatalf("failed to build the image w/o -q: %s, %v", out, err)
  5137  	}
  5138  	if !strings.Contains(out, "hi there") {
  5139  		c.Fatalf("missing output:%s\n", out)
  5140  	}
  5141  
  5142  	// Now do it w/o verbose
  5143  	buildCmd = exec.Command(dockerBinary, "build", "--no-cache", "-q", "-t", "verbose", ".")
  5144  	buildCmd.Dir = ctx.Dir
  5145  	out, _, err = runCommandWithOutput(buildCmd)
  5146  	if err != nil {
  5147  		c.Fatalf("failed to build the image w/ -q: %s, %v", out, err)
  5148  	}
  5149  	if strings.Contains(out, "hi there") {
  5150  		c.Fatalf("Bad output, should not contain 'hi there':%s", out)
  5151  	}
  5152  
  5153  }
  5154  
  5155  func (s *DockerSuite) TestBuildRUNoneJSON(c *check.C) {
  5156  	name := "testbuildrunonejson"
  5157  
  5158  	ctx, err := fakeContext(`FROM hello-world:frozen
  5159  RUN [ "/hello" ]`, map[string]string{})
  5160  	if err != nil {
  5161  		c.Fatal(err)
  5162  	}
  5163  	defer ctx.Close()
  5164  
  5165  	buildCmd := exec.Command(dockerBinary, "build", "--no-cache", "-t", name, ".")
  5166  	buildCmd.Dir = ctx.Dir
  5167  	out, _, err := runCommandWithOutput(buildCmd)
  5168  	if err != nil {
  5169  		c.Fatalf("failed to build the image: %s, %v", out, err)
  5170  	}
  5171  
  5172  	if !strings.Contains(out, "Hello from Docker") {
  5173  		c.Fatalf("bad output: %s", out)
  5174  	}
  5175  
  5176  }
  5177  
  5178  func (s *DockerSuite) TestBuildResourceConstraintsAreUsed(c *check.C) {
  5179  	name := "testbuildresourceconstraints"
  5180  
  5181  	ctx, err := fakeContext(`
  5182  	FROM hello-world:frozen
  5183  	RUN ["/hello"]
  5184  	`, map[string]string{})
  5185  	if err != nil {
  5186  		c.Fatal(err)
  5187  	}
  5188  
  5189  	cmd := exec.Command(dockerBinary, "build", "--no-cache", "--rm=false", "--memory=64m", "--memory-swap=-1", "--cpuset-cpus=0", "--cpuset-mems=0", "--cpu-shares=100", "--cpu-quota=8000", "-t", name, ".")
  5190  	cmd.Dir = ctx.Dir
  5191  
  5192  	out, _, err := runCommandWithOutput(cmd)
  5193  	if err != nil {
  5194  		c.Fatal(err, out)
  5195  	}
  5196  	out, _ = dockerCmd(c, "ps", "-lq")
  5197  
  5198  	cID := strings.TrimSpace(out)
  5199  
  5200  	type hostConfig struct {
  5201  		Memory     int64
  5202  		MemorySwap int64
  5203  		CpusetCpus string
  5204  		CpusetMems string
  5205  		CpuShares  int64
  5206  		CpuQuota   int64
  5207  	}
  5208  
  5209  	cfg, err := inspectFieldJSON(cID, "HostConfig")
  5210  	if err != nil {
  5211  		c.Fatal(err)
  5212  	}
  5213  
  5214  	var c1 hostConfig
  5215  	if err := json.Unmarshal([]byte(cfg), &c1); err != nil {
  5216  		c.Fatal(err, cfg)
  5217  	}
  5218  	if c1.Memory != 67108864 || c1.MemorySwap != -1 || c1.CpusetCpus != "0" || c1.CpusetMems != "0" || c1.CpuShares != 100 || c1.CpuQuota != 8000 {
  5219  		c.Fatalf("resource constraints not set properly:\nMemory: %d, MemSwap: %d, CpusetCpus: %s, CpusetMems: %s, CpuShares: %d, CpuQuota: %d",
  5220  			c1.Memory, c1.MemorySwap, c1.CpusetCpus, c1.CpusetMems, c1.CpuShares, c1.CpuQuota)
  5221  	}
  5222  
  5223  	// Make sure constraints aren't saved to image
  5224  	_, _ = dockerCmd(c, "run", "--name=test", name)
  5225  
  5226  	cfg, err = inspectFieldJSON("test", "HostConfig")
  5227  	if err != nil {
  5228  		c.Fatal(err)
  5229  	}
  5230  	var c2 hostConfig
  5231  	if err := json.Unmarshal([]byte(cfg), &c2); err != nil {
  5232  		c.Fatal(err, cfg)
  5233  	}
  5234  	if c2.Memory == 67108864 || c2.MemorySwap == -1 || c2.CpusetCpus == "0" || c2.CpusetMems == "0" || c2.CpuShares == 100 || c2.CpuQuota == 8000 {
  5235  		c.Fatalf("resource constraints leaked from build:\nMemory: %d, MemSwap: %d, CpusetCpus: %s, CpusetMems: %s, CpuShares: %d, CpuQuota: %d",
  5236  			c2.Memory, c2.MemorySwap, c2.CpusetCpus, c2.CpusetMems, c2.CpuShares, c2.CpuQuota)
  5237  	}
  5238  
  5239  }
  5240  
  5241  func (s *DockerSuite) TestBuildEmptyStringVolume(c *check.C) {
  5242  	name := "testbuildemptystringvolume"
  5243  
  5244  	_, err := buildImage(name, `
  5245    FROM busybox
  5246    ENV foo=""
  5247    VOLUME $foo
  5248    `, false)
  5249  	if err == nil {
  5250  		c.Fatal("Should have failed to build")
  5251  	}
  5252  
  5253  }