24 "github.com/docker/docker/integration-cli/checker"
25 "github.com/docker/docker/integration-cli/cli"
26 "github.com/docker/docker/integration-cli/cli/build"
27 "github.com/docker/docker/integration-cli/cli/build/fakecontext"
28 "github.com/docker/docker/pkg/mount"
29 "github.com/docker/docker/pkg/stringid"
30 "github.com/docker/docker/pkg/stringutils"
31 "github.com/docker/docker/pkg/testutil"
32 icmd "github.com/docker/docker/pkg/testutil/cmd"
33 "github.com/docker/docker/runconfig"
34 "github.com/docker/go-connections/nat"
35 "github.com/docker/libnetwork/resolvconf"
36 "github.com/docker/libnetwork/types"
37 "github.com/go-check/check"
38 libcontainerUser "github.com/opencontainers/runc/libcontainer/user"
41 // "test123" should be printed by docker run
42 func (s *DockerSuite) TestRunEchoStdout(c *check.C) {
43 out, _ := dockerCmd(c, "run", "busybox", "echo", "test123")
44 if out != "test123\n" {
45 c.Fatalf("container should've printed 'test123', got '%s'", out)
49 // "test" should be printed
50 func (s *DockerSuite) TestRunEchoNamedContainer(c *check.C) {
51 out, _ := dockerCmd(c, "run", "--name", "testfoonamedcontainer", "busybox", "echo", "test")
53 c.Errorf("container should've printed 'test'")
57 // docker run should not leak file descriptors. This test relies on Unix
58 // specific functionality and cannot run on Windows.
59 func (s *DockerSuite) TestRunLeakyFileDescriptors(c *check.C) {
60 testRequires(c, DaemonIsLinux)
61 out, _ := dockerCmd(c, "run", "busybox", "ls", "-C", "/proc/self/fd")
63 // normally, we should only get 0, 1, and 2, but 3 gets created by "ls" when it does "opendir" on the "fd" directory
64 if out != "0 1 2 3\n" {
65 c.Errorf("container should've printed '0 1 2 3', not: %s", out)
69 // it should be possible to lookup Google DNS
70 // this will fail when Internet access is unavailable
71 func (s *DockerSuite) TestRunLookupGoogleDNS(c *check.C) {
72 testRequires(c, Network, NotArm)
73 if testEnv.DaemonPlatform() == "windows" {
74 // nslookup isn't present in Windows busybox. Is built-in. Further,
75 // nslookup isn't present in nanoserver. Hence just use PowerShell...
76 dockerCmd(c, "run", testEnv.MinimalBaseImage(), "powershell", "Resolve-DNSName", "google.com")
78 dockerCmd(c, "run", "busybox", "nslookup", "google.com")
83 // the exit code should be 0
84 func (s *DockerSuite) TestRunExitCodeZero(c *check.C) {
85 dockerCmd(c, "run", "busybox", "true")
88 // the exit code should be 1
89 func (s *DockerSuite) TestRunExitCodeOne(c *check.C) {
90 _, exitCode, err := dockerCmdWithError("run", "busybox", "false")
91 c.Assert(err, checker.NotNil)
92 c.Assert(exitCode, checker.Equals, 1)
95 // it should be possible to pipe in data via stdin to a process running in a container
96 func (s *DockerSuite) TestRunStdinPipe(c *check.C) {
97 // TODO Windows: This needs some work to make compatible.
98 testRequires(c, DaemonIsLinux)
99 result := icmd.RunCmd(icmd.Cmd{
100 Command: []string{dockerBinary, "run", "-i", "-a", "stdin", "busybox", "cat"},
101 Stdin: strings.NewReader("blahblah"),
103 result.Assert(c, icmd.Success)
104 out := result.Stdout()
106 out = strings.TrimSpace(out)
107 dockerCmd(c, "wait", out)
109 logsOut, _ := dockerCmd(c, "logs", out)
111 containerLogs := strings.TrimSpace(logsOut)
112 if containerLogs != "blahblah" {
113 c.Errorf("logs didn't print the container's logs %s", containerLogs)
116 dockerCmd(c, "rm", out)
119 // the container's ID should be printed when starting a container in detached mode
120 func (s *DockerSuite) TestRunDetachedContainerIDPrinting(c *check.C) {
121 out, _ := dockerCmd(c, "run", "-d", "busybox", "true")
123 out = strings.TrimSpace(out)
124 dockerCmd(c, "wait", out)
126 rmOut, _ := dockerCmd(c, "rm", out)
128 rmOut = strings.TrimSpace(rmOut)
130 c.Errorf("rm didn't print the container ID %s %s", out, rmOut)
134 // the working directory should be set correctly
135 func (s *DockerSuite) TestRunWorkingDirectory(c *check.C) {
138 if testEnv.DaemonPlatform() == "windows" {
143 out, _ := dockerCmd(c, "run", "-w", dir, image, "pwd")
144 out = strings.TrimSpace(out)
146 c.Errorf("-w failed to set working directory")
149 // Then with --workdir
150 out, _ = dockerCmd(c, "run", "--workdir", dir, image, "pwd")
151 out = strings.TrimSpace(out)
153 c.Errorf("--workdir failed to set working directory")
157 // pinging Google's DNS resolver should fail when we disable the networking
158 func (s *DockerSuite) TestRunWithoutNetworking(c *check.C) {
161 if testEnv.DaemonPlatform() == "windows" {
163 image = testEnv.MinimalBaseImage()
166 // First using the long form --net
167 out, exitCode, err := dockerCmdWithError("run", "--net=none", image, "ping", count, "1", "8.8.8.8")
168 if err != nil && exitCode != 1 {
172 c.Errorf("--net=none should've disabled the network; the container shouldn't have been able to ping 8.8.8.8")
176 //test --link use container name to link target
177 func (s *DockerSuite) TestRunLinksContainerWithContainerName(c *check.C) {
178 // TODO Windows: This test cannot run on a Windows daemon as the networking
179 // settings are not populated back yet on inspect.
180 testRequires(c, DaemonIsLinux)
181 dockerCmd(c, "run", "-i", "-t", "-d", "--name", "parent", "busybox")
183 ip := inspectField(c, "parent", "NetworkSettings.Networks.bridge.IPAddress")
185 out, _ := dockerCmd(c, "run", "--link", "parent:test", "busybox", "/bin/cat", "/etc/hosts")
186 if !strings.Contains(out, ip+" test") {
187 c.Fatalf("use a container name to link target failed")
191 //test --link use container id to link target
192 func (s *DockerSuite) TestRunLinksContainerWithContainerID(c *check.C) {
193 // TODO Windows: This test cannot run on a Windows daemon as the networking
194 // settings are not populated back yet on inspect.
195 testRequires(c, DaemonIsLinux)
196 cID, _ := dockerCmd(c, "run", "-i", "-t", "-d", "busybox")
198 cID = strings.TrimSpace(cID)
199 ip := inspectField(c, cID, "NetworkSettings.Networks.bridge.IPAddress")
201 out, _ := dockerCmd(c, "run", "--link", cID+":test", "busybox", "/bin/cat", "/etc/hosts")
202 if !strings.Contains(out, ip+" test") {
203 c.Fatalf("use a container id to link target failed")
207 func (s *DockerSuite) TestUserDefinedNetworkLinks(c *check.C) {
208 testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm)
209 dockerCmd(c, "network", "create", "-d", "bridge", "udlinkNet")
211 dockerCmd(c, "run", "-d", "--net=udlinkNet", "--name=first", "busybox", "top")
212 c.Assert(waitRun("first"), check.IsNil)
214 // run a container in user-defined network udlinkNet with a link for an existing container
215 // and a link for a container that doesn't exist
216 dockerCmd(c, "run", "-d", "--net=udlinkNet", "--name=second", "--link=first:foo",
217 "--link=third:bar", "busybox", "top")
218 c.Assert(waitRun("second"), check.IsNil)
220 // ping to first and its alias foo must succeed
221 _, _, err := dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
222 c.Assert(err, check.IsNil)
223 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo")
224 c.Assert(err, check.IsNil)
226 // ping to third and its alias must fail
227 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "third")
228 c.Assert(err, check.NotNil)
229 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "bar")
230 c.Assert(err, check.NotNil)
232 // start third container now
233 dockerCmd(c, "run", "-d", "--net=udlinkNet", "--name=third", "busybox", "top")
234 c.Assert(waitRun("third"), check.IsNil)
236 // ping to third and its alias must succeed now
237 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "third")
238 c.Assert(err, check.IsNil)
239 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "bar")
240 c.Assert(err, check.IsNil)
243 func (s *DockerSuite) TestUserDefinedNetworkLinksWithRestart(c *check.C) {
244 testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm)
245 dockerCmd(c, "network", "create", "-d", "bridge", "udlinkNet")
247 dockerCmd(c, "run", "-d", "--net=udlinkNet", "--name=first", "busybox", "top")
248 c.Assert(waitRun("first"), check.IsNil)
250 dockerCmd(c, "run", "-d", "--net=udlinkNet", "--name=second", "--link=first:foo",
252 c.Assert(waitRun("second"), check.IsNil)
254 // ping to first and its alias foo must succeed
255 _, _, err := dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
256 c.Assert(err, check.IsNil)
257 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo")
258 c.Assert(err, check.IsNil)
260 // Restart first container
261 dockerCmd(c, "restart", "first")
262 c.Assert(waitRun("first"), check.IsNil)
264 // ping to first and its alias foo must still succeed
265 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
266 c.Assert(err, check.IsNil)
267 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo")
268 c.Assert(err, check.IsNil)
270 // Restart second container
271 dockerCmd(c, "restart", "second")
272 c.Assert(waitRun("second"), check.IsNil)
274 // ping to first and its alias foo must still succeed
275 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
276 c.Assert(err, check.IsNil)
277 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo")
278 c.Assert(err, check.IsNil)
281 func (s *DockerSuite) TestRunWithNetAliasOnDefaultNetworks(c *check.C) {
282 testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm)
284 defaults := []string{"bridge", "host", "none"}
285 for _, net := range defaults {
286 out, _, err := dockerCmdWithError("run", "-d", "--net", net, "--net-alias", "alias_"+net, "busybox", "top")
287 c.Assert(err, checker.NotNil)
288 c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkAndAlias.Error())
292 func (s *DockerSuite) TestUserDefinedNetworkAlias(c *check.C) {
293 testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm)
294 dockerCmd(c, "network", "create", "-d", "bridge", "net1")
296 cid1, _ := dockerCmd(c, "run", "-d", "--net=net1", "--name=first", "--net-alias=foo1", "--net-alias=foo2", "busybox", "top")
297 c.Assert(waitRun("first"), check.IsNil)
299 // Check if default short-id alias is added automatically
300 id := strings.TrimSpace(cid1)
301 aliases := inspectField(c, id, "NetworkSettings.Networks.net1.Aliases")
302 c.Assert(aliases, checker.Contains, stringid.TruncateID(id))
304 cid2, _ := dockerCmd(c, "run", "-d", "--net=net1", "--name=second", "busybox", "top")
305 c.Assert(waitRun("second"), check.IsNil)
307 // Check if default short-id alias is added automatically
308 id = strings.TrimSpace(cid2)
309 aliases = inspectField(c, id, "NetworkSettings.Networks.net1.Aliases")
310 c.Assert(aliases, checker.Contains, stringid.TruncateID(id))
312 // ping to first and its network-scoped aliases
313 _, _, err := dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
314 c.Assert(err, check.IsNil)
315 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo1")
316 c.Assert(err, check.IsNil)
317 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo2")
318 c.Assert(err, check.IsNil)
319 // ping first container's short-id alias
320 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", stringid.TruncateID(cid1))
321 c.Assert(err, check.IsNil)
323 // Restart first container
324 dockerCmd(c, "restart", "first")
325 c.Assert(waitRun("first"), check.IsNil)
327 // ping to first and its network-scoped aliases must succeed
328 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
329 c.Assert(err, check.IsNil)
330 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo1")
331 c.Assert(err, check.IsNil)
332 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo2")
333 c.Assert(err, check.IsNil)
334 // ping first container's short-id alias
335 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", stringid.TruncateID(cid1))
336 c.Assert(err, check.IsNil)
340 func (s *DockerSuite) TestRunWithDaemonFlags(c *check.C) {
341 out, _, err := dockerCmdWithError("--exec-opt", "foo=bar", "run", "-i", "busybox", "true")
342 c.Assert(err, checker.NotNil)
343 c.Assert(out, checker.Contains, "unknown flag: --exec-opt")
346 // Regression test for #4979
347 func (s *DockerSuite) TestRunWithVolumesFromExited(c *check.C) {
354 // Create a file in a volume
355 if testEnv.DaemonPlatform() == "windows" {
356 out, exitCode = dockerCmd(c, "run", "--name", "test-data", "--volume", `c:\some\dir`, testEnv.MinimalBaseImage(), "cmd", "/c", `echo hello > c:\some\dir\file`)
358 out, exitCode = dockerCmd(c, "run", "--name", "test-data", "--volume", "/some/dir", "busybox", "touch", "/some/dir/file")
361 c.Fatal("1", out, exitCode)
364 // Read the file from another container using --volumes-from to access the volume in the second container
365 if testEnv.DaemonPlatform() == "windows" {
366 out, exitCode = dockerCmd(c, "run", "--volumes-from", "test-data", testEnv.MinimalBaseImage(), "cmd", "/c", `type c:\some\dir\file`)
368 out, exitCode = dockerCmd(c, "run", "--volumes-from", "test-data", "busybox", "cat", "/some/dir/file")
371 c.Fatal("2", out, exitCode)
375 // Volume path is a symlink which also exists on the host, and the host side is a file not a dir
376 // But the volume call is just a normal volume, not a bind mount
377 func (s *DockerSuite) TestRunCreateVolumesInSymlinkDir(c *check.C) {
383 // This test cannot run on a Windows daemon as
384 // Windows does not support symlinks inside a volume path
385 testRequires(c, SameHostDaemon, DaemonIsLinux)
386 name := "test-volume-symlink"
388 dir, err := ioutil.TempDir("", name)
392 defer os.RemoveAll(dir)
394 // In the case of Windows to Windows CI, if the machine is setup so that
395 // the temp directory is not the C: drive, this test is invalid and will
397 if testEnv.DaemonPlatform() == "windows" && strings.ToLower(dir[:1]) != "c" {
398 c.Skip("Requires TEMP to point to C: drive")
401 f, err := os.OpenFile(filepath.Join(dir, "test"), os.O_CREATE, 0700)
407 if testEnv.DaemonPlatform() == "windows" {
408 dockerFile = fmt.Sprintf("FROM %s\nRUN mkdir %s\nRUN mklink /D c:\\test %s", testEnv.MinimalBaseImage(), dir, dir)
409 containerPath = `c:\test\test`
412 dockerFile = fmt.Sprintf("FROM busybox\nRUN mkdir -p %s\nRUN ln -s %s /test", dir, dir)
413 containerPath = "/test/test"
416 buildImageSuccessfully(c, name, build.WithDockerfile(dockerFile))
417 dockerCmd(c, "run", "-v", containerPath, name, cmd)
420 // Volume path is a symlink in the container
421 func (s *DockerSuite) TestRunCreateVolumesInSymlinkDir2(c *check.C) {
427 // This test cannot run on a Windows daemon as
428 // Windows does not support symlinks inside a volume path
429 testRequires(c, SameHostDaemon, DaemonIsLinux)
430 name := "test-volume-symlink2"
432 if testEnv.DaemonPlatform() == "windows" {
433 dockerFile = fmt.Sprintf("FROM %s\nRUN mkdir c:\\%s\nRUN mklink /D c:\\test c:\\%s", testEnv.MinimalBaseImage(), name, name)
434 containerPath = `c:\test\test`
437 dockerFile = fmt.Sprintf("FROM busybox\nRUN mkdir -p /%s\nRUN ln -s /%s /test", name, name)
438 containerPath = "/test/test"
441 buildImageSuccessfully(c, name, build.WithDockerfile(dockerFile))
442 dockerCmd(c, "run", "-v", containerPath, name, cmd)
445 func (s *DockerSuite) TestRunVolumesMountedAsReadonly(c *check.C) {
446 if _, code, err := dockerCmdWithError("run", "-v", "/test:/test:ro", "busybox", "touch", "/test/somefile"); err == nil || code == 0 {
447 c.Fatalf("run should fail because volume is ro: exit code %d", code)
451 func (s *DockerSuite) TestRunVolumesFromInReadonlyModeFails(c *check.C) {
456 if testEnv.DaemonPlatform() == "windows" {
457 volumeDir = `c:/test` // Forward-slash as using busybox
458 fileInVol = `c:/test/file`
460 testRequires(c, DaemonIsLinux)
462 fileInVol = `/test/file`
464 dockerCmd(c, "run", "--name", "parent", "-v", volumeDir, "busybox", "true")
466 if _, code, err := dockerCmdWithError("run", "--volumes-from", "parent:ro", "busybox", "touch", fileInVol); err == nil || code == 0 {
467 c.Fatalf("run should fail because volume is ro: exit code %d", code)
471 // Regression test for #1201
472 func (s *DockerSuite) TestRunVolumesFromInReadWriteMode(c *check.C) {
477 if testEnv.DaemonPlatform() == "windows" {
478 volumeDir = `c:/test` // Forward-slash as using busybox
479 fileInVol = `c:/test/file`
482 fileInVol = "/test/file"
485 dockerCmd(c, "run", "--name", "parent", "-v", volumeDir, "busybox", "true")
486 dockerCmd(c, "run", "--volumes-from", "parent:rw", "busybox", "touch", fileInVol)
488 if out, _, err := dockerCmdWithError("run", "--volumes-from", "parent:bar", "busybox", "touch", fileInVol); err == nil || !strings.Contains(out, `invalid mode: bar`) {
489 c.Fatalf("running --volumes-from parent:bar should have failed with invalid mode: %q", out)
492 dockerCmd(c, "run", "--volumes-from", "parent", "busybox", "touch", fileInVol)
495 func (s *DockerSuite) TestVolumesFromGetsProperMode(c *check.C) {
496 testRequires(c, SameHostDaemon)
497 prefix, slash := getPrefixAndSlashFromDaemonPlatform()
498 hostpath := testutil.RandomTmpDirPath("test", testEnv.DaemonPlatform())
499 if err := os.MkdirAll(hostpath, 0755); err != nil {
500 c.Fatalf("Failed to create %s: %q", hostpath, err)
502 defer os.RemoveAll(hostpath)
504 dockerCmd(c, "run", "--name", "parent", "-v", hostpath+":"+prefix+slash+"test:ro", "busybox", "true")
506 // Expect this "rw" mode to be be ignored since the inherited volume is "ro"
507 if _, _, err := dockerCmdWithError("run", "--volumes-from", "parent:rw", "busybox", "touch", prefix+slash+"test"+slash+"file"); err == nil {
508 c.Fatal("Expected volumes-from to inherit read-only volume even when passing in `rw`")
511 dockerCmd(c, "run", "--name", "parent2", "-v", hostpath+":"+prefix+slash+"test:ro", "busybox", "true")
513 // Expect this to be read-only since both are "ro"
514 if _, _, err := dockerCmdWithError("run", "--volumes-from", "parent2:ro", "busybox", "touch", prefix+slash+"test"+slash+"file"); err == nil {
515 c.Fatal("Expected volumes-from to inherit read-only volume even when passing in `ro`")
520 func (s *DockerSuite) TestRunNoDupVolumes(c *check.C) {
521 path1 := testutil.RandomTmpDirPath("test1", testEnv.DaemonPlatform())
522 path2 := testutil.RandomTmpDirPath("test2", testEnv.DaemonPlatform())
524 someplace := ":/someplace"
525 if testEnv.DaemonPlatform() == "windows" {
526 // Windows requires that the source directory exists before calling HCS
527 testRequires(c, SameHostDaemon)
528 someplace = `:c:\someplace`
529 if err := os.MkdirAll(path1, 0755); err != nil {
530 c.Fatalf("Failed to create %s: %q", path1, err)
532 defer os.RemoveAll(path1)
533 if err := os.MkdirAll(path2, 0755); err != nil {
534 c.Fatalf("Failed to create %s: %q", path1, err)
536 defer os.RemoveAll(path2)
538 mountstr1 := path1 + someplace
539 mountstr2 := path2 + someplace
541 if out, _, err := dockerCmdWithError("run", "-v", mountstr1, "-v", mountstr2, "busybox", "true"); err == nil {
542 c.Fatal("Expected error about duplicate mount definitions")
544 if !strings.Contains(out, "Duplicate mount point") {
545 c.Fatalf("Expected 'duplicate mount point' error, got %v", out)
549 // Test for https://github.com/docker/docker/issues/22093
550 volumename1 := "test1"
551 volumename2 := "test2"
552 volume1 := volumename1 + someplace
553 volume2 := volumename2 + someplace
554 if out, _, err := dockerCmdWithError("run", "-v", volume1, "-v", volume2, "busybox", "true"); err == nil {
555 c.Fatal("Expected error about duplicate mount definitions")
557 if !strings.Contains(out, "Duplicate mount point") {
558 c.Fatalf("Expected 'duplicate mount point' error, got %v", out)
561 // create failed should have create volume volumename1 or volumename2
562 // we should remove volumename2 or volumename2 successfully
563 out, _ := dockerCmd(c, "volume", "ls")
564 if strings.Contains(out, volumename1) {
565 dockerCmd(c, "volume", "rm", volumename1)
567 dockerCmd(c, "volume", "rm", volumename2)
572 func (s *DockerSuite) TestRunApplyVolumesFromBeforeVolumes(c *check.C) {
574 if testEnv.DaemonPlatform() == "windows" {
577 dockerCmd(c, "run", "--name", "parent", "-v", prefix+"/test", "busybox", "touch", prefix+"/test/foo")
578 dockerCmd(c, "run", "--volumes-from", "parent", "-v", prefix+"/test", "busybox", "cat", prefix+"/test/foo")
581 func (s *DockerSuite) TestRunMultipleVolumesFrom(c *check.C) {
583 if testEnv.DaemonPlatform() == "windows" {
586 dockerCmd(c, "run", "--name", "parent1", "-v", prefix+"/test", "busybox", "touch", prefix+"/test/foo")
587 dockerCmd(c, "run", "--name", "parent2", "-v", prefix+"/other", "busybox", "touch", prefix+"/other/bar")
588 dockerCmd(c, "run", "--volumes-from", "parent1", "--volumes-from", "parent2", "busybox", "sh", "-c", "cat /test/foo && cat /other/bar")
591 // this tests verifies the ID format for the container
592 func (s *DockerSuite) TestRunVerifyContainerID(c *check.C) {
593 out, exit, err := dockerCmdWithError("run", "-d", "busybox", "true")
598 c.Fatalf("expected exit code 0 received %d", exit)
601 match, err := regexp.MatchString("^[0-9a-f]{64}$", strings.TrimSuffix(out, "\n"))
606 c.Fatalf("Invalid container ID: %s", out)
610 // Test that creating a container with a volume doesn't crash. Regression test for #995.
611 func (s *DockerSuite) TestRunCreateVolume(c *check.C) {
613 if testEnv.DaemonPlatform() == "windows" {
616 dockerCmd(c, "run", "-v", prefix+"/var/lib/data", "busybox", "true")
619 // Test that creating a volume with a symlink in its path works correctly. Test for #5152.
620 // Note that this bug happens only with symlinks with a target that starts with '/'.
621 func (s *DockerSuite) TestRunCreateVolumeWithSymlink(c *check.C) {
622 // Cannot run on Windows as relies on Linux-specific functionality (sh -c mount...)
623 testRequires(c, DaemonIsLinux)
624 workingDirectory, err := ioutil.TempDir("", "TestRunCreateVolumeWithSymlink")
625 image := "docker-test-createvolumewithsymlink"
627 buildCmd := exec.Command(dockerBinary, "build", "-t", image, "-")
628 buildCmd.Stdin = strings.NewReader(`FROM busybox
629 RUN ln -s home /bar`)
630 buildCmd.Dir = workingDirectory
633 c.Fatalf("could not build '%s': %v", image, err)
636 _, exitCode, err := dockerCmdWithError("run", "-v", "/bar/foo", "--name", "test-createvolumewithsymlink", image, "sh", "-c", "mount | grep -q /home/foo")
637 if err != nil || exitCode != 0 {
638 c.Fatalf("[run] err: %v, exitcode: %d", err, exitCode)
641 volPath, err := inspectMountSourceField("test-createvolumewithsymlink", "/bar/foo")
642 c.Assert(err, checker.IsNil)
644 _, exitCode, err = dockerCmdWithError("rm", "-v", "test-createvolumewithsymlink")
645 if err != nil || exitCode != 0 {
646 c.Fatalf("[rm] err: %v, exitcode: %d", err, exitCode)
649 _, err = os.Stat(volPath)
650 if !os.IsNotExist(err) {
651 c.Fatalf("[open] (expecting 'file does not exist' error) err: %v, volPath: %s", err, volPath)
655 // Tests that a volume path that has a symlink exists in a container mounting it with `--volumes-from`.
656 func (s *DockerSuite) TestRunVolumesFromSymlinkPath(c *check.C) {
657 // This test cannot run on a Windows daemon as
658 // Windows does not support symlinks inside a volume path
659 testRequires(c, DaemonIsLinux)
661 workingDirectory, err := ioutil.TempDir("", "TestRunVolumesFromSymlinkPath")
662 c.Assert(err, checker.IsNil)
663 name := "docker-test-volumesfromsymlinkpath"
665 dfContents := `FROM busybox
669 if testEnv.DaemonPlatform() == "windows" {
671 dfContents = `FROM ` + testEnv.MinimalBaseImage() + `
673 RUN mklink /D c:\foo c:\home
674 VOLUME ["c:/foo/bar"]
675 ENTRYPOINT c:\windows\system32\cmd.exe`
678 buildCmd := exec.Command(dockerBinary, "build", "-t", name, "-")
679 buildCmd.Stdin = strings.NewReader(dfContents)
680 buildCmd.Dir = workingDirectory
683 c.Fatalf("could not build 'docker-test-volumesfromsymlinkpath': %v", err)
686 out, exitCode, err := dockerCmdWithError("run", "--name", "test-volumesfromsymlinkpath", name)
687 if err != nil || exitCode != 0 {
688 c.Fatalf("[run] (volume) err: %v, exitcode: %d, out: %s", err, exitCode, out)
691 _, exitCode, err = dockerCmdWithError("run", "--volumes-from", "test-volumesfromsymlinkpath", "busybox", "sh", "-c", "ls "+prefix+"/foo | grep -q bar")
692 if err != nil || exitCode != 0 {
693 c.Fatalf("[run] err: %v, exitcode: %d", err, exitCode)
697 func (s *DockerSuite) TestRunExitCode(c *check.C) {
703 _, exit, err = dockerCmdWithError("run", "busybox", "/bin/sh", "-c", "exit 72")
706 c.Fatal("should not have a non nil error")
709 c.Fatalf("expected exit code 72 received %d", exit)
713 func (s *DockerSuite) TestRunUserDefaults(c *check.C) {
714 expected := "uid=0(root) gid=0(root)"
715 if testEnv.DaemonPlatform() == "windows" {
716 expected = "uid=1000(ContainerAdministrator) gid=1000(ContainerAdministrator)"
718 out, _ := dockerCmd(c, "run", "busybox", "id")
719 if !strings.Contains(out, expected) {
720 c.Fatalf("expected '%s' got %s", expected, out)
724 func (s *DockerSuite) TestRunUserByName(c *check.C) {
725 // TODO Windows: This test cannot run on a Windows daemon as Windows does
726 // not support the use of -u
727 testRequires(c, DaemonIsLinux)
728 out, _ := dockerCmd(c, "run", "-u", "root", "busybox", "id")
729 if !strings.Contains(out, "uid=0(root) gid=0(root)") {
730 c.Fatalf("expected root user got %s", out)
734 func (s *DockerSuite) TestRunUserByID(c *check.C) {
735 // TODO Windows: This test cannot run on a Windows daemon as Windows does
736 // not support the use of -u
737 testRequires(c, DaemonIsLinux)
738 out, _ := dockerCmd(c, "run", "-u", "1", "busybox", "id")
739 if !strings.Contains(out, "uid=1(daemon) gid=1(daemon)") {
740 c.Fatalf("expected daemon user got %s", out)
744 func (s *DockerSuite) TestRunUserByIDBig(c *check.C) {
745 // TODO Windows: This test cannot run on a Windows daemon as Windows does
746 // not support the use of -u
747 testRequires(c, DaemonIsLinux, NotArm)
748 out, _, err := dockerCmdWithError("run", "-u", "2147483648", "busybox", "id")
750 c.Fatal("No error, but must be.", out)
752 if !strings.Contains(strings.ToUpper(out), strings.ToUpper(libcontainerUser.ErrRange.Error())) {
753 c.Fatalf("expected error about uids range, got %s", out)
757 func (s *DockerSuite) TestRunUserByIDNegative(c *check.C) {
758 // TODO Windows: This test cannot run on a Windows daemon as Windows does
759 // not support the use of -u
760 testRequires(c, DaemonIsLinux)
761 out, _, err := dockerCmdWithError("run", "-u", "-1", "busybox", "id")
763 c.Fatal("No error, but must be.", out)
765 if !strings.Contains(strings.ToUpper(out), strings.ToUpper(libcontainerUser.ErrRange.Error())) {
766 c.Fatalf("expected error about uids range, got %s", out)
770 func (s *DockerSuite) TestRunUserByIDZero(c *check.C) {
771 // TODO Windows: This test cannot run on a Windows daemon as Windows does
772 // not support the use of -u
773 testRequires(c, DaemonIsLinux)
774 out, _, err := dockerCmdWithError("run", "-u", "0", "busybox", "id")
778 if !strings.Contains(out, "uid=0(root) gid=0(root) groups=10(wheel)") {
779 c.Fatalf("expected daemon user got %s", out)
783 func (s *DockerSuite) TestRunUserNotFound(c *check.C) {
784 // TODO Windows: This test cannot run on a Windows daemon as Windows does
785 // not support the use of -u
786 testRequires(c, DaemonIsLinux)
787 _, _, err := dockerCmdWithError("run", "-u", "notme", "busybox", "id")
789 c.Fatal("unknown user should cause container to fail")
793 func (s *DockerSuite) TestRunTwoConcurrentContainers(c *check.C) {
795 group := sync.WaitGroup{}
798 errChan := make(chan error, 2)
799 for i := 0; i < 2; i++ {
802 _, _, err := dockerCmdWithError("run", "busybox", "sleep", sleepTime)
810 for err := range errChan {
811 c.Assert(err, check.IsNil)
815 func (s *DockerSuite) TestRunEnvironment(c *check.C) {
816 // TODO Windows: Environment handling is different between Linux and
817 // Windows and this test relies currently on unix functionality.
818 testRequires(c, DaemonIsLinux)
819 result := icmd.RunCmd(icmd.Cmd{
820 Command: []string{dockerBinary, "run", "-h", "testing", "-e=FALSE=true", "-e=TRUE", "-e=TRICKY", "-e=HOME=", "busybox", "env"},
821 Env: append(os.Environ(),
826 result.Assert(c, icmd.Success)
828 actualEnv := strings.Split(strings.TrimSpace(result.Combined()), "\n")
829 sort.Strings(actualEnv)
832 // The first two should not be tested here, those are "inherent" environment variable. This test validates
833 // the -e behavior, not the default environment variable (that could be subject to change)
834 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
843 sort.Strings(goodEnv)
844 if len(goodEnv) != len(actualEnv) {
845 c.Fatalf("Wrong environment: should be %d variables, not %d: %q", len(goodEnv), len(actualEnv), strings.Join(actualEnv, ", "))
847 for i := range goodEnv {
848 if actualEnv[i] != goodEnv[i] {
849 c.Fatalf("Wrong environment variable: should be %s, not %s", goodEnv[i], actualEnv[i])
854 func (s *DockerSuite) TestRunEnvironmentErase(c *check.C) {
855 // TODO Windows: Environment handling is different between Linux and
856 // Windows and this test relies currently on unix functionality.
857 testRequires(c, DaemonIsLinux)
859 // Test to make sure that when we use -e on env vars that are
860 // not set in our local env that they're removed (if present) in
863 result := icmd.RunCmd(icmd.Cmd{
864 Command: []string{dockerBinary, "run", "-e", "FOO", "-e", "HOSTNAME", "busybox", "env"},
865 Env: appendBaseEnv(true),
867 result.Assert(c, icmd.Success)
869 actualEnv := strings.Split(strings.TrimSpace(result.Combined()), "\n")
870 sort.Strings(actualEnv)
873 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
876 sort.Strings(goodEnv)
877 if len(goodEnv) != len(actualEnv) {
878 c.Fatalf("Wrong environment: should be %d variables, not %d: %q", len(goodEnv), len(actualEnv), strings.Join(actualEnv, ", "))
880 for i := range goodEnv {
881 if actualEnv[i] != goodEnv[i] {
882 c.Fatalf("Wrong environment variable: should be %s, not %s", goodEnv[i], actualEnv[i])
887 func (s *DockerSuite) TestRunEnvironmentOverride(c *check.C) {
888 // TODO Windows: Environment handling is different between Linux and
889 // Windows and this test relies currently on unix functionality.
890 testRequires(c, DaemonIsLinux)
892 // Test to make sure that when we use -e on env vars that are
893 // already in the env that we're overriding them
895 result := icmd.RunCmd(icmd.Cmd{
896 Command: []string{dockerBinary, "run", "-e", "HOSTNAME", "-e", "HOME=/root2", "busybox", "env"},
897 Env: appendBaseEnv(true, "HOSTNAME=bar"),
899 result.Assert(c, icmd.Success)
901 actualEnv := strings.Split(strings.TrimSpace(result.Combined()), "\n")
902 sort.Strings(actualEnv)
905 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
909 sort.Strings(goodEnv)
910 if len(goodEnv) != len(actualEnv) {
911 c.Fatalf("Wrong environment: should be %d variables, not %d: %q", len(goodEnv), len(actualEnv), strings.Join(actualEnv, ", "))
913 for i := range goodEnv {
914 if actualEnv[i] != goodEnv[i] {
915 c.Fatalf("Wrong environment variable: should be %s, not %s", goodEnv[i], actualEnv[i])
920 func (s *DockerSuite) TestRunContainerNetwork(c *check.C) {
921 if testEnv.DaemonPlatform() == "windows" {
922 // Windows busybox does not have ping. Use built in ping instead.
923 dockerCmd(c, "run", testEnv.MinimalBaseImage(), "ping", "-n", "1", "127.0.0.1")
925 dockerCmd(c, "run", "busybox", "ping", "-c", "1", "127.0.0.1")
929 func (s *DockerSuite) TestRunNetHostNotAllowedWithLinks(c *check.C) {
930 // TODO Windows: This is Linux specific as --link is not supported and
931 // this will be deprecated in favor of container networking model.
932 testRequires(c, DaemonIsLinux, NotUserNamespace)
933 dockerCmd(c, "run", "--name", "linked", "busybox", "true")
935 _, _, err := dockerCmdWithError("run", "--net=host", "--link", "linked:linked", "busybox", "true")
937 c.Fatal("Expected error")
941 // #7851 hostname outside container shows FQDN, inside only shortname
942 // For testing purposes it is not required to set host's hostname directly
943 // and use "--net=host" (as the original issue submitter did), as the same
944 // codepath is executed with "docker run -h <hostname>". Both were manually
945 // tested, but this testcase takes the simpler path of using "run -h .."
946 func (s *DockerSuite) TestRunFullHostnameSet(c *check.C) {
947 // TODO Windows: -h is not yet functional.
948 testRequires(c, DaemonIsLinux)
949 out, _ := dockerCmd(c, "run", "-h", "foo.bar.baz", "busybox", "hostname")
950 if actual := strings.Trim(out, "\r\n"); actual != "foo.bar.baz" {
951 c.Fatalf("expected hostname 'foo.bar.baz', received %s", actual)
955 func (s *DockerSuite) TestRunPrivilegedCanMknod(c *check.C) {
956 // Not applicable for Windows as Windows daemon does not support
957 // the concept of --privileged, and mknod is a Unix concept.
958 testRequires(c, DaemonIsLinux, NotUserNamespace)
959 out, _ := dockerCmd(c, "run", "--privileged", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
960 if actual := strings.Trim(out, "\r\n"); actual != "ok" {
961 c.Fatalf("expected output ok received %s", actual)
965 func (s *DockerSuite) TestRunUnprivilegedCanMknod(c *check.C) {
966 // Not applicable for Windows as Windows daemon does not support
967 // the concept of --privileged, and mknod is a Unix concept.
968 testRequires(c, DaemonIsLinux, NotUserNamespace)
969 out, _ := dockerCmd(c, "run", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
970 if actual := strings.Trim(out, "\r\n"); actual != "ok" {
971 c.Fatalf("expected output ok received %s", actual)
975 func (s *DockerSuite) TestRunCapDropInvalid(c *check.C) {
976 // Not applicable for Windows as there is no concept of --cap-drop
977 testRequires(c, DaemonIsLinux)
978 out, _, err := dockerCmdWithError("run", "--cap-drop=CHPASS", "busybox", "ls")
984 func (s *DockerSuite) TestRunCapDropCannotMknod(c *check.C) {
985 // Not applicable for Windows as there is no concept of --cap-drop or mknod
986 testRequires(c, DaemonIsLinux)
987 out, _, err := dockerCmdWithError("run", "--cap-drop=MKNOD", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
992 if actual := strings.Trim(out, "\r\n"); actual == "ok" {
993 c.Fatalf("expected output not ok received %s", actual)
997 func (s *DockerSuite) TestRunCapDropCannotMknodLowerCase(c *check.C) {
998 // Not applicable for Windows as there is no concept of --cap-drop or mknod
999 testRequires(c, DaemonIsLinux)
1000 out, _, err := dockerCmdWithError("run", "--cap-drop=mknod", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
1005 if actual := strings.Trim(out, "\r\n"); actual == "ok" {
1006 c.Fatalf("expected output not ok received %s", actual)
1010 func (s *DockerSuite) TestRunCapDropALLCannotMknod(c *check.C) {
1011 // Not applicable for Windows as there is no concept of --cap-drop or mknod
1012 testRequires(c, DaemonIsLinux)
1013 out, _, err := dockerCmdWithError("run", "--cap-drop=ALL", "--cap-add=SETGID", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
1017 if actual := strings.Trim(out, "\r\n"); actual == "ok" {
1018 c.Fatalf("expected output not ok received %s", actual)
1022 func (s *DockerSuite) TestRunCapDropALLAddMknodCanMknod(c *check.C) {
1023 // Not applicable for Windows as there is no concept of --cap-drop or mknod
1024 testRequires(c, DaemonIsLinux, NotUserNamespace)
1025 out, _ := dockerCmd(c, "run", "--cap-drop=ALL", "--cap-add=MKNOD", "--cap-add=SETGID", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
1027 if actual := strings.Trim(out, "\r\n"); actual != "ok" {
1028 c.Fatalf("expected output ok received %s", actual)
1032 func (s *DockerSuite) TestRunCapAddInvalid(c *check.C) {
1033 // Not applicable for Windows as there is no concept of --cap-add
1034 testRequires(c, DaemonIsLinux)
1035 out, _, err := dockerCmdWithError("run", "--cap-add=CHPASS", "busybox", "ls")
1041 func (s *DockerSuite) TestRunCapAddCanDownInterface(c *check.C) {
1042 // Not applicable for Windows as there is no concept of --cap-add
1043 testRequires(c, DaemonIsLinux)
1044 out, _ := dockerCmd(c, "run", "--cap-add=NET_ADMIN", "busybox", "sh", "-c", "ip link set eth0 down && echo ok")
1046 if actual := strings.Trim(out, "\r\n"); actual != "ok" {
1047 c.Fatalf("expected output ok received %s", actual)
1051 func (s *DockerSuite) TestRunCapAddALLCanDownInterface(c *check.C) {
1052 // Not applicable for Windows as there is no concept of --cap-add
1053 testRequires(c, DaemonIsLinux)
1054 out, _ := dockerCmd(c, "run", "--cap-add=ALL", "busybox", "sh", "-c", "ip link set eth0 down && echo ok")
1056 if actual := strings.Trim(out, "\r\n"); actual != "ok" {
1057 c.Fatalf("expected output ok received %s", actual)
1061 func (s *DockerSuite) TestRunCapAddALLDropNetAdminCanDownInterface(c *check.C) {
1062 // Not applicable for Windows as there is no concept of --cap-add
1063 testRequires(c, DaemonIsLinux)
1064 out, _, err := dockerCmdWithError("run", "--cap-add=ALL", "--cap-drop=NET_ADMIN", "busybox", "sh", "-c", "ip link set eth0 down && echo ok")
1068 if actual := strings.Trim(out, "\r\n"); actual == "ok" {
1069 c.Fatalf("expected output not ok received %s", actual)
1073 func (s *DockerSuite) TestRunGroupAdd(c *check.C) {
1074 // Not applicable for Windows as there is no concept of --group-add
1075 testRequires(c, DaemonIsLinux)
1076 out, _ := dockerCmd(c, "run", "--group-add=audio", "--group-add=staff", "--group-add=777", "busybox", "sh", "-c", "id")
1078 groupsList := "uid=0(root) gid=0(root) groups=10(wheel),29(audio),50(staff),777"
1079 if actual := strings.Trim(out, "\r\n"); actual != groupsList {
1080 c.Fatalf("expected output %s received %s", groupsList, actual)
1084 func (s *DockerSuite) TestRunPrivilegedCanMount(c *check.C) {
1085 // Not applicable for Windows as there is no concept of --privileged
1086 testRequires(c, DaemonIsLinux, NotUserNamespace)
1087 out, _ := dockerCmd(c, "run", "--privileged", "busybox", "sh", "-c", "mount -t tmpfs none /tmp && echo ok")
1089 if actual := strings.Trim(out, "\r\n"); actual != "ok" {
1090 c.Fatalf("expected output ok received %s", actual)
1094 func (s *DockerSuite) TestRunUnprivilegedCannotMount(c *check.C) {
1095 // Not applicable for Windows as there is no concept of unprivileged
1096 testRequires(c, DaemonIsLinux)
1097 out, _, err := dockerCmdWithError("run", "busybox", "sh", "-c", "mount -t tmpfs none /tmp && echo ok")
1102 if actual := strings.Trim(out, "\r\n"); actual == "ok" {
1103 c.Fatalf("expected output not ok received %s", actual)
1107 func (s *DockerSuite) TestRunSysNotWritableInNonPrivilegedContainers(c *check.C) {
1108 // Not applicable for Windows as there is no concept of unprivileged
1109 testRequires(c, DaemonIsLinux, NotArm)
1110 if _, code, err := dockerCmdWithError("run", "busybox", "touch", "/sys/kernel/profiling"); err == nil || code == 0 {
1111 c.Fatal("sys should not be writable in a non privileged container")
1115 func (s *DockerSuite) TestRunSysWritableInPrivilegedContainers(c *check.C) {
1116 // Not applicable for Windows as there is no concept of unprivileged
1117 testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm)
1118 if _, code, err := dockerCmdWithError("run", "--privileged", "busybox", "touch", "/sys/kernel/profiling"); err != nil || code != 0 {
1119 c.Fatalf("sys should be writable in privileged container")
1123 func (s *DockerSuite) TestRunProcNotWritableInNonPrivilegedContainers(c *check.C) {
1124 // Not applicable for Windows as there is no concept of unprivileged
1125 testRequires(c, DaemonIsLinux)
1126 if _, code, err := dockerCmdWithError("run", "busybox", "touch", "/proc/sysrq-trigger"); err == nil || code == 0 {
1127 c.Fatal("proc should not be writable in a non privileged container")
1131 func (s *DockerSuite) TestRunProcWritableInPrivilegedContainers(c *check.C) {
1132 // Not applicable for Windows as there is no concept of --privileged
1133 testRequires(c, DaemonIsLinux, NotUserNamespace)
1134 if _, code := dockerCmd(c, "run", "--privileged", "busybox", "sh", "-c", "touch /proc/sysrq-trigger"); code != 0 {
1135 c.Fatalf("proc should be writable in privileged container")
1139 func (s *DockerSuite) TestRunDeviceNumbers(c *check.C) {
1140 // Not applicable on Windows as /dev/ is a Unix specific concept
1141 // TODO: NotUserNamespace could be removed here if "root" "root" is replaced w user
1142 testRequires(c, DaemonIsLinux, NotUserNamespace)
1143 out, _ := dockerCmd(c, "run", "busybox", "sh", "-c", "ls -l /dev/null")
1144 deviceLineFields := strings.Fields(out)
1145 deviceLineFields[6] = ""
1146 deviceLineFields[7] = ""
1147 deviceLineFields[8] = ""
1148 expected := []string{"crw-rw-rw-", "1", "root", "root", "1,", "3", "", "", "", "/dev/null"}
1150 if !(reflect.DeepEqual(deviceLineFields, expected)) {
1151 c.Fatalf("expected output\ncrw-rw-rw- 1 root root 1, 3 May 24 13:29 /dev/null\n received\n %s\n", out)
1155 func (s *DockerSuite) TestRunThatCharacterDevicesActLikeCharacterDevices(c *check.C) {
1156 // Not applicable on Windows as /dev/ is a Unix specific concept
1157 testRequires(c, DaemonIsLinux)
1158 out, _ := dockerCmd(c, "run", "busybox", "sh", "-c", "dd if=/dev/zero of=/zero bs=1k count=5 2> /dev/null ; du -h /zero")
1159 if actual := strings.Trim(out, "\r\n"); actual[0] == '0' {
1160 c.Fatalf("expected a new file called /zero to be create that is greater than 0 bytes long, but du says: %s", actual)
1164 func (s *DockerSuite) TestRunUnprivilegedWithChroot(c *check.C) {
1165 // Not applicable on Windows as it does not support chroot
1166 testRequires(c, DaemonIsLinux)
1167 dockerCmd(c, "run", "busybox", "chroot", "/", "true")
1170 func (s *DockerSuite) TestRunAddingOptionalDevices(c *check.C) {
1171 // Not applicable on Windows as Windows does not support --device
1172 testRequires(c, DaemonIsLinux, NotUserNamespace)
1173 out, _ := dockerCmd(c, "run", "--device", "/dev/zero:/dev/nulo", "busybox", "sh", "-c", "ls /dev/nulo")
1174 if actual := strings.Trim(out, "\r\n"); actual != "/dev/nulo" {
1175 c.Fatalf("expected output /dev/nulo, received %s", actual)
1179 func (s *DockerSuite) TestRunAddingOptionalDevicesNoSrc(c *check.C) {
1180 // Not applicable on Windows as Windows does not support --device
1181 testRequires(c, DaemonIsLinux, NotUserNamespace)
1182 out, _ := dockerCmd(c, "run", "--device", "/dev/zero:rw", "busybox", "sh", "-c", "ls /dev/zero")
1183 if actual := strings.Trim(out, "\r\n"); actual != "/dev/zero" {
1184 c.Fatalf("expected output /dev/zero, received %s", actual)
1188 func (s *DockerSuite) TestRunAddingOptionalDevicesInvalidMode(c *check.C) {
1189 // Not applicable on Windows as Windows does not support --device
1190 testRequires(c, DaemonIsLinux, NotUserNamespace)
1191 _, _, err := dockerCmdWithError("run", "--device", "/dev/zero:ro", "busybox", "sh", "-c", "ls /dev/zero")
1193 c.Fatalf("run container with device mode ro should fail")
1197 func (s *DockerSuite) TestRunModeHostname(c *check.C) {
1198 // Not applicable on Windows as Windows does not support -h
1199 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
1201 out, _ := dockerCmd(c, "run", "-h=testhostname", "busybox", "cat", "/etc/hostname")
1203 if actual := strings.Trim(out, "\r\n"); actual != "testhostname" {
1204 c.Fatalf("expected 'testhostname', but says: %q", actual)
1207 out, _ = dockerCmd(c, "run", "--net=host", "busybox", "cat", "/etc/hostname")
1209 hostname, err := os.Hostname()
1213 if actual := strings.Trim(out, "\r\n"); actual != hostname {
1214 c.Fatalf("expected %q, but says: %q", hostname, actual)
1218 func (s *DockerSuite) TestRunRootWorkdir(c *check.C) {
1219 out, _ := dockerCmd(c, "run", "--workdir", "/", "busybox", "pwd")
1221 if testEnv.DaemonPlatform() == "windows" {
1222 expected = "C:" + expected
1224 if out != expected {
1225 c.Fatalf("pwd returned %q (expected %s)", s, expected)
1229 func (s *DockerSuite) TestRunAllowBindMountingRoot(c *check.C) {
1230 if testEnv.DaemonPlatform() == "windows" {
1231 // Windows busybox will fail with Permission Denied on items such as pagefile.sys
1232 dockerCmd(c, "run", "-v", `c:\:c:\host`, testEnv.MinimalBaseImage(), "cmd", "-c", "dir", `c:\host`)
1234 dockerCmd(c, "run", "-v", "/:/host", "busybox", "ls", "/host")
1238 func (s *DockerSuite) TestRunDisallowBindMountingRootToRoot(c *check.C) {
1240 targetDir := "/host"
1241 if testEnv.DaemonPlatform() == "windows" {
1243 targetDir = "c:/host" // Forward slash as using busybox
1245 out, _, err := dockerCmdWithError("run", "-v", mount, "busybox", "ls", targetDir)
1251 // Verify that a container gets default DNS when only localhost resolvers exist
1252 func (s *DockerSuite) TestRunDNSDefaultOptions(c *check.C) {
1253 // Not applicable on Windows as this is testing Unix specific functionality
1254 testRequires(c, SameHostDaemon, DaemonIsLinux)
1256 // preserve original resolv.conf for restoring after test
1257 origResolvConf, err := ioutil.ReadFile("/etc/resolv.conf")
1258 if os.IsNotExist(err) {
1259 c.Fatalf("/etc/resolv.conf does not exist")
1261 // defer restored original conf
1263 if err := ioutil.WriteFile("/etc/resolv.conf", origResolvConf, 0644); err != nil {
1268 // test 3 cases: standard IPv4 localhost, commented out localhost, and IPv6 localhost
1269 // 2 are removed from the file at container start, and the 3rd (commented out) one is ignored by
1270 // GetNameservers(), leading to a replacement of nameservers with the default set
1271 tmpResolvConf := []byte("nameserver 127.0.0.1\n#nameserver 127.0.2.1\nnameserver ::1")
1272 if err := ioutil.WriteFile("/etc/resolv.conf", tmpResolvConf, 0644); err != nil {
1276 actual, _ := dockerCmd(c, "run", "busybox", "cat", "/etc/resolv.conf")
1277 // check that the actual defaults are appended to the commented out
1278 // localhost resolver (which should be preserved)
1279 // NOTE: if we ever change the defaults from google dns, this will break
1280 expected := "#nameserver 127.0.2.1\n\nnameserver 8.8.8.8\nnameserver 8.8.4.4\n"
1281 if actual != expected {
1282 c.Fatalf("expected resolv.conf be: %q, but was: %q", expected, actual)
1286 func (s *DockerSuite) TestRunDNSOptions(c *check.C) {
1287 // Not applicable on Windows as Windows does not support --dns*, or
1288 // the Unix-specific functionality of resolv.conf.
1289 testRequires(c, DaemonIsLinux)
1290 result := cli.DockerCmd(c, "run", "--dns=127.0.0.1", "--dns-search=mydomain", "--dns-opt=ndots:9", "busybox", "cat", "/etc/resolv.conf")
1292 // The client will get a warning on stderr when setting DNS to a localhost address; verify this:
1293 if !strings.Contains(result.Stderr(), "Localhost DNS setting") {
1294 c.Fatalf("Expected warning on stderr about localhost resolver, but got %q", result.Stderr())
1297 actual := strings.Replace(strings.Trim(result.Stdout(), "\r\n"), "\n", " ", -1)
1298 if actual != "search mydomain nameserver 127.0.0.1 options ndots:9" {
1299 c.Fatalf("expected 'search mydomain nameserver 127.0.0.1 options ndots:9', but says: %q", actual)
1302 out := cli.DockerCmd(c, "run", "--dns=1.1.1.1", "--dns-search=.", "--dns-opt=ndots:3", "busybox", "cat", "/etc/resolv.conf").Combined()
1304 actual = strings.Replace(strings.Trim(strings.Trim(out, "\r\n"), " "), "\n", " ", -1)
1305 if actual != "nameserver 1.1.1.1 options ndots:3" {
1306 c.Fatalf("expected 'nameserver 1.1.1.1 options ndots:3', but says: %q", actual)
1310 func (s *DockerSuite) TestRunDNSRepeatOptions(c *check.C) {
1311 testRequires(c, DaemonIsLinux)
1312 out := cli.DockerCmd(c, "run", "--dns=1.1.1.1", "--dns=2.2.2.2", "--dns-search=mydomain", "--dns-search=mydomain2", "--dns-opt=ndots:9", "--dns-opt=timeout:3", "busybox", "cat", "/etc/resolv.conf").Stdout()
1314 actual := strings.Replace(strings.Trim(out, "\r\n"), "\n", " ", -1)
1315 if actual != "search mydomain mydomain2 nameserver 1.1.1.1 nameserver 2.2.2.2 options ndots:9 timeout:3" {
1316 c.Fatalf("expected 'search mydomain mydomain2 nameserver 1.1.1.1 nameserver 2.2.2.2 options ndots:9 timeout:3', but says: %q", actual)
1320 func (s *DockerSuite) TestRunDNSOptionsBasedOnHostResolvConf(c *check.C) {
1321 // Not applicable on Windows as testing Unix specific functionality
1322 testRequires(c, SameHostDaemon, DaemonIsLinux)
1324 origResolvConf, err := ioutil.ReadFile("/etc/resolv.conf")
1325 if os.IsNotExist(err) {
1326 c.Fatalf("/etc/resolv.conf does not exist")
1329 hostNameservers := resolvconf.GetNameservers(origResolvConf, types.IP)
1330 hostSearch := resolvconf.GetSearchDomains(origResolvConf)
1333 out, _ = dockerCmd(c, "run", "--dns=127.0.0.1", "busybox", "cat", "/etc/resolv.conf")
1335 if actualNameservers := resolvconf.GetNameservers([]byte(out), types.IP); string(actualNameservers[0]) != "127.0.0.1" {
1336 c.Fatalf("expected '127.0.0.1', but says: %q", string(actualNameservers[0]))
1339 actualSearch := resolvconf.GetSearchDomains([]byte(out))
1340 if len(actualSearch) != len(hostSearch) {
1341 c.Fatalf("expected %q search domain(s), but it has: %q", len(hostSearch), len(actualSearch))
1343 for i := range actualSearch {
1344 if actualSearch[i] != hostSearch[i] {
1345 c.Fatalf("expected %q domain, but says: %q", actualSearch[i], hostSearch[i])
1349 out, _ = dockerCmd(c, "run", "--dns-search=mydomain", "busybox", "cat", "/etc/resolv.conf")
1351 actualNameservers := resolvconf.GetNameservers([]byte(out), types.IP)
1352 if len(actualNameservers) != len(hostNameservers) {
1353 c.Fatalf("expected %q nameserver(s), but it has: %q", len(hostNameservers), len(actualNameservers))
1355 for i := range actualNameservers {
1356 if actualNameservers[i] != hostNameservers[i] {
1357 c.Fatalf("expected %q nameserver, but says: %q", actualNameservers[i], hostNameservers[i])
1361 if actualSearch = resolvconf.GetSearchDomains([]byte(out)); string(actualSearch[0]) != "mydomain" {
1362 c.Fatalf("expected 'mydomain', but says: %q", string(actualSearch[0]))
1366 tmpResolvConf := []byte("search example.com\nnameserver 12.34.56.78\nnameserver 127.0.0.1")
1367 if err := ioutil.WriteFile("/etc/resolv.conf", tmpResolvConf, 0644); err != nil {
1370 // put the old resolvconf back
1372 if err := ioutil.WriteFile("/etc/resolv.conf", origResolvConf, 0644); err != nil {
1377 resolvConf, err := ioutil.ReadFile("/etc/resolv.conf")
1378 if os.IsNotExist(err) {
1379 c.Fatalf("/etc/resolv.conf does not exist")
1382 hostSearch = resolvconf.GetSearchDomains(resolvConf)
1384 out, _ = dockerCmd(c, "run", "busybox", "cat", "/etc/resolv.conf")
1385 if actualNameservers = resolvconf.GetNameservers([]byte(out), types.IP); string(actualNameservers[0]) != "12.34.56.78" || len(actualNameservers) != 1 {
1386 c.Fatalf("expected '12.34.56.78', but has: %v", actualNameservers)
1389 actualSearch = resolvconf.GetSearchDomains([]byte(out))
1390 if len(actualSearch) != len(hostSearch) {
1391 c.Fatalf("expected %q search domain(s), but it has: %q", len(hostSearch), len(actualSearch))
1393 for i := range actualSearch {
1394 if actualSearch[i] != hostSearch[i] {
1395 c.Fatalf("expected %q domain, but says: %q", actualSearch[i], hostSearch[i])
1400 // Test to see if a non-root user can resolve a DNS name. Also
1401 // check if the container resolv.conf file has at least 0644 perm.
1402 func (s *DockerSuite) TestRunNonRootUserResolvName(c *check.C) {
1403 // Not applicable on Windows as Windows does not support --user
1404 testRequires(c, SameHostDaemon, Network, DaemonIsLinux, NotArm)
1406 dockerCmd(c, "run", "--name=testperm", "--user=nobody", "busybox", "nslookup", "apt.dockerproject.org")
1408 cID := getIDByName(c, "testperm")
1410 fmode := (os.FileMode)(0644)
1411 finfo, err := os.Stat(containerStorageFile(cID, "resolv.conf"))
1416 if (finfo.Mode() & fmode) != fmode {
1417 c.Fatalf("Expected container resolv.conf mode to be at least %s, instead got %s", fmode.String(), finfo.Mode().String())
1421 // Test if container resolv.conf gets updated the next time it restarts
1422 // if host /etc/resolv.conf has changed. This only applies if the container
1423 // uses the host's /etc/resolv.conf and does not have any dns options provided.
1424 func (s *DockerSuite) TestRunResolvconfUpdate(c *check.C) {
1425 // Not applicable on Windows as testing unix specific functionality
1426 testRequires(c, SameHostDaemon, DaemonIsLinux)
1427 c.Skip("Unstable test, to be re-activated once #19937 is resolved")
1429 tmpResolvConf := []byte("search pommesfrites.fr\nnameserver 12.34.56.78\n")
1430 tmpLocalhostResolvConf := []byte("nameserver 127.0.0.1")
1432 //take a copy of resolv.conf for restoring after test completes
1433 resolvConfSystem, err := ioutil.ReadFile("/etc/resolv.conf")
1438 // This test case is meant to test monitoring resolv.conf when it is
1439 // a regular file not a bind mounc. So we unmount resolv.conf and replace
1440 // it with a file containing the original settings.
1441 mounted, err := mount.Mounted("/etc/resolv.conf")
1446 icmd.RunCommand("umount", "/etc/resolv.conf").Assert(c, icmd.Success)
1451 if err := ioutil.WriteFile("/etc/resolv.conf", resolvConfSystem, 0644); err != nil {
1456 //1. test that a restarting container gets an updated resolv.conf
1457 dockerCmd(c, "run", "--name=first", "busybox", "true")
1458 containerID1 := getIDByName(c, "first")
1460 // replace resolv.conf with our temporary copy
1461 bytesResolvConf := []byte(tmpResolvConf)
1462 if err := ioutil.WriteFile("/etc/resolv.conf", bytesResolvConf, 0644); err != nil {
1466 // start the container again to pickup changes
1467 dockerCmd(c, "start", "first")
1469 // check for update in container
1470 containerResolv := readContainerFile(c, containerID1, "resolv.conf")
1471 if !bytes.Equal(containerResolv, bytesResolvConf) {
1472 c.Fatalf("Restarted container does not have updated resolv.conf; expected %q, got %q", tmpResolvConf, string(containerResolv))
1475 /* //make a change to resolv.conf (in this case replacing our tmp copy with orig copy)
1476 if err := ioutil.WriteFile("/etc/resolv.conf", resolvConfSystem, 0644); err != nil {
1479 //2. test that a restarting container does not receive resolv.conf updates
1480 // if it modified the container copy of the starting point resolv.conf
1481 dockerCmd(c, "run", "--name=second", "busybox", "sh", "-c", "echo 'search mylittlepony.com' >>/etc/resolv.conf")
1482 containerID2 := getIDByName(c, "second")
1484 //make a change to resolv.conf (in this case replacing our tmp copy with orig copy)
1485 if err := ioutil.WriteFile("/etc/resolv.conf", resolvConfSystem, 0644); err != nil {
1489 // start the container again
1490 dockerCmd(c, "start", "second")
1492 // check for update in container
1493 containerResolv = readContainerFile(c, containerID2, "resolv.conf")
1494 if bytes.Equal(containerResolv, resolvConfSystem) {
1495 c.Fatalf("Container's resolv.conf should not have been updated with host resolv.conf: %q", string(containerResolv))
1498 //3. test that a running container's resolv.conf is not modified while running
1499 out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
1500 runningContainerID := strings.TrimSpace(out)
1502 // replace resolv.conf
1503 if err := ioutil.WriteFile("/etc/resolv.conf", bytesResolvConf, 0644); err != nil {
1507 // check for update in container
1508 containerResolv = readContainerFile(c, runningContainerID, "resolv.conf")
1509 if bytes.Equal(containerResolv, bytesResolvConf) {
1510 c.Fatalf("Running container should not have updated resolv.conf; expected %q, got %q", string(resolvConfSystem), string(containerResolv))
1513 //4. test that a running container's resolv.conf is updated upon restart
1514 // (the above container is still running..)
1515 dockerCmd(c, "restart", runningContainerID)
1517 // check for update in container
1518 containerResolv = readContainerFile(c, runningContainerID, "resolv.conf")
1519 if !bytes.Equal(containerResolv, bytesResolvConf) {
1520 c.Fatalf("Restarted container should have updated resolv.conf; expected %q, got %q", string(bytesResolvConf), string(containerResolv))
1523 //5. test that additions of a localhost resolver are cleaned from
1524 // host resolv.conf before updating container's resolv.conf copies
1526 // replace resolv.conf with a localhost-only nameserver copy
1527 bytesResolvConf = []byte(tmpLocalhostResolvConf)
1528 if err = ioutil.WriteFile("/etc/resolv.conf", bytesResolvConf, 0644); err != nil {
1532 // start the container again to pickup changes
1533 dockerCmd(c, "start", "first")
1535 // our first exited container ID should have been updated, but with default DNS
1536 // after the cleanup of resolv.conf found only a localhost nameserver:
1537 containerResolv = readContainerFile(c, containerID1, "resolv.conf")
1538 expected := "\nnameserver 8.8.8.8\nnameserver 8.8.4.4\n"
1539 if !bytes.Equal(containerResolv, []byte(expected)) {
1540 c.Fatalf("Container does not have cleaned/replaced DNS in resolv.conf; expected %q, got %q", expected, string(containerResolv))
1543 //6. Test that replacing (as opposed to modifying) resolv.conf triggers an update
1544 // of containers' resolv.conf.
1546 // Restore the original resolv.conf
1547 if err := ioutil.WriteFile("/etc/resolv.conf", resolvConfSystem, 0644); err != nil {
1551 // Run the container so it picks up the old settings
1552 dockerCmd(c, "run", "--name=third", "busybox", "true")
1553 containerID3 := getIDByName(c, "third")
1555 // Create a modified resolv.conf.aside and override resolv.conf with it
1556 bytesResolvConf = []byte(tmpResolvConf)
1557 if err := ioutil.WriteFile("/etc/resolv.conf.aside", bytesResolvConf, 0644); err != nil {
1561 err = os.Rename("/etc/resolv.conf.aside", "/etc/resolv.conf")
1566 // start the container again to pickup changes
1567 dockerCmd(c, "start", "third")
1569 // check for update in container
1570 containerResolv = readContainerFile(c, containerID3, "resolv.conf")
1571 if !bytes.Equal(containerResolv, bytesResolvConf) {
1572 c.Fatalf("Stopped container does not have updated resolv.conf; expected\n%q\n got\n%q", tmpResolvConf, string(containerResolv))
1575 //cleanup, restore original resolv.conf happens in defer func()
1578 func (s *DockerSuite) TestRunAddHost(c *check.C) {
1579 // Not applicable on Windows as it does not support --add-host
1580 testRequires(c, DaemonIsLinux)
1581 out, _ := dockerCmd(c, "run", "--add-host=extra:86.75.30.9", "busybox", "grep", "extra", "/etc/hosts")
1583 actual := strings.Trim(out, "\r\n")
1584 if actual != "86.75.30.9\textra" {
1585 c.Fatalf("expected '86.75.30.9\textra', but says: %q", actual)
1589 // Regression test for #6983
1590 func (s *DockerSuite) TestRunAttachStdErrOnlyTTYMode(c *check.C) {
1591 _, exitCode := dockerCmd(c, "run", "-t", "-a", "stderr", "busybox", "true")
1593 c.Fatalf("Container should have exited with error code 0")
1597 // Regression test for #6983
1598 func (s *DockerSuite) TestRunAttachStdOutOnlyTTYMode(c *check.C) {
1599 _, exitCode := dockerCmd(c, "run", "-t", "-a", "stdout", "busybox", "true")
1601 c.Fatalf("Container should have exited with error code 0")
1605 // Regression test for #6983
1606 func (s *DockerSuite) TestRunAttachStdOutAndErrTTYMode(c *check.C) {
1607 _, exitCode := dockerCmd(c, "run", "-t", "-a", "stdout", "-a", "stderr", "busybox", "true")
1609 c.Fatalf("Container should have exited with error code 0")
1613 // Test for #10388 - this will run the same test as TestRunAttachStdOutAndErrTTYMode
1614 // but using --attach instead of -a to make sure we read the flag correctly
1615 func (s *DockerSuite) TestRunAttachWithDetach(c *check.C) {
1616 icmd.RunCommand(dockerBinary, "run", "-d", "--attach", "stdout", "busybox", "true").Assert(c, icmd.Expected{
1618 Error: "exit status 1",
1619 Err: "Conflicting options: -a and -d",
1623 func (s *DockerSuite) TestRunState(c *check.C) {
1624 // TODO Windows: This needs some rework as Windows busybox does not support top
1625 testRequires(c, DaemonIsLinux)
1626 out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
1628 id := strings.TrimSpace(out)
1629 state := inspectField(c, id, "State.Running")
1630 if state != "true" {
1631 c.Fatal("Container state is 'not running'")
1633 pid1 := inspectField(c, id, "State.Pid")
1635 c.Fatal("Container state Pid 0")
1638 dockerCmd(c, "stop", id)
1639 state = inspectField(c, id, "State.Running")
1640 if state != "false" {
1641 c.Fatal("Container state is 'running'")
1643 pid2 := inspectField(c, id, "State.Pid")
1645 c.Fatalf("Container state Pid %s, but expected %s", pid2, pid1)
1648 dockerCmd(c, "start", id)
1649 state = inspectField(c, id, "State.Running")
1650 if state != "true" {
1651 c.Fatal("Container state is 'not running'")
1653 pid3 := inspectField(c, id, "State.Pid")
1655 c.Fatalf("Container state Pid %s, but expected %s", pid2, pid1)
1660 func (s *DockerSuite) TestRunCopyVolumeUIDGID(c *check.C) {
1661 // Not applicable on Windows as it does not support uid or gid in this way
1662 testRequires(c, DaemonIsLinux)
1663 name := "testrunvolumesuidgid"
1664 buildImageSuccessfully(c, name, build.WithDockerfile(`FROM busybox
1665 RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
1666 RUN echo 'dockerio:x:1001:' >> /etc/group
1667 RUN mkdir -p /hello && touch /hello/test && chown dockerio.dockerio /hello`))
1669 // Test that the uid and gid is copied from the image to the volume
1670 out, _ := dockerCmd(c, "run", "--rm", "-v", "/hello", name, "sh", "-c", "ls -l / | grep hello | awk '{print $3\":\"$4}'")
1671 out = strings.TrimSpace(out)
1672 if out != "dockerio:dockerio" {
1673 c.Fatalf("Wrong /hello ownership: %s, expected dockerio:dockerio", out)
1678 func (s *DockerSuite) TestRunCopyVolumeContent(c *check.C) {
1679 // TODO Windows, post RS1. Windows does not yet support volume functionality
1680 // that copies from the image to the volume.
1681 testRequires(c, DaemonIsLinux)
1682 name := "testruncopyvolumecontent"
1683 buildImageSuccessfully(c, name, build.WithDockerfile(`FROM busybox
1684 RUN mkdir -p /hello/local && echo hello > /hello/local/world`))
1686 // Test that the content is copied from the image to the volume
1687 out, _ := dockerCmd(c, "run", "--rm", "-v", "/hello", name, "find", "/hello")
1688 if !(strings.Contains(out, "/hello/local/world") && strings.Contains(out, "/hello/local")) {
1689 c.Fatal("Container failed to transfer content to volume")
1693 func (s *DockerSuite) TestRunCleanupCmdOnEntrypoint(c *check.C) {
1694 name := "testrunmdcleanuponentrypoint"
1695 buildImageSuccessfully(c, name, build.WithDockerfile(`FROM busybox
1697 CMD ["testingpoint"]`))
1699 out, exit := dockerCmd(c, "run", "--entrypoint", "whoami", name)
1701 c.Fatalf("expected exit code 0 received %d, out: %q", exit, out)
1703 out = strings.TrimSpace(out)
1705 if testEnv.DaemonPlatform() == "windows" {
1706 if strings.Contains(testEnv.MinimalBaseImage(), "windowsservercore") {
1707 expected = `user manager\containeradministrator`
1709 expected = `ContainerAdministrator` // nanoserver
1712 if out != expected {
1713 c.Fatalf("Expected output %s, got %q. %s", expected, out, testEnv.MinimalBaseImage())
1717 // TestRunWorkdirExistsAndIsFile checks that if 'docker run -w' with existing file can be detected
1718 func (s *DockerSuite) TestRunWorkdirExistsAndIsFile(c *check.C) {
1719 existingFile := "/bin/cat"
1720 expected := "not a directory"
1721 if testEnv.DaemonPlatform() == "windows" {
1722 existingFile = `\windows\system32\ntdll.dll`
1723 expected = `The directory name is invalid.`
1726 out, exitCode, err := dockerCmdWithError("run", "-w", existingFile, "busybox")
1727 if !(err != nil && exitCode == 125 && strings.Contains(out, expected)) {
1728 c.Fatalf("Existing binary as a directory should error out with exitCode 125; we got: %s, exitCode: %d", out, exitCode)
1732 func (s *DockerSuite) TestRunExitOnStdinClose(c *check.C) {
1733 name := "testrunexitonstdinclose"
1737 if testEnv.DaemonPlatform() == "windows" {
1740 runCmd := exec.Command(dockerBinary, "run", "--name", name, "-i", "busybox", meow)
1742 stdin, err := runCmd.StdinPipe()
1746 stdout, err := runCmd.StdoutPipe()
1751 if err := runCmd.Start(); err != nil {
1754 if _, err := stdin.Write([]byte("hello\n")); err != nil {
1758 r := bufio.NewReader(stdout)
1759 line, err := r.ReadString('\n')
1763 line = strings.TrimSpace(line)
1764 if line != "hello" {
1765 c.Fatalf("Output should be 'hello', got '%q'", line)
1767 if err := stdin.Close(); err != nil {
1770 finish := make(chan error)
1772 finish <- runCmd.Wait()
1776 case err := <-finish:
1777 c.Assert(err, check.IsNil)
1778 case <-time.After(time.Duration(delay) * time.Second):
1779 c.Fatal("docker run failed to exit on stdin close")
1781 state := inspectField(c, name, "State.Running")
1783 if state != "false" {
1784 c.Fatal("Container must be stopped after stdin closing")
1788 // Test run -i --restart xxx doesn't hang
1789 func (s *DockerSuite) TestRunInteractiveWithRestartPolicy(c *check.C) {
1790 name := "test-inter-restart"
1792 result := icmd.StartCmd(icmd.Cmd{
1793 Command: []string{dockerBinary, "run", "-i", "--name", name, "--restart=always", "busybox", "sh"},
1794 Stdin: bytes.NewBufferString("exit 11"),
1796 c.Assert(result.Error, checker.IsNil)
1798 dockerCmdWithResult("stop", name).Assert(c, icmd.Success)
1801 result = icmd.WaitOnCmd(60*time.Second, result)
1802 c.Assert(result, icmd.Matches, icmd.Expected{ExitCode: 11})
1806 func (s *DockerSuite) TestRunWriteSpecialFilesAndNotCommit(c *check.C) {
1807 // Cannot run on Windows as this files are not present in Windows
1808 testRequires(c, DaemonIsLinux)
1810 testRunWriteSpecialFilesAndNotCommit(c, "writehosts", "/etc/hosts")
1811 testRunWriteSpecialFilesAndNotCommit(c, "writehostname", "/etc/hostname")
1812 testRunWriteSpecialFilesAndNotCommit(c, "writeresolv", "/etc/resolv.conf")
1815 func testRunWriteSpecialFilesAndNotCommit(c *check.C, name, path string) {
1816 command := fmt.Sprintf("echo test2267 >> %s && cat %s", path, path)
1817 out, _ := dockerCmd(c, "run", "--name", name, "busybox", "sh", "-c", command)
1818 if !strings.Contains(out, "test2267") {
1819 c.Fatalf("%s should contain 'test2267'", path)
1822 out, _ = dockerCmd(c, "diff", name)
1823 if len(strings.Trim(out, "\r\n")) != 0 && !eqToBaseDiff(out, c) {
1824 c.Fatal("diff should be empty")
1828 func eqToBaseDiff(out string, c *check.C) bool {
1829 name := "eqToBaseDiff" + stringutils.GenerateRandomAlphaOnlyString(32)
1830 dockerCmd(c, "run", "--name", name, "busybox", "echo", "hello")
1831 cID := getIDByName(c, name)
1832 baseDiff, _ := dockerCmd(c, "diff", cID)
1833 baseArr := strings.Split(baseDiff, "\n")
1834 sort.Strings(baseArr)
1835 outArr := strings.Split(out, "\n")
1836 sort.Strings(outArr)
1837 return sliceEq(baseArr, outArr)
1840 func sliceEq(a, b []string) bool {
1841 if len(a) != len(b) {
1854 func (s *DockerSuite) TestRunWithBadDevice(c *check.C) {
1855 // Cannot run on Windows as Windows does not support --device
1856 testRequires(c, DaemonIsLinux)
1858 out, _, err := dockerCmdWithError("run", "--name", name, "--device", "/etc", "busybox", "true")
1861 c.Fatal("Run should fail with bad device")
1863 expected := `"/etc": not a device node`
1864 if !strings.Contains(out, expected) {
1865 c.Fatalf("Output should contain %q, actual out: %q", expected, out)
1869 func (s *DockerSuite) TestRunEntrypoint(c *check.C) {
1870 name := "entrypoint"
1872 out, _ := dockerCmd(c, "run", "--name", name, "--entrypoint", "echo", "busybox", "-n", "foobar")
1873 expected := "foobar"
1875 if out != expected {
1876 c.Fatalf("Output should be %q, actual out: %q", expected, out)
1880 func (s *DockerSuite) TestRunBindMounts(c *check.C) {
1881 testRequires(c, SameHostDaemon)
1882 if testEnv.DaemonPlatform() == "linux" {
1883 testRequires(c, DaemonIsLinux, NotUserNamespace)
1886 prefix, _ := getPrefixAndSlashFromDaemonPlatform()
1888 tmpDir, err := ioutil.TempDir("", "docker-test-container")
1893 defer os.RemoveAll(tmpDir)
1894 writeFile(path.Join(tmpDir, "touch-me"), "", c)
1896 // Test reading from a read-only bind mount
1897 out, _ := dockerCmd(c, "run", "-v", fmt.Sprintf("%s:%s/tmp:ro", tmpDir, prefix), "busybox", "ls", prefix+"/tmp")
1898 if !strings.Contains(out, "touch-me") {
1899 c.Fatal("Container failed to read from bind mount")
1902 // test writing to bind mount
1903 if testEnv.DaemonPlatform() == "windows" {
1904 dockerCmd(c, "run", "-v", fmt.Sprintf(`%s:c:\tmp:rw`, tmpDir), "busybox", "touch", "c:/tmp/holla")
1906 dockerCmd(c, "run", "-v", fmt.Sprintf("%s:/tmp:rw", tmpDir), "busybox", "touch", "/tmp/holla")
1909 readFile(path.Join(tmpDir, "holla"), c) // Will fail if the file doesn't exist
1911 // test mounting to an illegal destination directory
1912 _, _, err = dockerCmdWithError("run", "-v", fmt.Sprintf("%s:.", tmpDir), "busybox", "ls", ".")
1914 c.Fatal("Container bind mounted illegal directory")
1917 // Windows does not (and likely never will) support mounting a single file
1918 if testEnv.DaemonPlatform() != "windows" {
1919 // test mount a file
1920 dockerCmd(c, "run", "-v", fmt.Sprintf("%s/holla:/tmp/holla:rw", tmpDir), "busybox", "sh", "-c", "echo -n 'yotta' > /tmp/holla")
1921 content := readFile(path.Join(tmpDir, "holla"), c) // Will fail if the file doesn't exist
1923 if content != expected {
1924 c.Fatalf("Output should be %q, actual out: %q", expected, content)
1929 // Ensure that CIDFile gets deleted if it's empty
1930 // Perform this test by making `docker run` fail
1931 func (s *DockerSuite) TestRunCidFileCleanupIfEmpty(c *check.C) {
1932 // Skip on Windows. Base image on Windows has a CMD set in the image.
1933 testRequires(c, DaemonIsLinux)
1935 tmpDir, err := ioutil.TempDir("", "TestRunCidFile")
1939 defer os.RemoveAll(tmpDir)
1940 tmpCidFile := path.Join(tmpDir, "cid")
1943 if testEnv.DaemonPlatform() == "windows" {
1944 // Windows can't support an emptyfs image. Just use the regular Windows image
1945 image = testEnv.MinimalBaseImage()
1947 out, _, err := dockerCmdWithError("run", "--cidfile", tmpCidFile, image)
1949 c.Fatalf("Run without command must fail. out=%s", out)
1950 } else if !strings.Contains(out, "No command specified") {
1951 c.Fatalf("Run without command failed with wrong output. out=%s\nerr=%v", out, err)
1954 if _, err := os.Stat(tmpCidFile); err == nil {
1955 c.Fatalf("empty CIDFile %q should've been deleted", tmpCidFile)
1959 // #2098 - Docker cidFiles only contain short version of the containerId
1960 //sudo docker run --cidfile /tmp/docker_tesc.cid ubuntu echo "test"
1961 // TestRunCidFile tests that run --cidfile returns the longid
1962 func (s *DockerSuite) TestRunCidFileCheckIDLength(c *check.C) {
1963 tmpDir, err := ioutil.TempDir("", "TestRunCidFile")
1967 tmpCidFile := path.Join(tmpDir, "cid")
1968 defer os.RemoveAll(tmpDir)
1970 out, _ := dockerCmd(c, "run", "-d", "--cidfile", tmpCidFile, "busybox", "true")
1972 id := strings.TrimSpace(out)
1973 buffer, err := ioutil.ReadFile(tmpCidFile)
1977 cid := string(buffer)
1979 c.Fatalf("--cidfile should be a long id, not %q", id)
1982 c.Fatalf("cid must be equal to %s, got %s", id, cid)
1986 func (s *DockerSuite) TestRunSetMacAddress(c *check.C) {
1987 mac := "12:34:56:78:9a:bc"
1989 if testEnv.DaemonPlatform() == "windows" {
1990 out, _ = dockerCmd(c, "run", "-i", "--rm", fmt.Sprintf("--mac-address=%s", mac), "busybox", "sh", "-c", "ipconfig /all | grep 'Physical Address' | awk '{print $12}'")
1991 mac = strings.Replace(strings.ToUpper(mac), ":", "-", -1) // To Windows-style MACs
1993 out, _ = dockerCmd(c, "run", "-i", "--rm", fmt.Sprintf("--mac-address=%s", mac), "busybox", "/bin/sh", "-c", "ip link show eth0 | tail -1 | awk '{print $2}'")
1996 actualMac := strings.TrimSpace(out)
1997 if actualMac != mac {
1998 c.Fatalf("Set MAC address with --mac-address failed. The container has an incorrect MAC address: %q, expected: %q", actualMac, mac)
2002 func (s *DockerSuite) TestRunInspectMacAddress(c *check.C) {
2003 // TODO Windows. Network settings are not propagated back to inspect.
2004 testRequires(c, DaemonIsLinux)
2005 mac := "12:34:56:78:9a:bc"
2006 out, _ := dockerCmd(c, "run", "-d", "--mac-address="+mac, "busybox", "top")
2008 id := strings.TrimSpace(out)
2009 inspectedMac := inspectField(c, id, "NetworkSettings.Networks.bridge.MacAddress")
2010 if inspectedMac != mac {
2011 c.Fatalf("docker inspect outputs wrong MAC address: %q, should be: %q", inspectedMac, mac)
2015 // test docker run use an invalid mac address
2016 func (s *DockerSuite) TestRunWithInvalidMacAddress(c *check.C) {
2017 out, _, err := dockerCmdWithError("run", "--mac-address", "92:d0:c6:0a:29", "busybox")
2018 //use an invalid mac address should with an error out
2019 if err == nil || !strings.Contains(out, "is not a valid mac address") {
2020 c.Fatalf("run with an invalid --mac-address should with error out")
2024 func (s *DockerSuite) TestRunDeallocatePortOnMissingIptablesRule(c *check.C) {
2025 // TODO Windows. Network settings are not propagated back to inspect.
2026 testRequires(c, SameHostDaemon, DaemonIsLinux)
2028 out := cli.DockerCmd(c, "run", "-d", "-p", "23:23", "busybox", "top").Combined()
2030 id := strings.TrimSpace(out)
2031 ip := inspectField(c, id, "NetworkSettings.Networks.bridge.IPAddress")
2032 icmd.RunCommand("iptables", "-D", "DOCKER", "-d", fmt.Sprintf("%s/32", ip),
2033 "!", "-i", "docker0", "-o", "docker0", "-p", "tcp", "-m", "tcp", "--dport", "23", "-j", "ACCEPT").Assert(c, icmd.Success)
2035 cli.DockerCmd(c, "rm", "-fv", id)
2037 cli.DockerCmd(c, "run", "-d", "-p", "23:23", "busybox", "top")
2040 func (s *DockerSuite) TestRunPortInUse(c *check.C) {
2041 // TODO Windows. The duplicate NAT message returned by Windows will be
2042 // changing as is currently completely undecipherable. Does need modifying
2043 // to run sh rather than top though as top isn't in Windows busybox.
2044 testRequires(c, SameHostDaemon, DaemonIsLinux)
2047 dockerCmd(c, "run", "-d", "-p", port+":80", "busybox", "top")
2049 out, _, err := dockerCmdWithError("run", "-d", "-p", port+":80", "busybox", "top")
2051 c.Fatalf("Binding on used port must fail")
2053 if !strings.Contains(out, "port is already allocated") {
2054 c.Fatalf("Out must be about \"port is already allocated\", got %s", out)
2058 // https://github.com/docker/docker/issues/12148
2059 func (s *DockerSuite) TestRunAllocatePortInReservedRange(c *check.C) {
2060 // TODO Windows. -P is not yet supported
2061 testRequires(c, DaemonIsLinux)
2062 // allocate a dynamic port to get the most recent
2063 out, _ := dockerCmd(c, "run", "-d", "-P", "-p", "80", "busybox", "top")
2065 id := strings.TrimSpace(out)
2066 out, _ = dockerCmd(c, "port", id, "80")
2068 strPort := strings.Split(strings.TrimSpace(out), ":")[1]
2069 port, err := strconv.ParseInt(strPort, 10, 64)
2071 c.Fatalf("invalid port, got: %s, error: %s", strPort, err)
2074 // allocate a static port and a dynamic port together, with static port
2075 // takes the next recent port in dynamic port range.
2076 dockerCmd(c, "run", "-d", "-P", "-p", "80", "-p", fmt.Sprintf("%d:8080", port+1), "busybox", "top")
2079 // Regression test for #7792
2080 func (s *DockerSuite) TestRunMountOrdering(c *check.C) {
2081 // TODO Windows: Post RS1. Windows does not support nested mounts.
2082 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
2083 prefix, _ := getPrefixAndSlashFromDaemonPlatform()
2085 tmpDir, err := ioutil.TempDir("", "docker_nested_mount_test")
2089 defer os.RemoveAll(tmpDir)
2091 tmpDir2, err := ioutil.TempDir("", "docker_nested_mount_test2")
2095 defer os.RemoveAll(tmpDir2)
2097 // Create a temporary tmpfs mounc.
2098 fooDir := filepath.Join(tmpDir, "foo")
2099 if err := os.MkdirAll(filepath.Join(tmpDir, "foo"), 0755); err != nil {
2100 c.Fatalf("failed to mkdir at %s - %s", fooDir, err)
2103 if err := ioutil.WriteFile(fmt.Sprintf("%s/touch-me", fooDir), []byte{}, 0644); err != nil {
2107 if err := ioutil.WriteFile(fmt.Sprintf("%s/touch-me", tmpDir), []byte{}, 0644); err != nil {
2111 if err := ioutil.WriteFile(fmt.Sprintf("%s/touch-me", tmpDir2), []byte{}, 0644); err != nil {
2116 "-v", fmt.Sprintf("%s:"+prefix+"/tmp", tmpDir),
2117 "-v", fmt.Sprintf("%s:"+prefix+"/tmp/foo", fooDir),
2118 "-v", fmt.Sprintf("%s:"+prefix+"/tmp/tmp2", tmpDir2),
2119 "-v", fmt.Sprintf("%s:"+prefix+"/tmp/tmp2/foo", fooDir),
2120 "busybox:latest", "sh", "-c",
2121 "ls "+prefix+"/tmp/touch-me && ls "+prefix+"/tmp/foo/touch-me && ls "+prefix+"/tmp/tmp2/touch-me && ls "+prefix+"/tmp/tmp2/foo/touch-me")
2124 // Regression test for https://github.com/docker/docker/issues/8259
2125 func (s *DockerSuite) TestRunReuseBindVolumeThatIsSymlink(c *check.C) {
2126 // Not applicable on Windows as Windows does not support volumes
2127 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
2128 prefix, _ := getPrefixAndSlashFromDaemonPlatform()
2130 tmpDir, err := ioutil.TempDir(os.TempDir(), "testlink")
2134 defer os.RemoveAll(tmpDir)
2136 linkPath := os.TempDir() + "/testlink2"
2137 if err := os.Symlink(tmpDir, linkPath); err != nil {
2140 defer os.RemoveAll(linkPath)
2142 // Create first container
2143 dockerCmd(c, "run", "-v", fmt.Sprintf("%s:"+prefix+"/tmp/test", linkPath), "busybox", "ls", prefix+"/tmp/test")
2145 // Create second container with same symlinked path
2146 // This will fail if the referenced issue is hit with a "Volume exists" error
2147 dockerCmd(c, "run", "-v", fmt.Sprintf("%s:"+prefix+"/tmp/test", linkPath), "busybox", "ls", prefix+"/tmp/test")
2150 //GH#10604: Test an "/etc" volume doesn't overlay special bind mounts in container
2151 func (s *DockerSuite) TestRunCreateVolumeEtc(c *check.C) {
2152 // While Windows supports volumes, it does not support --add-host hence
2153 // this test is not applicable on Windows.
2154 testRequires(c, DaemonIsLinux)
2155 out, _ := dockerCmd(c, "run", "--dns=127.0.0.1", "-v", "/etc", "busybox", "cat", "/etc/resolv.conf")
2156 if !strings.Contains(out, "nameserver 127.0.0.1") {
2157 c.Fatal("/etc volume mount hides /etc/resolv.conf")
2160 out, _ = dockerCmd(c, "run", "-h=test123", "-v", "/etc", "busybox", "cat", "/etc/hostname")
2161 if !strings.Contains(out, "test123") {
2162 c.Fatal("/etc volume mount hides /etc/hostname")
2165 out, _ = dockerCmd(c, "run", "--add-host=test:192.168.0.1", "-v", "/etc", "busybox", "cat", "/etc/hosts")
2166 out = strings.Replace(out, "\n", " ", -1)
2167 if !strings.Contains(out, "192.168.0.1\ttest") || !strings.Contains(out, "127.0.0.1\tlocalhost") {
2168 c.Fatal("/etc volume mount hides /etc/hosts")
2172 func (s *DockerSuite) TestVolumesNoCopyData(c *check.C) {
2173 // TODO Windows (Post RS1). Windows does not support volumes which
2174 // are pre-populated such as is built in the dockerfile used in this test.
2175 testRequires(c, DaemonIsLinux)
2176 prefix, slash := getPrefixAndSlashFromDaemonPlatform()
2177 buildImageSuccessfully(c, "dataimage", build.WithDockerfile(`FROM busybox
2178 RUN ["mkdir", "-p", "/foo"]
2179 RUN ["touch", "/foo/bar"]`))
2180 dockerCmd(c, "run", "--name", "test", "-v", prefix+slash+"foo", "busybox")
2182 if out, _, err := dockerCmdWithError("run", "--volumes-from", "test", "dataimage", "ls", "-lh", "/foo/bar"); err == nil || !strings.Contains(out, "No such file or directory") {
2183 c.Fatalf("Data was copied on volumes-from but shouldn't be:\n%q", out)
2186 tmpDir := testutil.RandomTmpDirPath("docker_test_bind_mount_copy_data", testEnv.DaemonPlatform())
2187 if out, _, err := dockerCmdWithError("run", "-v", tmpDir+":/foo", "dataimage", "ls", "-lh", "/foo/bar"); err == nil || !strings.Contains(out, "No such file or directory") {
2188 c.Fatalf("Data was copied on bind-mount but shouldn't be:\n%q", out)
2192 func (s *DockerSuite) TestRunNoOutputFromPullInStdout(c *check.C) {
2193 // just run with unknown image
2194 cmd := exec.Command(dockerBinary, "run", "asdfsg")
2195 stdout := bytes.NewBuffer(nil)
2197 if err := cmd.Run(); err == nil {
2198 c.Fatal("Run with unknown image should fail")
2200 if stdout.Len() != 0 {
2201 c.Fatalf("Stdout contains output from pull: %s", stdout)
2205 func (s *DockerSuite) TestRunVolumesCleanPaths(c *check.C) {
2206 testRequires(c, SameHostDaemon)
2207 prefix, slash := getPrefixAndSlashFromDaemonPlatform()
2208 buildImageSuccessfully(c, "run_volumes_clean_paths", build.WithDockerfile(`FROM busybox
2209 VOLUME `+prefix+`/foo/`))
2210 dockerCmd(c, "run", "-v", prefix+"/foo", "-v", prefix+"/bar/", "--name", "dark_helmet", "run_volumes_clean_paths")
2212 out, err := inspectMountSourceField("dark_helmet", prefix+slash+"foo"+slash)
2213 if err != errMountNotFound {
2214 c.Fatalf("Found unexpected volume entry for '%s/foo/' in volumes\n%q", prefix, out)
2217 out, err = inspectMountSourceField("dark_helmet", prefix+slash+`foo`)
2218 c.Assert(err, check.IsNil)
2219 if !strings.Contains(strings.ToLower(out), strings.ToLower(testEnv.VolumesConfigPath())) {
2220 c.Fatalf("Volume was not defined for %s/foo\n%q", prefix, out)
2223 out, err = inspectMountSourceField("dark_helmet", prefix+slash+"bar"+slash)
2224 if err != errMountNotFound {
2225 c.Fatalf("Found unexpected volume entry for '%s/bar/' in volumes\n%q", prefix, out)
2228 out, err = inspectMountSourceField("dark_helmet", prefix+slash+"bar")
2229 c.Assert(err, check.IsNil)
2230 if !strings.Contains(strings.ToLower(out), strings.ToLower(testEnv.VolumesConfigPath())) {
2231 c.Fatalf("Volume was not defined for %s/bar\n%q", prefix, out)
2235 // Regression test for #3631
2236 func (s *DockerSuite) TestRunSlowStdoutConsumer(c *check.C) {
2237 // TODO Windows: This should be able to run on Windows if can find an
2238 // alternate to /dev/zero and /dev/stdout.
2239 testRequires(c, DaemonIsLinux)
2240 cont := exec.Command(dockerBinary, "run", "--rm", "busybox", "/bin/sh", "-c", "dd if=/dev/zero of=/dev/stdout bs=1024 count=2000 | catv")
2242 stdout, err := cont.StdoutPipe()
2247 if err := cont.Start(); err != nil {
2250 n, err := testutil.ConsumeWithSpeed(stdout, 10000, 5*time.Millisecond, nil)
2255 expected := 2 * 1024 * 2000
2257 c.Fatalf("Expected %d, got %d", expected, n)
2261 func (s *DockerSuite) TestRunAllowPortRangeThroughExpose(c *check.C) {
2262 // TODO Windows: -P is not currently supported. Also network
2263 // settings are not propagated back.
2264 testRequires(c, DaemonIsLinux)
2265 out, _ := dockerCmd(c, "run", "-d", "--expose", "3000-3003", "-P", "busybox", "top")
2267 id := strings.TrimSpace(out)
2268 portstr := inspectFieldJSON(c, id, "NetworkSettings.Ports")
2269 var ports nat.PortMap
2270 if err := json.Unmarshal([]byte(portstr), &ports); err != nil {
2273 for port, binding := range ports {
2274 portnum, _ := strconv.Atoi(strings.Split(string(port), "/")[0])
2275 if portnum < 3000 || portnum > 3003 {
2276 c.Fatalf("Port %d is out of range ", portnum)
2278 if binding == nil || len(binding) != 1 || len(binding[0].HostPort) == 0 {
2279 c.Fatalf("Port is not mapped for the port %s", port)
2284 func (s *DockerSuite) TestRunExposePort(c *check.C) {
2285 out, _, err := dockerCmdWithError("run", "--expose", "80000", "busybox")
2286 c.Assert(err, checker.NotNil, check.Commentf("--expose with an invalid port should error out"))
2287 c.Assert(out, checker.Contains, "invalid range format for --expose")
2290 func (s *DockerSuite) TestRunModeIpcHost(c *check.C) {
2291 // Not applicable on Windows as uses Unix-specific capabilities
2292 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
2294 hostIpc, err := os.Readlink("/proc/1/ns/ipc")
2299 out, _ := dockerCmd(c, "run", "--ipc=host", "busybox", "readlink", "/proc/self/ns/ipc")
2300 out = strings.Trim(out, "\n")
2302 c.Fatalf("IPC different with --ipc=host %s != %s\n", hostIpc, out)
2305 out, _ = dockerCmd(c, "run", "busybox", "readlink", "/proc/self/ns/ipc")
2306 out = strings.Trim(out, "\n")
2308 c.Fatalf("IPC should be different without --ipc=host %s == %s\n", hostIpc, out)
2312 func (s *DockerSuite) TestRunModeIpcContainer(c *check.C) {
2313 // Not applicable on Windows as uses Unix-specific capabilities
2314 testRequires(c, SameHostDaemon, DaemonIsLinux)
2316 out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", "echo -n test > /dev/shm/test && touch /dev/mqueue/toto && top")
2318 id := strings.TrimSpace(out)
2319 state := inspectField(c, id, "State.Running")
2320 if state != "true" {
2321 c.Fatal("Container state is 'not running'")
2323 pid1 := inspectField(c, id, "State.Pid")
2325 parentContainerIpc, err := os.Readlink(fmt.Sprintf("/proc/%s/ns/ipc", pid1))
2330 out, _ = dockerCmd(c, "run", fmt.Sprintf("--ipc=container:%s", id), "busybox", "readlink", "/proc/self/ns/ipc")
2331 out = strings.Trim(out, "\n")
2332 if parentContainerIpc != out {
2333 c.Fatalf("IPC different with --ipc=container:%s %s != %s\n", id, parentContainerIpc, out)
2336 catOutput, _ := dockerCmd(c, "run", fmt.Sprintf("--ipc=container:%s", id), "busybox", "cat", "/dev/shm/test")
2337 if catOutput != "test" {
2338 c.Fatalf("Output of /dev/shm/test expected test but found: %s", catOutput)
2341 // check that /dev/mqueue is actually of mqueue type
2342 grepOutput, _ := dockerCmd(c, "run", fmt.Sprintf("--ipc=container:%s", id), "busybox", "grep", "/dev/mqueue", "/proc/mounts")
2343 if !strings.HasPrefix(grepOutput, "mqueue /dev/mqueue mqueue rw") {
2344 c.Fatalf("Output of 'grep /proc/mounts' expected 'mqueue /dev/mqueue mqueue rw' but found: %s", grepOutput)
2347 lsOutput, _ := dockerCmd(c, "run", fmt.Sprintf("--ipc=container:%s", id), "busybox", "ls", "/dev/mqueue")
2348 lsOutput = strings.Trim(lsOutput, "\n")
2349 if lsOutput != "toto" {
2350 c.Fatalf("Output of 'ls /dev/mqueue' expected 'toto' but found: %s", lsOutput)
2354 func (s *DockerSuite) TestRunModeIpcContainerNotExists(c *check.C) {
2355 // Not applicable on Windows as uses Unix-specific capabilities
2356 testRequires(c, DaemonIsLinux)
2357 out, _, err := dockerCmdWithError("run", "-d", "--ipc", "container:abcd1234", "busybox", "top")
2358 if !strings.Contains(out, "abcd1234") || err == nil {
2359 c.Fatalf("run IPC from a non exists container should with correct error out")
2363 func (s *DockerSuite) TestRunModeIpcContainerNotRunning(c *check.C) {
2364 // Not applicable on Windows as uses Unix-specific capabilities
2365 testRequires(c, SameHostDaemon, DaemonIsLinux)
2367 out, _ := dockerCmd(c, "create", "busybox")
2369 id := strings.TrimSpace(out)
2370 out, _, err := dockerCmdWithError("run", fmt.Sprintf("--ipc=container:%s", id), "busybox")
2372 c.Fatalf("Run container with ipc mode container should fail with non running container: %s\n%s", out, err)
2376 func (s *DockerSuite) TestRunModePIDContainer(c *check.C) {
2377 // Not applicable on Windows as uses Unix-specific capabilities
2378 testRequires(c, SameHostDaemon, DaemonIsLinux)
2380 out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", "top")
2382 id := strings.TrimSpace(out)
2383 state := inspectField(c, id, "State.Running")
2384 if state != "true" {
2385 c.Fatal("Container state is 'not running'")
2387 pid1 := inspectField(c, id, "State.Pid")
2389 parentContainerPid, err := os.Readlink(fmt.Sprintf("/proc/%s/ns/pid", pid1))
2394 out, _ = dockerCmd(c, "run", fmt.Sprintf("--pid=container:%s", id), "busybox", "readlink", "/proc/self/ns/pid")
2395 out = strings.Trim(out, "\n")
2396 if parentContainerPid != out {
2397 c.Fatalf("PID different with --pid=container:%s %s != %s\n", id, parentContainerPid, out)
2401 func (s *DockerSuite) TestRunModePIDContainerNotExists(c *check.C) {
2402 // Not applicable on Windows as uses Unix-specific capabilities
2403 testRequires(c, DaemonIsLinux)
2404 out, _, err := dockerCmdWithError("run", "-d", "--pid", "container:abcd1234", "busybox", "top")
2405 if !strings.Contains(out, "abcd1234") || err == nil {
2406 c.Fatalf("run PID from a non exists container should with correct error out")
2410 func (s *DockerSuite) TestRunModePIDContainerNotRunning(c *check.C) {
2411 // Not applicable on Windows as uses Unix-specific capabilities
2412 testRequires(c, SameHostDaemon, DaemonIsLinux)
2414 out, _ := dockerCmd(c, "create", "busybox")
2416 id := strings.TrimSpace(out)
2417 out, _, err := dockerCmdWithError("run", fmt.Sprintf("--pid=container:%s", id), "busybox")
2419 c.Fatalf("Run container with pid mode container should fail with non running container: %s\n%s", out, err)
2423 func (s *DockerSuite) TestRunMountShmMqueueFromHost(c *check.C) {
2424 // Not applicable on Windows as uses Unix-specific capabilities
2425 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
2427 dockerCmd(c, "run", "-d", "--name", "shmfromhost", "-v", "/dev/shm:/dev/shm", "-v", "/dev/mqueue:/dev/mqueue", "busybox", "sh", "-c", "echo -n test > /dev/shm/test && touch /dev/mqueue/toto && top")
2428 defer os.Remove("/dev/mqueue/toto")
2429 defer os.Remove("/dev/shm/test")
2430 volPath, err := inspectMountSourceField("shmfromhost", "/dev/shm")
2431 c.Assert(err, checker.IsNil)
2432 if volPath != "/dev/shm" {
2433 c.Fatalf("volumePath should have been /dev/shm, was %s", volPath)
2436 out, _ := dockerCmd(c, "run", "--name", "ipchost", "--ipc", "host", "busybox", "cat", "/dev/shm/test")
2438 c.Fatalf("Output of /dev/shm/test expected test but found: %s", out)
2441 // Check that the mq was created
2442 if _, err := os.Stat("/dev/mqueue/toto"); err != nil {
2443 c.Fatalf("Failed to confirm '/dev/mqueue/toto' presence on host: %s", err.Error())
2447 func (s *DockerSuite) TestContainerNetworkMode(c *check.C) {
2448 // Not applicable on Windows as uses Unix-specific capabilities
2449 testRequires(c, SameHostDaemon, DaemonIsLinux)
2451 out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
2452 id := strings.TrimSpace(out)
2453 c.Assert(waitRun(id), check.IsNil)
2454 pid1 := inspectField(c, id, "State.Pid")
2456 parentContainerNet, err := os.Readlink(fmt.Sprintf("/proc/%s/ns/net", pid1))
2461 out, _ = dockerCmd(c, "run", fmt.Sprintf("--net=container:%s", id), "busybox", "readlink", "/proc/self/ns/net")
2462 out = strings.Trim(out, "\n")
2463 if parentContainerNet != out {
2464 c.Fatalf("NET different with --net=container:%s %s != %s\n", id, parentContainerNet, out)
2468 func (s *DockerSuite) TestRunModePIDHost(c *check.C) {
2469 // Not applicable on Windows as uses Unix-specific capabilities
2470 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
2472 hostPid, err := os.Readlink("/proc/1/ns/pid")
2477 out, _ := dockerCmd(c, "run", "--pid=host", "busybox", "readlink", "/proc/self/ns/pid")
2478 out = strings.Trim(out, "\n")
2480 c.Fatalf("PID different with --pid=host %s != %s\n", hostPid, out)
2483 out, _ = dockerCmd(c, "run", "busybox", "readlink", "/proc/self/ns/pid")
2484 out = strings.Trim(out, "\n")
2486 c.Fatalf("PID should be different without --pid=host %s == %s\n", hostPid, out)
2490 func (s *DockerSuite) TestRunModeUTSHost(c *check.C) {
2491 // Not applicable on Windows as uses Unix-specific capabilities
2492 testRequires(c, SameHostDaemon, DaemonIsLinux)
2494 hostUTS, err := os.Readlink("/proc/1/ns/uts")
2499 out, _ := dockerCmd(c, "run", "--uts=host", "busybox", "readlink", "/proc/self/ns/uts")
2500 out = strings.Trim(out, "\n")
2502 c.Fatalf("UTS different with --uts=host %s != %s\n", hostUTS, out)
2505 out, _ = dockerCmd(c, "run", "busybox", "readlink", "/proc/self/ns/uts")
2506 out = strings.Trim(out, "\n")
2508 c.Fatalf("UTS should be different without --uts=host %s == %s\n", hostUTS, out)
2511 out, _ = dockerCmdWithFail(c, "run", "-h=name", "--uts=host", "busybox", "ps")
2512 c.Assert(out, checker.Contains, runconfig.ErrConflictUTSHostname.Error())
2515 func (s *DockerSuite) TestRunTLSVerify(c *check.C) {
2516 // Remote daemons use TLS and this test is not applicable when TLS is required.
2517 testRequires(c, SameHostDaemon)
2518 if out, code, err := dockerCmdWithError("ps"); err != nil || code != 0 {
2519 c.Fatalf("Should have worked: %v:\n%v", err, out)
2522 // Regardless of whether we specify true or false we need to
2523 // test to make sure tls is turned on if --tlsverify is specified at all
2524 result := dockerCmdWithResult("--tlsverify=false", "ps")
2525 result.Assert(c, icmd.Expected{ExitCode: 1, Err: "error during connect"})
2527 result = dockerCmdWithResult("--tlsverify=true", "ps")
2528 result.Assert(c, icmd.Expected{ExitCode: 1, Err: "cert"})
2531 func (s *DockerSuite) TestRunPortFromDockerRangeInUse(c *check.C) {
2532 // TODO Windows. Once moved to libnetwork/CNM, this may be able to be
2534 testRequires(c, DaemonIsLinux)
2535 // first find allocator current position
2536 out, _ := dockerCmd(c, "run", "-d", "-p", ":80", "busybox", "top")
2538 id := strings.TrimSpace(out)
2539 out, _ = dockerCmd(c, "port", id)
2541 out = strings.TrimSpace(out)
2543 c.Fatal("docker port command output is empty")
2545 out = strings.Split(out, ":")[1]
2546 lastPort, err := strconv.Atoi(out)
2550 port := lastPort + 1
2551 l, err := net.Listen("tcp", ":"+strconv.Itoa(port))
2557 out, _ = dockerCmd(c, "run", "-d", "-p", ":80", "busybox", "top")
2559 id = strings.TrimSpace(out)
2560 dockerCmd(c, "port", id)
2563 func (s *DockerSuite) TestRunTTYWithPipe(c *check.C) {
2564 errChan := make(chan error)
2566 defer close(errChan)
2568 cmd := exec.Command(dockerBinary, "run", "-ti", "busybox", "true")
2569 if _, err := cmd.StdinPipe(); err != nil {
2574 expected := "the input device is not a TTY"
2575 if runtime.GOOS == "windows" {
2576 expected += ". If you are using mintty, try prefixing the command with 'winpty'"
2578 if out, _, err := runCommandWithOutput(cmd); err == nil {
2579 errChan <- fmt.Errorf("run should have failed")
2581 } else if !strings.Contains(out, expected) {
2582 errChan <- fmt.Errorf("run failed with error %q: expected %q", out, expected)
2588 case err := <-errChan:
2589 c.Assert(err, check.IsNil)
2590 case <-time.After(30 * time.Second):
2591 c.Fatal("container is running but should have failed")
2595 func (s *DockerSuite) TestRunNonLocalMacAddress(c *check.C) {
2596 addr := "00:16:3E:08:00:50"
2597 args := []string{"run", "--mac-address", addr}
2600 if testEnv.DaemonPlatform() != "windows" {
2601 args = append(args, "busybox", "ifconfig")
2603 args = append(args, testEnv.MinimalBaseImage(), "ipconfig", "/all")
2604 expected = strings.Replace(strings.ToUpper(addr), ":", "-", -1)
2607 if out, _ := dockerCmd(c, args...); !strings.Contains(out, expected) {
2608 c.Fatalf("Output should have contained %q: %s", expected, out)
2612 func (s *DockerSuite) TestRunNetHost(c *check.C) {
2613 // Not applicable on Windows as uses Unix-specific capabilities
2614 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
2616 hostNet, err := os.Readlink("/proc/1/ns/net")
2621 out, _ := dockerCmd(c, "run", "--net=host", "busybox", "readlink", "/proc/self/ns/net")
2622 out = strings.Trim(out, "\n")
2624 c.Fatalf("Net namespace different with --net=host %s != %s\n", hostNet, out)
2627 out, _ = dockerCmd(c, "run", "busybox", "readlink", "/proc/self/ns/net")
2628 out = strings.Trim(out, "\n")
2630 c.Fatalf("Net namespace should be different without --net=host %s == %s\n", hostNet, out)
2634 func (s *DockerSuite) TestRunNetHostTwiceSameName(c *check.C) {
2635 // TODO Windows. As Windows networking evolves and converges towards
2636 // CNM, this test may be possible to enable on Windows.
2637 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
2639 dockerCmd(c, "run", "--rm", "--name=thost", "--net=host", "busybox", "true")
2640 dockerCmd(c, "run", "--rm", "--name=thost", "--net=host", "busybox", "true")
2643 func (s *DockerSuite) TestRunNetContainerWhichHost(c *check.C) {
2644 // Not applicable on Windows as uses Unix-specific capabilities
2645 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
2647 hostNet, err := os.Readlink("/proc/1/ns/net")
2652 dockerCmd(c, "run", "-d", "--net=host", "--name=test", "busybox", "top")
2654 out, _ := dockerCmd(c, "run", "--net=container:test", "busybox", "readlink", "/proc/self/ns/net")
2655 out = strings.Trim(out, "\n")
2657 c.Fatalf("Container should have host network namespace")
2661 func (s *DockerSuite) TestRunAllowPortRangeThroughPublish(c *check.C) {
2662 // TODO Windows. This may be possible to enable in the future. However,
2663 // Windows does not currently support --expose, or populate the network
2664 // settings seen through inspect.
2665 testRequires(c, DaemonIsLinux)
2666 out, _ := dockerCmd(c, "run", "-d", "--expose", "3000-3003", "-p", "3000-3003", "busybox", "top")
2668 id := strings.TrimSpace(out)
2669 portstr := inspectFieldJSON(c, id, "NetworkSettings.Ports")
2671 var ports nat.PortMap
2672 err := json.Unmarshal([]byte(portstr), &ports)
2673 c.Assert(err, checker.IsNil, check.Commentf("failed to unmarshal: %v", portstr))
2674 for port, binding := range ports {
2675 portnum, _ := strconv.Atoi(strings.Split(string(port), "/")[0])
2676 if portnum < 3000 || portnum > 3003 {
2677 c.Fatalf("Port %d is out of range ", portnum)
2679 if binding == nil || len(binding) != 1 || len(binding[0].HostPort) == 0 {
2680 c.Fatal("Port is not mapped for the port "+port, out)
2685 func (s *DockerSuite) TestRunSetDefaultRestartPolicy(c *check.C) {
2686 runSleepingContainer(c, "--name=testrunsetdefaultrestartpolicy")
2687 out := inspectField(c, "testrunsetdefaultrestartpolicy", "HostConfig.RestartPolicy.Name")
2689 c.Fatalf("Set default restart policy failed")
2693 func (s *DockerSuite) TestRunRestartMaxRetries(c *check.C) {
2694 out, _ := dockerCmd(c, "run", "-d", "--restart=on-failure:3", "busybox", "false")
2695 timeout := 10 * time.Second
2696 if testEnv.DaemonPlatform() == "windows" {
2697 timeout = 120 * time.Second
2700 id := strings.TrimSpace(string(out))
2701 if err := waitInspect(id, "{{ .State.Restarting }} {{ .State.Running }}", "false false", timeout); err != nil {
2705 count := inspectField(c, id, "RestartCount")
2707 c.Fatalf("Container was restarted %s times, expected %d", count, 3)
2710 MaximumRetryCount := inspectField(c, id, "HostConfig.RestartPolicy.MaximumRetryCount")
2711 if MaximumRetryCount != "3" {
2712 c.Fatalf("Container Maximum Retry Count is %s, expected %s", MaximumRetryCount, "3")
2716 func (s *DockerSuite) TestRunContainerWithWritableRootfs(c *check.C) {
2717 dockerCmd(c, "run", "--rm", "busybox", "touch", "/file")
2720 func (s *DockerSuite) TestRunContainerWithReadonlyRootfs(c *check.C) {
2721 // Not applicable on Windows which does not support --read-only
2722 testRequires(c, DaemonIsLinux, UserNamespaceROMount)
2725 // don't test privileged mode subtest if user namespaces enabled
2726 if root := os.Getenv("DOCKER_REMAP_ROOT"); root != "" {
2729 testReadOnlyFile(c, testPriv, "/file", "/etc/hosts", "/etc/resolv.conf", "/etc/hostname", "/sys/kernel", "/dev/.dont.touch.me")
2732 func (s *DockerSuite) TestPermissionsPtsReadonlyRootfs(c *check.C) {
2733 // Not applicable on Windows due to use of Unix specific functionality, plus
2734 // the use of --read-only which is not supported.
2735 testRequires(c, DaemonIsLinux, UserNamespaceROMount)
2737 // Ensure we have not broken writing /dev/pts
2738 out, status := dockerCmd(c, "run", "--read-only", "--rm", "busybox", "mount")
2740 c.Fatal("Could not obtain mounts when checking /dev/pts mntpnt.")
2742 expected := "type devpts (rw,"
2743 if !strings.Contains(string(out), expected) {
2744 c.Fatalf("expected output to contain %s but contains %s", expected, out)
2748 func testReadOnlyFile(c *check.C, testPriv bool, filenames ...string) {
2749 touch := "touch " + strings.Join(filenames, " ")
2750 out, _, err := dockerCmdWithError("run", "--read-only", "--rm", "busybox", "sh", "-c", touch)
2751 c.Assert(err, checker.NotNil)
2753 for _, f := range filenames {
2754 expected := "touch: " + f + ": Read-only file system"
2755 c.Assert(out, checker.Contains, expected)
2762 out, _, err = dockerCmdWithError("run", "--read-only", "--privileged", "--rm", "busybox", "sh", "-c", touch)
2763 c.Assert(err, checker.NotNil)
2765 for _, f := range filenames {
2766 expected := "touch: " + f + ": Read-only file system"
2767 c.Assert(out, checker.Contains, expected)
2771 func (s *DockerSuite) TestRunContainerWithReadonlyEtcHostsAndLinkedContainer(c *check.C) {
2772 // Not applicable on Windows which does not support --link
2773 testRequires(c, DaemonIsLinux, UserNamespaceROMount)
2775 dockerCmd(c, "run", "-d", "--name", "test-etc-hosts-ro-linked", "busybox", "top")
2777 out, _ := dockerCmd(c, "run", "--read-only", "--link", "test-etc-hosts-ro-linked:testlinked", "busybox", "cat", "/etc/hosts")
2778 if !strings.Contains(string(out), "testlinked") {
2779 c.Fatal("Expected /etc/hosts to be updated even if --read-only enabled")
2783 func (s *DockerSuite) TestRunContainerWithReadonlyRootfsWithDNSFlag(c *check.C) {
2784 // Not applicable on Windows which does not support either --read-only or --dns.
2785 testRequires(c, DaemonIsLinux, UserNamespaceROMount)
2787 out, _ := dockerCmd(c, "run", "--read-only", "--dns", "1.1.1.1", "busybox", "/bin/cat", "/etc/resolv.conf")
2788 if !strings.Contains(string(out), "1.1.1.1") {
2789 c.Fatal("Expected /etc/resolv.conf to be updated even if --read-only enabled and --dns flag used")
2793 func (s *DockerSuite) TestRunContainerWithReadonlyRootfsWithAddHostFlag(c *check.C) {
2794 // Not applicable on Windows which does not support --read-only
2795 testRequires(c, DaemonIsLinux, UserNamespaceROMount)
2797 out, _ := dockerCmd(c, "run", "--read-only", "--add-host", "testreadonly:127.0.0.1", "busybox", "/bin/cat", "/etc/hosts")
2798 if !strings.Contains(string(out), "testreadonly") {
2799 c.Fatal("Expected /etc/hosts to be updated even if --read-only enabled and --add-host flag used")
2803 func (s *DockerSuite) TestRunVolumesFromRestartAfterRemoved(c *check.C) {
2804 prefix, _ := getPrefixAndSlashFromDaemonPlatform()
2805 runSleepingContainer(c, "--name=voltest", "-v", prefix+"/foo")
2806 runSleepingContainer(c, "--name=restarter", "--volumes-from", "voltest")
2808 // Remove the main volume container and restart the consuming container
2809 dockerCmd(c, "rm", "-f", "voltest")
2811 // This should not fail since the volumes-from were already applied
2812 dockerCmd(c, "restart", "restarter")
2815 // run container with --rm should remove container if exit code != 0
2816 func (s *DockerSuite) TestRunContainerWithRmFlagExitCodeNotEqualToZero(c *check.C) {
2818 cli.Docker(cli.Args("run", "--name", name, "--rm", "busybox", "ls", "/notexists")).Assert(c, icmd.Expected{
2822 out := cli.DockerCmd(c, "ps", "-q", "-a").Combined()
2824 c.Fatal("Expected not to have containers", out)
2828 func (s *DockerSuite) TestRunContainerWithRmFlagCannotStartContainer(c *check.C) {
2830 cli.Docker(cli.Args("run", "--name", name, "--rm", "busybox", "commandNotFound")).Assert(c, icmd.Expected{
2833 out := cli.DockerCmd(c, "ps", "-q", "-a").Combined()
2835 c.Fatal("Expected not to have containers", out)
2839 func (s *DockerSuite) TestRunPIDHostWithChildIsKillable(c *check.C) {
2840 // Not applicable on Windows as uses Unix specific functionality
2841 testRequires(c, DaemonIsLinux, NotUserNamespace)
2842 name := "ibuildthecloud"
2843 dockerCmd(c, "run", "-d", "--pid=host", "--name", name, "busybox", "sh", "-c", "sleep 30; echo hi")
2845 c.Assert(waitRun(name), check.IsNil)
2847 errchan := make(chan error)
2849 if out, _, err := dockerCmdWithError("kill", name); err != nil {
2850 errchan <- fmt.Errorf("%v:\n%s", err, out)
2855 case err := <-errchan:
2856 c.Assert(err, check.IsNil)
2857 case <-time.After(5 * time.Second):
2858 c.Fatal("Kill container timed out")
2862 func (s *DockerSuite) TestRunWithTooSmallMemoryLimit(c *check.C) {
2863 // TODO Windows. This may be possible to enable once Windows supports
2864 // memory limits on containers
2865 testRequires(c, DaemonIsLinux)
2866 // this memory limit is 1 byte less than the min, which is 4MB
2867 // https://github.com/docker/docker/blob/v1.5.0/daemon/create.go#L22
2868 out, _, err := dockerCmdWithError("run", "-m", "4194303", "busybox")
2869 if err == nil || !strings.Contains(out, "Minimum memory limit allowed is 4MB") {
2870 c.Fatalf("expected run to fail when using too low a memory limit: %q", out)
2874 func (s *DockerSuite) TestRunWriteToProcAsound(c *check.C) {
2875 // Not applicable on Windows as uses Unix specific functionality
2876 testRequires(c, DaemonIsLinux)
2877 _, code, err := dockerCmdWithError("run", "busybox", "sh", "-c", "echo 111 >> /proc/asound/version")
2878 if err == nil || code == 0 {
2879 c.Fatal("standard container should not be able to write to /proc/asound")
2883 func (s *DockerSuite) TestRunReadProcTimer(c *check.C) {
2884 // Not applicable on Windows as uses Unix specific functionality
2885 testRequires(c, DaemonIsLinux)
2886 out, code, err := dockerCmdWithError("run", "busybox", "cat", "/proc/timer_stats")
2893 if strings.Trim(out, "\n ") != "" {
2894 c.Fatalf("expected to receive no output from /proc/timer_stats but received %q", out)
2898 func (s *DockerSuite) TestRunReadProcLatency(c *check.C) {
2899 // Not applicable on Windows as uses Unix specific functionality
2900 testRequires(c, DaemonIsLinux)
2901 // some kernels don't have this configured so skip the test if this file is not found
2902 // on the host running the tests.
2903 if _, err := os.Stat("/proc/latency_stats"); err != nil {
2904 c.Skip("kernel doesn't have latency_stats configured")
2907 out, code, err := dockerCmdWithError("run", "busybox", "cat", "/proc/latency_stats")
2914 if strings.Trim(out, "\n ") != "" {
2915 c.Fatalf("expected to receive no output from /proc/latency_stats but received %q", out)
2919 func (s *DockerSuite) TestRunReadFilteredProc(c *check.C) {
2920 // Not applicable on Windows as uses Unix specific functionality
2921 testRequires(c, Apparmor, DaemonIsLinux, NotUserNamespace)
2923 testReadPaths := []string{
2924 "/proc/latency_stats",
2925 "/proc/timer_stats",
2928 for i, filePath := range testReadPaths {
2929 name := fmt.Sprintf("procsieve-%d", i)
2930 shellCmd := fmt.Sprintf("exec 3<%s", filePath)
2932 out, exitCode, err := dockerCmdWithError("run", "--privileged", "--security-opt", "apparmor=docker-default", "--name", name, "busybox", "sh", "-c", shellCmd)
2937 c.Fatalf("Open FD for read should have failed with permission denied, got: %s, %v", out, err)
2942 func (s *DockerSuite) TestMountIntoProc(c *check.C) {
2943 // Not applicable on Windows as uses Unix specific functionality
2944 testRequires(c, DaemonIsLinux)
2945 _, code, err := dockerCmdWithError("run", "-v", "/proc//sys", "busybox", "true")
2946 if err == nil || code == 0 {
2947 c.Fatal("container should not be able to mount into /proc")
2951 func (s *DockerSuite) TestMountIntoSys(c *check.C) {
2952 // Not applicable on Windows as uses Unix specific functionality
2953 testRequires(c, DaemonIsLinux)
2954 testRequires(c, NotUserNamespace)
2955 dockerCmd(c, "run", "-v", "/sys/fs/cgroup", "busybox", "true")
2958 func (s *DockerSuite) TestRunUnshareProc(c *check.C) {
2959 // Not applicable on Windows as uses Unix specific functionality
2960 testRequires(c, Apparmor, DaemonIsLinux, NotUserNamespace)
2962 // In this test goroutines are used to run test cases in parallel to prevent the test from taking a long time to run.
2963 errChan := make(chan error)
2967 out, _, err := dockerCmdWithError("run", "--name", name, "--security-opt", "seccomp=unconfined", "debian:jessie", "unshare", "-p", "-m", "-f", "-r", "--mount-proc=/proc", "mount")
2969 !(strings.Contains(strings.ToLower(out), "permission denied") ||
2970 strings.Contains(strings.ToLower(out), "operation not permitted")) {
2971 errChan <- fmt.Errorf("unshare with --mount-proc should have failed with 'permission denied' or 'operation not permitted', got: %s, %v", out, err)
2979 out, _, err := dockerCmdWithError("run", "--name", name, "--security-opt", "seccomp=unconfined", "debian:jessie", "unshare", "-p", "-m", "-f", "-r", "mount", "-t", "proc", "none", "/proc")
2981 !(strings.Contains(strings.ToLower(out), "mount: cannot mount none") ||
2982 strings.Contains(strings.ToLower(out), "permission denied") ||
2983 strings.Contains(strings.ToLower(out), "operation not permitted")) {
2984 errChan <- fmt.Errorf("unshare and mount of /proc should have failed with 'mount: cannot mount none' or 'permission denied', got: %s, %v", out, err)
2990 /* Ensure still fails if running privileged with the default policy */
2992 name := "crashoverride"
2993 out, _, err := dockerCmdWithError("run", "--privileged", "--security-opt", "seccomp=unconfined", "--security-opt", "apparmor=docker-default", "--name", name, "debian:jessie", "unshare", "-p", "-m", "-f", "-r", "mount", "-t", "proc", "none", "/proc")
2995 !(strings.Contains(strings.ToLower(out), "mount: cannot mount none") ||
2996 strings.Contains(strings.ToLower(out), "permission denied") ||
2997 strings.Contains(strings.ToLower(out), "operation not permitted")) {
2998 errChan <- fmt.Errorf("privileged unshare with apparmor should have failed with 'mount: cannot mount none' or 'permission denied', got: %s, %v", out, err)
3005 for i := 0; i < 3; i++ {
3007 if retErr == nil && err != nil {
3016 func (s *DockerSuite) TestRunPublishPort(c *check.C) {
3017 // TODO Windows: This may be possible once Windows moves to libnetwork and CNM
3018 testRequires(c, DaemonIsLinux)
3019 dockerCmd(c, "run", "-d", "--name", "test", "--expose", "8080", "busybox", "top")
3020 out, _ := dockerCmd(c, "port", "test")
3021 out = strings.Trim(out, "\r\n")
3023 c.Fatalf("run without --publish-all should not publish port, out should be nil, but got: %s", out)
3028 func (s *DockerSuite) TestDevicePermissions(c *check.C) {
3029 // Not applicable on Windows as uses Unix specific functionality
3030 testRequires(c, DaemonIsLinux)
3031 const permissions = "crw-rw-rw-"
3032 out, status := dockerCmd(c, "run", "--device", "/dev/fuse:/dev/fuse:mrw", "busybox:latest", "ls", "-l", "/dev/fuse")
3034 c.Fatalf("expected status 0, got %d", status)
3036 if !strings.HasPrefix(out, permissions) {
3037 c.Fatalf("output should begin with %q, got %q", permissions, out)
3041 func (s *DockerSuite) TestRunCapAddCHOWN(c *check.C) {
3042 // Not applicable on Windows as uses Unix specific functionality
3043 testRequires(c, DaemonIsLinux)
3044 out, _ := dockerCmd(c, "run", "--cap-drop=ALL", "--cap-add=CHOWN", "busybox", "sh", "-c", "adduser -D -H newuser && chown newuser /home && echo ok")
3046 if actual := strings.Trim(out, "\r\n"); actual != "ok" {
3047 c.Fatalf("expected output ok received %s", actual)
3051 // https://github.com/docker/docker/pull/14498
3052 func (s *DockerSuite) TestVolumeFromMixedRWOptions(c *check.C) {
3053 prefix, slash := getPrefixAndSlashFromDaemonPlatform()
3055 dockerCmd(c, "run", "--name", "parent", "-v", prefix+"/test", "busybox", "true")
3057 dockerCmd(c, "run", "--volumes-from", "parent:ro", "--name", "test-volumes-1", "busybox", "true")
3058 dockerCmd(c, "run", "--volumes-from", "parent:rw", "--name", "test-volumes-2", "busybox", "true")
3060 if testEnv.DaemonPlatform() != "windows" {
3061 mRO, err := inspectMountPoint("test-volumes-1", prefix+slash+"test")
3062 c.Assert(err, checker.IsNil, check.Commentf("failed to inspect mount point"))
3064 c.Fatalf("Expected RO volume was RW")
3068 mRW, err := inspectMountPoint("test-volumes-2", prefix+slash+"test")
3069 c.Assert(err, checker.IsNil, check.Commentf("failed to inspect mount point"))
3071 c.Fatalf("Expected RW volume was RO")
3075 func (s *DockerSuite) TestRunWriteFilteredProc(c *check.C) {
3076 // Not applicable on Windows as uses Unix specific functionality
3077 testRequires(c, Apparmor, DaemonIsLinux, NotUserNamespace)
3079 testWritePaths := []string{
3080 /* modprobe and core_pattern should both be denied by generic
3081 * policy of denials for /proc/sys/kernel. These files have been
3082 * picked to be checked as they are particularly sensitive to writes */
3083 "/proc/sys/kernel/modprobe",
3084 "/proc/sys/kernel/core_pattern",
3085 "/proc/sysrq-trigger",
3088 for i, filePath := range testWritePaths {
3089 name := fmt.Sprintf("writeprocsieve-%d", i)
3091 shellCmd := fmt.Sprintf("exec 3>%s", filePath)
3092 out, code, err := dockerCmdWithError("run", "--privileged", "--security-opt", "apparmor=docker-default", "--name", name, "busybox", "sh", "-c", shellCmd)
3097 c.Fatalf("Open FD for write should have failed with permission denied, got: %s, %v", out, err)
3102 func (s *DockerSuite) TestRunNetworkFilesBindMount(c *check.C) {
3103 // Not applicable on Windows as uses Unix specific functionality
3104 testRequires(c, SameHostDaemon, DaemonIsLinux)
3106 expected := "test123"
3108 filename := createTmpFile(c, expected)
3109 defer os.Remove(filename)
3111 nwfiles := []string{"/etc/resolv.conf", "/etc/hosts", "/etc/hostname"}
3113 for i := range nwfiles {
3114 actual, _ := dockerCmd(c, "run", "-v", filename+":"+nwfiles[i], "busybox", "cat", nwfiles[i])
3115 if actual != expected {
3116 c.Fatalf("expected %s be: %q, but was: %q", nwfiles[i], expected, actual)
3121 func (s *DockerSuite) TestRunNetworkFilesBindMountRO(c *check.C) {
3122 // Not applicable on Windows as uses Unix specific functionality
3123 testRequires(c, SameHostDaemon, DaemonIsLinux)
3125 filename := createTmpFile(c, "test123")
3126 defer os.Remove(filename)
3128 nwfiles := []string{"/etc/resolv.conf", "/etc/hosts", "/etc/hostname"}
3130 for i := range nwfiles {
3131 _, exitCode, err := dockerCmdWithError("run", "-v", filename+":"+nwfiles[i]+":ro", "busybox", "touch", nwfiles[i])
3132 if err == nil || exitCode == 0 {
3133 c.Fatalf("run should fail because bind mount of %s is ro: exit code %d", nwfiles[i], exitCode)
3138 func (s *DockerSuite) TestRunNetworkFilesBindMountROFilesystem(c *check.C) {
3139 // Not applicable on Windows as uses Unix specific functionality
3140 testRequires(c, SameHostDaemon, DaemonIsLinux, UserNamespaceROMount)
3142 filename := createTmpFile(c, "test123")
3143 defer os.Remove(filename)
3145 nwfiles := []string{"/etc/resolv.conf", "/etc/hosts", "/etc/hostname"}
3147 for i := range nwfiles {
3148 _, exitCode := dockerCmd(c, "run", "-v", filename+":"+nwfiles[i], "--read-only", "busybox", "touch", nwfiles[i])
3150 c.Fatalf("run should not fail because %s is mounted writable on read-only root filesystem: exit code %d", nwfiles[i], exitCode)
3154 for i := range nwfiles {
3155 _, exitCode, err := dockerCmdWithError("run", "-v", filename+":"+nwfiles[i]+":ro", "--read-only", "busybox", "touch", nwfiles[i])
3156 if err == nil || exitCode == 0 {
3157 c.Fatalf("run should fail because %s is mounted read-only on read-only root filesystem: exit code %d", nwfiles[i], exitCode)
3162 func (s *DockerTrustSuite) TestTrustedRun(c *check.C) {
3163 // Windows does not support this functionality
3164 testRequires(c, DaemonIsLinux)
3165 repoName := s.setupTrustedImage(c, "trusted-run")
3168 cli.Docker(cli.Args("run", repoName), trustedCmd).Assert(c, SuccessTagging)
3169 cli.DockerCmd(c, "rmi", repoName)
3171 // Try untrusted run to ensure we pushed the tag to the registry
3172 cli.Docker(cli.Args("run", "--disable-content-trust=true", repoName), trustedCmd).Assert(c, SuccessDownloadedOnStderr)
3175 func (s *DockerTrustSuite) TestUntrustedRun(c *check.C) {
3176 // Windows does not support this functionality
3177 testRequires(c, DaemonIsLinux)
3178 repoName := fmt.Sprintf("%v/dockercliuntrusted/runtest:latest", privateRegistryURL)
3179 // tag the image and upload it to the private registry
3180 cli.DockerCmd(c, "tag", "busybox", repoName)
3181 cli.DockerCmd(c, "push", repoName)
3182 cli.DockerCmd(c, "rmi", repoName)
3184 // Try trusted run on untrusted tag
3185 cli.Docker(cli.Args("run", repoName), trustedCmd).Assert(c, icmd.Expected{
3187 Err: "does not have trust data for",
3191 func (s *DockerTrustSuite) TestTrustedRunFromBadTrustServer(c *check.C) {
3192 // Windows does not support this functionality
3193 testRequires(c, DaemonIsLinux)
3194 repoName := fmt.Sprintf("%v/dockerclievilrun/trusted:latest", privateRegistryURL)
3195 evilLocalConfigDir, err := ioutil.TempDir("", "evilrun-local-config-dir")
3197 c.Fatalf("Failed to create local temp dir")
3200 // tag the image and upload it to the private registry
3201 cli.DockerCmd(c, "tag", "busybox", repoName)
3203 cli.Docker(cli.Args("push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing)
3204 cli.DockerCmd(c, "rmi", repoName)
3207 cli.Docker(cli.Args("run", repoName), trustedCmd).Assert(c, SuccessTagging)
3208 cli.DockerCmd(c, "rmi", repoName)
3210 // Kill the notary server, start a new "evil" one.
3212 s.not, err = newTestNotary(c)
3214 c.Fatalf("Restarting notary server failed.")
3217 // In order to make an evil server, lets re-init a client (with a different trust dir) and push new data.
3218 // tag an image and upload it to the private registry
3219 cli.DockerCmd(c, "--config", evilLocalConfigDir, "tag", "busybox", repoName)
3221 // Push up to the new server
3222 cli.Docker(cli.Args("--config", evilLocalConfigDir, "push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing)
3224 // Now, try running with the original client from this new trust server. This should fail because the new root is invalid.
3225 cli.Docker(cli.Args("run", repoName), trustedCmd).Assert(c, icmd.Expected{
3227 Err: "could not rotate trust to a new trusted root",
3231 func (s *DockerSuite) TestPtraceContainerProcsFromHost(c *check.C) {
3232 // Not applicable on Windows as uses Unix specific functionality
3233 testRequires(c, DaemonIsLinux, SameHostDaemon)
3235 out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
3236 id := strings.TrimSpace(out)
3237 c.Assert(waitRun(id), check.IsNil)
3238 pid1 := inspectField(c, id, "State.Pid")
3240 _, err := os.Readlink(fmt.Sprintf("/proc/%s/ns/net", pid1))
3246 func (s *DockerSuite) TestAppArmorDeniesPtrace(c *check.C) {
3247 // Not applicable on Windows as uses Unix specific functionality
3248 testRequires(c, SameHostDaemon, Apparmor, DaemonIsLinux)
3250 // Run through 'sh' so we are NOT pid 1. Pid 1 may be able to trace
3251 // itself, but pid>1 should not be able to trace pid1.
3252 _, exitCode, _ := dockerCmdWithError("run", "busybox", "sh", "-c", "sh -c readlink /proc/1/ns/net")
3254 c.Fatal("ptrace was not successfully restricted by AppArmor")
3258 func (s *DockerSuite) TestAppArmorTraceSelf(c *check.C) {
3259 // Not applicable on Windows as uses Unix specific functionality
3260 testRequires(c, DaemonIsLinux, SameHostDaemon, Apparmor)
3262 _, exitCode, _ := dockerCmdWithError("run", "busybox", "readlink", "/proc/1/ns/net")
3264 c.Fatal("ptrace of self failed.")
3268 func (s *DockerSuite) TestAppArmorDeniesChmodProc(c *check.C) {
3269 // Not applicable on Windows as uses Unix specific functionality
3270 testRequires(c, SameHostDaemon, Apparmor, DaemonIsLinux, NotUserNamespace)
3271 _, exitCode, _ := dockerCmdWithError("run", "busybox", "chmod", "744", "/proc/cpuinfo")
3273 // If our test failed, attempt to repair the host system...
3274 _, exitCode, _ := dockerCmdWithError("run", "busybox", "chmod", "444", "/proc/cpuinfo")
3276 c.Fatal("AppArmor was unsuccessful in prohibiting chmod of /proc/* files.")
3281 func (s *DockerSuite) TestRunCapAddSYSTIME(c *check.C) {
3282 // Not applicable on Windows as uses Unix specific functionality
3283 testRequires(c, DaemonIsLinux)
3285 dockerCmd(c, "run", "--cap-drop=ALL", "--cap-add=SYS_TIME", "busybox", "sh", "-c", "grep ^CapEff /proc/self/status | sed 's/^CapEff:\t//' | grep ^0000000002000000$")
3288 // run create container failed should clean up the container
3289 func (s *DockerSuite) TestRunCreateContainerFailedCleanUp(c *check.C) {
3290 // TODO Windows. This may be possible to enable once link is supported
3291 testRequires(c, DaemonIsLinux)
3292 name := "unique_name"
3293 _, _, err := dockerCmdWithError("run", "--name", name, "--link", "nothing:nothing", "busybox")
3294 c.Assert(err, check.NotNil, check.Commentf("Expected docker run to fail!"))
3296 containerID, err := inspectFieldWithError(name, "Id")
3297 c.Assert(err, checker.NotNil, check.Commentf("Expected not to have this container: %s!", containerID))
3298 c.Assert(containerID, check.Equals, "", check.Commentf("Expected not to have this container: %s!", containerID))
3301 func (s *DockerSuite) TestRunNamedVolume(c *check.C) {
3302 prefix, _ := getPrefixAndSlashFromDaemonPlatform()
3303 testRequires(c, DaemonIsLinux)
3304 dockerCmd(c, "run", "--name=test", "-v", "testing:"+prefix+"/foo", "busybox", "sh", "-c", "echo hello > "+prefix+"/foo/bar")
3306 out, _ := dockerCmd(c, "run", "--volumes-from", "test", "busybox", "sh", "-c", "cat "+prefix+"/foo/bar")
3307 c.Assert(strings.TrimSpace(out), check.Equals, "hello")
3309 out, _ = dockerCmd(c, "run", "-v", "testing:"+prefix+"/foo", "busybox", "sh", "-c", "cat "+prefix+"/foo/bar")
3310 c.Assert(strings.TrimSpace(out), check.Equals, "hello")
3313 func (s *DockerSuite) TestRunWithUlimits(c *check.C) {
3314 // Not applicable on Windows as uses Unix specific functionality
3315 testRequires(c, DaemonIsLinux)
3317 out, _ := dockerCmd(c, "run", "--name=testulimits", "--ulimit", "nofile=42", "busybox", "/bin/sh", "-c", "ulimit -n")
3318 ul := strings.TrimSpace(out)
3320 c.Fatalf("expected `ulimit -n` to be 42, got %s", ul)
3324 func (s *DockerSuite) TestRunContainerWithCgroupParent(c *check.C) {
3325 // Not applicable on Windows as uses Unix specific functionality
3326 testRequires(c, DaemonIsLinux)
3328 // cgroup-parent relative path
3329 testRunContainerWithCgroupParent(c, "test", "cgroup-test")
3331 // cgroup-parent absolute path
3332 testRunContainerWithCgroupParent(c, "/cgroup-parent/test", "cgroup-test-absolute")
3335 func testRunContainerWithCgroupParent(c *check.C, cgroupParent, name string) {
3336 out, _, err := dockerCmdWithError("run", "--cgroup-parent", cgroupParent, "--name", name, "busybox", "cat", "/proc/self/cgroup")
3338 c.Fatalf("unexpected failure when running container with --cgroup-parent option - %s\n%v", string(out), err)
3340 cgroupPaths := testutil.ParseCgroupPaths(string(out))
3341 if len(cgroupPaths) == 0 {
3342 c.Fatalf("unexpected output - %q", string(out))
3344 id := getIDByName(c, name)
3345 expectedCgroup := path.Join(cgroupParent, id)
3347 for _, path := range cgroupPaths {
3348 if strings.HasSuffix(path, expectedCgroup) {
3354 c.Fatalf("unexpected cgroup paths. Expected at least one cgroup path to have suffix %q. Cgroup Paths: %v", expectedCgroup, cgroupPaths)
3358 // TestRunInvalidCgroupParent checks that a specially-crafted cgroup parent doesn't cause Docker to crash or start modifying /.
3359 func (s *DockerSuite) TestRunInvalidCgroupParent(c *check.C) {
3360 // Not applicable on Windows as uses Unix specific functionality
3361 testRequires(c, DaemonIsLinux)
3363 testRunInvalidCgroupParent(c, "../../../../../../../../SHOULD_NOT_EXIST", "SHOULD_NOT_EXIST", "cgroup-invalid-test")
3365 testRunInvalidCgroupParent(c, "/../../../../../../../../SHOULD_NOT_EXIST", "/SHOULD_NOT_EXIST", "cgroup-absolute-invalid-test")
3368 func testRunInvalidCgroupParent(c *check.C, cgroupParent, cleanCgroupParent, name string) {
3369 out, _, err := dockerCmdWithError("run", "--cgroup-parent", cgroupParent, "--name", name, "busybox", "cat", "/proc/self/cgroup")
3371 // XXX: This may include a daemon crash.
3372 c.Fatalf("unexpected failure when running container with --cgroup-parent option - %s\n%v", string(out), err)
3375 // We expect "/SHOULD_NOT_EXIST" to not exist. If not, we have a security issue.
3376 if _, err := os.Stat("/SHOULD_NOT_EXIST"); err == nil || !os.IsNotExist(err) {
3377 c.Fatalf("SECURITY: --cgroup-parent with ../../ relative paths cause files to be created in the host (this is bad) !!")
3380 cgroupPaths := testutil.ParseCgroupPaths(string(out))
3381 if len(cgroupPaths) == 0 {
3382 c.Fatalf("unexpected output - %q", string(out))
3384 id := getIDByName(c, name)
3385 expectedCgroup := path.Join(cleanCgroupParent, id)
3387 for _, path := range cgroupPaths {
3388 if strings.HasSuffix(path, expectedCgroup) {
3394 c.Fatalf("unexpected cgroup paths. Expected at least one cgroup path to have suffix %q. Cgroup Paths: %v", expectedCgroup, cgroupPaths)
3398 func (s *DockerSuite) TestRunContainerWithCgroupMountRO(c *check.C) {
3399 // Not applicable on Windows as uses Unix specific functionality
3400 // --read-only + userns has remount issues
3401 testRequires(c, DaemonIsLinux, NotUserNamespace)
3403 filename := "/sys/fs/cgroup/devices/test123"
3404 out, _, err := dockerCmdWithError("run", "busybox", "touch", filename)
3406 c.Fatal("expected cgroup mount point to be read-only, touch file should fail")
3408 expected := "Read-only file system"
3409 if !strings.Contains(out, expected) {
3410 c.Fatalf("expected output from failure to contain %s but contains %s", expected, out)
3414 func (s *DockerSuite) TestRunContainerNetworkModeToSelf(c *check.C) {
3415 // Not applicable on Windows which does not support --net=container
3416 testRequires(c, DaemonIsLinux)
3417 out, _, err := dockerCmdWithError("run", "--name=me", "--net=container:me", "busybox", "true")
3418 if err == nil || !strings.Contains(out, "cannot join own network") {
3419 c.Fatalf("using container net mode to self should result in an error\nerr: %q\nout: %s", err, out)
3423 func (s *DockerSuite) TestRunContainerNetModeWithDNSMacHosts(c *check.C) {
3424 // Not applicable on Windows which does not support --net=container
3425 testRequires(c, DaemonIsLinux)
3426 out, _, err := dockerCmdWithError("run", "-d", "--name", "parent", "busybox", "top")
3428 c.Fatalf("failed to run container: %v, output: %q", err, out)
3431 out, _, err = dockerCmdWithError("run", "--dns", "1.2.3.4", "--net=container:parent", "busybox")
3432 if err == nil || !strings.Contains(out, runconfig.ErrConflictNetworkAndDNS.Error()) {
3433 c.Fatalf("run --net=container with --dns should error out")
3436 out, _, err = dockerCmdWithError("run", "--mac-address", "92:d0:c6:0a:29:33", "--net=container:parent", "busybox")
3437 if err == nil || !strings.Contains(out, runconfig.ErrConflictContainerNetworkAndMac.Error()) {
3438 c.Fatalf("run --net=container with --mac-address should error out")
3441 out, _, err = dockerCmdWithError("run", "--add-host", "test:192.168.2.109", "--net=container:parent", "busybox")
3442 if err == nil || !strings.Contains(out, runconfig.ErrConflictNetworkHosts.Error()) {
3443 c.Fatalf("run --net=container with --add-host should error out")
3447 func (s *DockerSuite) TestRunContainerNetModeWithExposePort(c *check.C) {
3448 // Not applicable on Windows which does not support --net=container
3449 testRequires(c, DaemonIsLinux)
3450 dockerCmd(c, "run", "-d", "--name", "parent", "busybox", "top")
3452 out, _, err := dockerCmdWithError("run", "-p", "5000:5000", "--net=container:parent", "busybox")
3453 if err == nil || !strings.Contains(out, runconfig.ErrConflictNetworkPublishPorts.Error()) {
3454 c.Fatalf("run --net=container with -p should error out")
3457 out, _, err = dockerCmdWithError("run", "-P", "--net=container:parent", "busybox")
3458 if err == nil || !strings.Contains(out, runconfig.ErrConflictNetworkPublishPorts.Error()) {
3459 c.Fatalf("run --net=container with -P should error out")
3462 out, _, err = dockerCmdWithError("run", "--expose", "5000", "--net=container:parent", "busybox")
3463 if err == nil || !strings.Contains(out, runconfig.ErrConflictNetworkExposePorts.Error()) {
3464 c.Fatalf("run --net=container with --expose should error out")
3468 func (s *DockerSuite) TestRunLinkToContainerNetMode(c *check.C) {
3469 // Not applicable on Windows which does not support --net=container or --link
3470 testRequires(c, DaemonIsLinux)
3471 dockerCmd(c, "run", "--name", "test", "-d", "busybox", "top")
3472 dockerCmd(c, "run", "--name", "parent", "-d", "--net=container:test", "busybox", "top")
3473 dockerCmd(c, "run", "-d", "--link=parent:parent", "busybox", "top")
3474 dockerCmd(c, "run", "--name", "child", "-d", "--net=container:parent", "busybox", "top")
3475 dockerCmd(c, "run", "-d", "--link=child:child", "busybox", "top")
3478 func (s *DockerSuite) TestRunLoopbackOnlyExistsWhenNetworkingDisabled(c *check.C) {
3479 // TODO Windows: This may be possible to convert.
3480 testRequires(c, DaemonIsLinux)
3481 out, _ := dockerCmd(c, "run", "--net=none", "busybox", "ip", "-o", "-4", "a", "show", "up")
3485 parts = strings.Split(out, "\n")
3488 for _, l := range parts {
3495 c.Fatalf("Wrong interface count in container %d", count)
3498 if !strings.HasPrefix(out, "1: lo") {
3499 c.Fatalf("Wrong interface in test container: expected [1: lo], got %s", out)
3504 func (s *DockerSuite) TestRunLoopbackWhenNetworkDisabled(c *check.C) {
3505 if testEnv.DaemonPlatform() == "windows" {
3506 dockerCmd(c, "run", "--net=none", testEnv.MinimalBaseImage(), "ping", "-n", "1", "127.0.0.1")
3508 dockerCmd(c, "run", "--net=none", "busybox", "ping", "-c", "1", "127.0.0.1")
3512 func (s *DockerSuite) TestRunModeNetContainerHostname(c *check.C) {
3513 // Windows does not support --net=container
3514 testRequires(c, DaemonIsLinux, ExecSupport)
3516 dockerCmd(c, "run", "-i", "-d", "--name", "parent", "busybox", "top")
3517 out, _ := dockerCmd(c, "exec", "parent", "cat", "/etc/hostname")
3518 out1, _ := dockerCmd(c, "run", "--net=container:parent", "busybox", "cat", "/etc/hostname")
3521 c.Fatal("containers with shared net namespace should have same hostname")
3525 func (s *DockerSuite) TestRunNetworkNotInitializedNoneMode(c *check.C) {
3526 // TODO Windows: Network settings are not currently propagated. This may
3527 // be resolved in the future with the move to libnetwork and CNM.
3528 testRequires(c, DaemonIsLinux)
3529 out, _ := dockerCmd(c, "run", "-d", "--net=none", "busybox", "top")
3530 id := strings.TrimSpace(out)
3531 res := inspectField(c, id, "NetworkSettings.Networks.none.IPAddress")
3533 c.Fatalf("For 'none' mode network must not be initialized, but container got IP: %s", res)
3537 func (s *DockerSuite) TestTwoContainersInNetHost(c *check.C) {
3538 // Not applicable as Windows does not support --net=host
3539 testRequires(c, DaemonIsLinux, NotUserNamespace, NotUserNamespace)
3540 dockerCmd(c, "run", "-d", "--net=host", "--name=first", "busybox", "top")
3541 dockerCmd(c, "run", "-d", "--net=host", "--name=second", "busybox", "top")
3542 dockerCmd(c, "stop", "first")
3543 dockerCmd(c, "stop", "second")
3546 func (s *DockerSuite) TestContainersInUserDefinedNetwork(c *check.C) {
3547 testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm)
3548 dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork")
3549 dockerCmd(c, "run", "-d", "--net=testnetwork", "--name=first", "busybox", "top")
3550 c.Assert(waitRun("first"), check.IsNil)
3551 dockerCmd(c, "run", "-t", "--net=testnetwork", "--name=second", "busybox", "ping", "-c", "1", "first")
3554 func (s *DockerSuite) TestContainersInMultipleNetworks(c *check.C) {
3555 testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm)
3556 // Create 2 networks using bridge driver
3557 dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1")
3558 dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork2")
3559 // Run and connect containers to testnetwork1
3560 dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=first", "busybox", "top")
3561 c.Assert(waitRun("first"), check.IsNil)
3562 dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=second", "busybox", "top")
3563 c.Assert(waitRun("second"), check.IsNil)
3564 // Check connectivity between containers in testnetwork2
3565 dockerCmd(c, "exec", "first", "ping", "-c", "1", "second.testnetwork1")
3566 // Connect containers to testnetwork2
3567 dockerCmd(c, "network", "connect", "testnetwork2", "first")
3568 dockerCmd(c, "network", "connect", "testnetwork2", "second")
3569 // Check connectivity between containers
3570 dockerCmd(c, "exec", "second", "ping", "-c", "1", "first.testnetwork2")
3573 func (s *DockerSuite) TestContainersNetworkIsolation(c *check.C) {
3574 testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm)
3575 // Create 2 networks using bridge driver
3576 dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1")
3577 dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork2")
3578 // Run 1 container in testnetwork1 and another in testnetwork2
3579 dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=first", "busybox", "top")
3580 c.Assert(waitRun("first"), check.IsNil)
3581 dockerCmd(c, "run", "-d", "--net=testnetwork2", "--name=second", "busybox", "top")
3582 c.Assert(waitRun("second"), check.IsNil)
3584 // Check Isolation between containers : ping must fail
3585 _, _, err := dockerCmdWithError("exec", "first", "ping", "-c", "1", "second")
3586 c.Assert(err, check.NotNil)
3587 // Connect first container to testnetwork2
3588 dockerCmd(c, "network", "connect", "testnetwork2", "first")
3589 // ping must succeed now
3590 _, _, err = dockerCmdWithError("exec", "first", "ping", "-c", "1", "second")
3591 c.Assert(err, check.IsNil)
3593 // Disconnect first container from testnetwork2
3594 dockerCmd(c, "network", "disconnect", "testnetwork2", "first")
3595 // ping must fail again
3596 _, _, err = dockerCmdWithError("exec", "first", "ping", "-c", "1", "second")
3597 c.Assert(err, check.NotNil)
3600 func (s *DockerSuite) TestNetworkRmWithActiveContainers(c *check.C) {
3601 testRequires(c, DaemonIsLinux, NotUserNamespace)
3602 // Create 2 networks using bridge driver
3603 dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1")
3604 // Run and connect containers to testnetwork1
3605 dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=first", "busybox", "top")
3606 c.Assert(waitRun("first"), check.IsNil)
3607 dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=second", "busybox", "top")
3608 c.Assert(waitRun("second"), check.IsNil)
3609 // Network delete with active containers must fail
3610 _, _, err := dockerCmdWithError("network", "rm", "testnetwork1")
3611 c.Assert(err, check.NotNil)
3613 dockerCmd(c, "stop", "first")
3614 _, _, err = dockerCmdWithError("network", "rm", "testnetwork1")
3615 c.Assert(err, check.NotNil)
3618 func (s *DockerSuite) TestContainerRestartInMultipleNetworks(c *check.C) {
3619 testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm)
3620 // Create 2 networks using bridge driver
3621 dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1")
3622 dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork2")
3624 // Run and connect containers to testnetwork1
3625 dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=first", "busybox", "top")
3626 c.Assert(waitRun("first"), check.IsNil)
3627 dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=second", "busybox", "top")
3628 c.Assert(waitRun("second"), check.IsNil)
3629 // Check connectivity between containers in testnetwork2
3630 dockerCmd(c, "exec", "first", "ping", "-c", "1", "second.testnetwork1")
3631 // Connect containers to testnetwork2
3632 dockerCmd(c, "network", "connect", "testnetwork2", "first")
3633 dockerCmd(c, "network", "connect", "testnetwork2", "second")
3634 // Check connectivity between containers
3635 dockerCmd(c, "exec", "second", "ping", "-c", "1", "first.testnetwork2")
3637 // Stop second container and test ping failures on both networks
3638 dockerCmd(c, "stop", "second")
3639 _, _, err := dockerCmdWithError("exec", "first", "ping", "-c", "1", "second.testnetwork1")
3640 c.Assert(err, check.NotNil)
3641 _, _, err = dockerCmdWithError("exec", "first", "ping", "-c", "1", "second.testnetwork2")
3642 c.Assert(err, check.NotNil)
3644 // Start second container and connectivity must be restored on both networks
3645 dockerCmd(c, "start", "second")
3646 dockerCmd(c, "exec", "first", "ping", "-c", "1", "second.testnetwork1")
3647 dockerCmd(c, "exec", "second", "ping", "-c", "1", "first.testnetwork2")
3650 func (s *DockerSuite) TestContainerWithConflictingHostNetworks(c *check.C) {
3651 testRequires(c, DaemonIsLinux, NotUserNamespace)
3652 // Run a container with --net=host
3653 dockerCmd(c, "run", "-d", "--net=host", "--name=first", "busybox", "top")
3654 c.Assert(waitRun("first"), check.IsNil)
3656 // Create a network using bridge driver
3657 dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1")
3659 // Connecting to the user defined network must fail
3660 _, _, err := dockerCmdWithError("network", "connect", "testnetwork1", "first")
3661 c.Assert(err, check.NotNil)
3664 func (s *DockerSuite) TestContainerWithConflictingSharedNetwork(c *check.C) {
3665 testRequires(c, DaemonIsLinux)
3666 dockerCmd(c, "run", "-d", "--name=first", "busybox", "top")
3667 c.Assert(waitRun("first"), check.IsNil)
3668 // Run second container in first container's network namespace
3669 dockerCmd(c, "run", "-d", "--net=container:first", "--name=second", "busybox", "top")
3670 c.Assert(waitRun("second"), check.IsNil)
3672 // Create a network using bridge driver
3673 dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1")
3675 // Connecting to the user defined network must fail
3676 out, _, err := dockerCmdWithError("network", "connect", "testnetwork1", "second")
3677 c.Assert(err, check.NotNil)
3678 c.Assert(out, checker.Contains, runconfig.ErrConflictSharedNetwork.Error())
3681 func (s *DockerSuite) TestContainerWithConflictingNoneNetwork(c *check.C) {
3682 testRequires(c, DaemonIsLinux)
3683 dockerCmd(c, "run", "-d", "--net=none", "--name=first", "busybox", "top")
3684 c.Assert(waitRun("first"), check.IsNil)
3686 // Create a network using bridge driver
3687 dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1")
3689 // Connecting to the user defined network must fail
3690 out, _, err := dockerCmdWithError("network", "connect", "testnetwork1", "first")
3691 c.Assert(err, check.NotNil)
3692 c.Assert(out, checker.Contains, runconfig.ErrConflictNoNetwork.Error())
3694 // create a container connected to testnetwork1
3695 dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=second", "busybox", "top")
3696 c.Assert(waitRun("second"), check.IsNil)
3698 // Connect second container to none network. it must fail as well
3699 _, _, err = dockerCmdWithError("network", "connect", "none", "second")
3700 c.Assert(err, check.NotNil)
3703 // #11957 - stdin with no tty does not exit if stdin is not closed even though container exited
3704 func (s *DockerSuite) TestRunStdinBlockedAfterContainerExit(c *check.C) {
3705 cmd := exec.Command(dockerBinary, "run", "-i", "--name=test", "busybox", "true")
3706 in, err := cmd.StdinPipe()
3707 c.Assert(err, check.IsNil)
3709 stdout := bytes.NewBuffer(nil)
3712 c.Assert(cmd.Start(), check.IsNil)
3714 waitChan := make(chan error)
3716 waitChan <- cmd.Wait()
3720 case err := <-waitChan:
3721 c.Assert(err, check.IsNil, check.Commentf(stdout.String()))
3722 case <-time.After(30 * time.Second):
3723 c.Fatal("timeout waiting for command to exit")
3727 func (s *DockerSuite) TestRunWrongCpusetCpusFlagValue(c *check.C) {
3728 // TODO Windows: This needs validation (error out) in the daemon.
3729 testRequires(c, DaemonIsLinux)
3730 out, exitCode, err := dockerCmdWithError("run", "--cpuset-cpus", "1-10,11--", "busybox", "true")
3731 c.Assert(err, check.NotNil)
3732 expected := "Error response from daemon: Invalid value 1-10,11-- for cpuset cpus.\n"
3733 if !(strings.Contains(out, expected) || exitCode == 125) {
3734 c.Fatalf("Expected output to contain %q with exitCode 125, got out: %q exitCode: %v", expected, out, exitCode)
3738 func (s *DockerSuite) TestRunWrongCpusetMemsFlagValue(c *check.C) {
3739 // TODO Windows: This needs validation (error out) in the daemon.
3740 testRequires(c, DaemonIsLinux)
3741 out, exitCode, err := dockerCmdWithError("run", "--cpuset-mems", "1-42--", "busybox", "true")
3742 c.Assert(err, check.NotNil)
3743 expected := "Error response from daemon: Invalid value 1-42-- for cpuset mems.\n"
3744 if !(strings.Contains(out, expected) || exitCode == 125) {
3745 c.Fatalf("Expected output to contain %q with exitCode 125, got out: %q exitCode: %v", expected, out, exitCode)
3749 // TestRunNonExecutableCmd checks that 'docker run busybox foo' exits with error code 127'
3750 func (s *DockerSuite) TestRunNonExecutableCmd(c *check.C) {
3751 name := "testNonExecutableCmd"
3752 icmd.RunCommand(dockerBinary, "run", "--name", name, "busybox", "foo").Assert(c, icmd.Expected{
3754 Error: "exit status 127",
3758 // TestRunNonExistingCmd checks that 'docker run busybox /bin/foo' exits with code 127.
3759 func (s *DockerSuite) TestRunNonExistingCmd(c *check.C) {
3760 name := "testNonExistingCmd"
3761 icmd.RunCommand(dockerBinary, "run", "--name", name, "busybox", "/bin/foo").Assert(c, icmd.Expected{
3763 Error: "exit status 127",
3767 // TestCmdCannotBeInvoked checks that 'docker run busybox /etc' exits with 126, or
3768 // 127 on Windows. The difference is that in Windows, the container must be started
3769 // as that's when the check is made (and yes, by its design...)
3770 func (s *DockerSuite) TestCmdCannotBeInvoked(c *check.C) {
3772 if testEnv.DaemonPlatform() == "windows" {
3775 name := "testCmdCannotBeInvoked"
3776 icmd.RunCommand(dockerBinary, "run", "--name", name, "busybox", "/etc").Assert(c, icmd.Expected{
3778 Error: fmt.Sprintf("exit status %d", expected),
3782 // TestRunNonExistingImage checks that 'docker run foo' exits with error msg 125 and contains 'Unable to find image'
3783 // FIXME(vdemeester) should be a unit test
3784 func (s *DockerSuite) TestRunNonExistingImage(c *check.C) {
3785 icmd.RunCommand(dockerBinary, "run", "foo").Assert(c, icmd.Expected{
3787 Err: "Unable to find image",
3791 // TestDockerFails checks that 'docker run -foo busybox' exits with 125 to signal docker run failed
3792 // FIXME(vdemeester) should be a unit test
3793 func (s *DockerSuite) TestDockerFails(c *check.C) {
3794 icmd.RunCommand(dockerBinary, "run", "-foo", "busybox").Assert(c, icmd.Expected{
3796 Error: "exit status 125",
3800 // TestRunInvalidReference invokes docker run with a bad reference.
3801 func (s *DockerSuite) TestRunInvalidReference(c *check.C) {
3802 out, exit, _ := dockerCmdWithError("run", "busybox@foo")
3804 c.Fatalf("expected non-zero exist code; received %d", exit)
3807 if !strings.Contains(out, "invalid reference format") {
3808 c.Fatalf(`Expected "invalid reference format" in output; got: %s`, out)
3812 // Test fix for issue #17854
3813 func (s *DockerSuite) TestRunInitLayerPathOwnership(c *check.C) {
3814 // Not applicable on Windows as it does not support Linux uid/gid ownership
3815 testRequires(c, DaemonIsLinux)
3816 name := "testetcfileownership"
3817 buildImageSuccessfully(c, name, build.WithDockerfile(`FROM busybox
3818 RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
3819 RUN echo 'dockerio:x:1001:' >> /etc/group
3820 RUN chown dockerio:dockerio /etc`))
3822 // Test that dockerio ownership of /etc is retained at runtime
3823 out, _ := dockerCmd(c, "run", "--rm", name, "stat", "-c", "%U:%G", "/etc")
3824 out = strings.TrimSpace(out)
3825 if out != "dockerio:dockerio" {
3826 c.Fatalf("Wrong /etc ownership: expected dockerio:dockerio, got %q", out)
3830 func (s *DockerSuite) TestRunWithOomScoreAdj(c *check.C) {
3831 testRequires(c, DaemonIsLinux)
3834 out, _ := dockerCmd(c, "run", "--oom-score-adj", expected, "busybox", "cat", "/proc/self/oom_score_adj")
3835 oomScoreAdj := strings.TrimSpace(out)
3836 if oomScoreAdj != "642" {
3837 c.Fatalf("Expected oom_score_adj set to %q, got %q instead", expected, oomScoreAdj)
3841 func (s *DockerSuite) TestRunWithOomScoreAdjInvalidRange(c *check.C) {
3842 testRequires(c, DaemonIsLinux)
3844 out, _, err := dockerCmdWithError("run", "--oom-score-adj", "1001", "busybox", "true")
3845 c.Assert(err, check.NotNil)
3846 expected := "Invalid value 1001, range for oom score adj is [-1000, 1000]."
3847 if !strings.Contains(out, expected) {
3848 c.Fatalf("Expected output to contain %q, got %q instead", expected, out)
3850 out, _, err = dockerCmdWithError("run", "--oom-score-adj", "-1001", "busybox", "true")
3851 c.Assert(err, check.NotNil)
3852 expected = "Invalid value -1001, range for oom score adj is [-1000, 1000]."
3853 if !strings.Contains(out, expected) {
3854 c.Fatalf("Expected output to contain %q, got %q instead", expected, out)
3858 func (s *DockerSuite) TestRunVolumesMountedAsShared(c *check.C) {
3859 // Volume propagation is linux only. Also it creates directories for
3860 // bind mounting, so needs to be same host.
3861 testRequires(c, DaemonIsLinux, SameHostDaemon, NotUserNamespace)
3863 // Prepare a source directory to bind mount
3864 tmpDir, err := ioutil.TempDir("", "volume-source")
3868 defer os.RemoveAll(tmpDir)
3870 if err := os.Mkdir(path.Join(tmpDir, "mnt1"), 0755); err != nil {
3874 // Convert this directory into a shared mount point so that we do
3875 // not rely on propagation properties of parent mount.
3876 icmd.RunCommand("mount", "--bind", tmpDir, tmpDir).Assert(c, icmd.Success)
3877 icmd.RunCommand("mount", "--make-private", "--make-shared", tmpDir).Assert(c, icmd.Success)
3879 dockerCmd(c, "run", "--privileged", "-v", fmt.Sprintf("%s:/volume-dest:shared", tmpDir), "busybox", "mount", "--bind", "/volume-dest/mnt1", "/volume-dest/mnt1")
3881 // Make sure a bind mount under a shared volume propagated to host.
3882 if mounted, _ := mount.Mounted(path.Join(tmpDir, "mnt1")); !mounted {
3883 c.Fatalf("Bind mount under shared volume did not propagate to host")
3886 mount.Unmount(path.Join(tmpDir, "mnt1"))
3889 func (s *DockerSuite) TestRunVolumesMountedAsSlave(c *check.C) {
3890 // Volume propagation is linux only. Also it creates directories for
3891 // bind mounting, so needs to be same host.
3892 testRequires(c, DaemonIsLinux, SameHostDaemon, NotUserNamespace)
3894 // Prepare a source directory to bind mount
3895 tmpDir, err := ioutil.TempDir("", "volume-source")
3899 defer os.RemoveAll(tmpDir)
3901 if err := os.Mkdir(path.Join(tmpDir, "mnt1"), 0755); err != nil {
3905 // Prepare a source directory with file in it. We will bind mount this
3906 // directory and see if file shows up.
3907 tmpDir2, err := ioutil.TempDir("", "volume-source2")
3911 defer os.RemoveAll(tmpDir2)
3913 if err := ioutil.WriteFile(path.Join(tmpDir2, "slave-testfile"), []byte("Test"), 0644); err != nil {
3917 // Convert this directory into a shared mount point so that we do
3918 // not rely on propagation properties of parent mount.
3919 icmd.RunCommand("mount", "--bind", tmpDir, tmpDir).Assert(c, icmd.Success)
3920 icmd.RunCommand("mount", "--make-private", "--make-shared", tmpDir).Assert(c, icmd.Success)
3922 dockerCmd(c, "run", "-i", "-d", "--name", "parent", "-v", fmt.Sprintf("%s:/volume-dest:slave", tmpDir), "busybox", "top")
3924 // Bind mount tmpDir2/ onto tmpDir/mnt1. If mount propagates inside
3925 // container then contents of tmpDir2/slave-testfile should become
3926 // visible at "/volume-dest/mnt1/slave-testfile"
3927 icmd.RunCommand("mount", "--bind", tmpDir2, path.Join(tmpDir, "mnt1")).Assert(c, icmd.Success)
3929 out, _ := dockerCmd(c, "exec", "parent", "cat", "/volume-dest/mnt1/slave-testfile")
3931 mount.Unmount(path.Join(tmpDir, "mnt1"))
3934 c.Fatalf("Bind mount under slave volume did not propagate to container")
3938 func (s *DockerSuite) TestRunNamedVolumesMountedAsShared(c *check.C) {
3939 testRequires(c, DaemonIsLinux, NotUserNamespace)
3940 out, exitCode, _ := dockerCmdWithError("run", "-v", "foo:/test:shared", "busybox", "touch", "/test/somefile")
3941 c.Assert(exitCode, checker.Not(checker.Equals), 0)
3942 c.Assert(out, checker.Contains, "invalid mount config")
3945 func (s *DockerSuite) TestRunNamedVolumeCopyImageData(c *check.C) {
3946 testRequires(c, DaemonIsLinux)
3948 testImg := "testvolumecopy"
3949 buildImageSuccessfully(c, testImg, build.WithDockerfile(`
3951 RUN mkdir -p /foo && echo hello > /foo/hello
3954 dockerCmd(c, "run", "-v", "foo:/foo", testImg)
3955 out, _ := dockerCmd(c, "run", "-v", "foo:/foo", "busybox", "cat", "/foo/hello")
3956 c.Assert(strings.TrimSpace(out), check.Equals, "hello")
3959 func (s *DockerSuite) TestRunNamedVolumeNotRemoved(c *check.C) {
3960 prefix, _ := getPrefixAndSlashFromDaemonPlatform()
3962 dockerCmd(c, "volume", "create", "test")
3964 dockerCmd(c, "run", "--rm", "-v", "test:"+prefix+"/foo", "-v", prefix+"/bar", "busybox", "true")
3965 dockerCmd(c, "volume", "inspect", "test")
3966 out, _ := dockerCmd(c, "volume", "ls", "-q")
3967 c.Assert(strings.TrimSpace(out), checker.Equals, "test")
3969 dockerCmd(c, "run", "--name=test", "-v", "test:"+prefix+"/foo", "-v", prefix+"/bar", "busybox", "true")
3970 dockerCmd(c, "rm", "-fv", "test")
3971 dockerCmd(c, "volume", "inspect", "test")
3972 out, _ = dockerCmd(c, "volume", "ls", "-q")
3973 c.Assert(strings.TrimSpace(out), checker.Equals, "test")
3976 func (s *DockerSuite) TestRunNamedVolumesFromNotRemoved(c *check.C) {
3977 prefix, _ := getPrefixAndSlashFromDaemonPlatform()
3979 dockerCmd(c, "volume", "create", "test")
3980 dockerCmd(c, "run", "--name=parent", "-v", "test:"+prefix+"/foo", "-v", prefix+"/bar", "busybox", "true")
3981 dockerCmd(c, "run", "--name=child", "--volumes-from=parent", "busybox", "true")
3983 // Remove the parent so there are not other references to the volumes
3984 dockerCmd(c, "rm", "-f", "parent")
3985 // now remove the child and ensure the named volume (and only the named volume) still exists
3986 dockerCmd(c, "rm", "-fv", "child")
3987 dockerCmd(c, "volume", "inspect", "test")
3988 out, _ := dockerCmd(c, "volume", "ls", "-q")
3989 c.Assert(strings.TrimSpace(out), checker.Equals, "test")
3992 func (s *DockerSuite) TestRunAttachFailedNoLeak(c *check.C) {
3993 nroutines, err := getGoroutineNumber()
3994 c.Assert(err, checker.IsNil)
3996 runSleepingContainer(c, "--name=test", "-p", "8000:8000")
3998 // Wait until container is fully up and running
3999 c.Assert(waitRun("test"), check.IsNil)
4001 out, _, err := dockerCmdWithError("run", "--name=fail", "-p", "8000:8000", "busybox", "true")
4002 // We will need the following `inspect` to diagnose the issue if test fails (#21247)
4003 out1, err1 := dockerCmd(c, "inspect", "--format", "{{json .State}}", "test")
4004 out2, err2 := dockerCmd(c, "inspect", "--format", "{{json .State}}", "fail")
4005 c.Assert(err, checker.NotNil, check.Commentf("Command should have failed but succeeded with: %s\nContainer 'test' [%+v]: %s\nContainer 'fail' [%+v]: %s", out, err1, out1, err2, out2))
4006 // check for windows error as well
4007 // TODO Windows Post TP5. Fix the error message string
4008 c.Assert(strings.Contains(string(out), "port is already allocated") ||
4009 strings.Contains(string(out), "were not connected because a duplicate name exists") ||
4010 strings.Contains(string(out), "HNS failed with error : Failed to create endpoint") ||
4011 strings.Contains(string(out), "HNS failed with error : The object already exists"), checker.Equals, true, check.Commentf("Output: %s", out))
4012 dockerCmd(c, "rm", "-f", "test")
4014 // NGoroutines is not updated right away, so we need to wait before failing
4015 c.Assert(waitForGoroutines(nroutines), checker.IsNil)
4018 // Test for one character directory name case (#20122)
4019 func (s *DockerSuite) TestRunVolumeWithOneCharacter(c *check.C) {
4020 testRequires(c, DaemonIsLinux)
4022 out, _ := dockerCmd(c, "run", "-v", "/tmp/q:/foo", "busybox", "sh", "-c", "find /foo")
4023 c.Assert(strings.TrimSpace(out), checker.Equals, "/foo")
4026 func (s *DockerSuite) TestRunVolumeCopyFlag(c *check.C) {
4027 testRequires(c, DaemonIsLinux) // Windows does not support copying data from image to the volume
4028 buildImageSuccessfully(c, "volumecopy", build.WithDockerfile(`FROM busybox
4029 RUN mkdir /foo && echo hello > /foo/bar
4031 dockerCmd(c, "volume", "create", "test")
4033 // test with the nocopy flag
4034 out, _, err := dockerCmdWithError("run", "-v", "test:/foo:nocopy", "volumecopy")
4035 c.Assert(err, checker.NotNil, check.Commentf(out))
4036 // test default behavior which is to copy for non-binds
4037 out, _ = dockerCmd(c, "run", "-v", "test:/foo", "volumecopy")
4038 c.Assert(strings.TrimSpace(out), checker.Equals, "hello")
4039 // error out when the volume is already populated
4040 out, _, err = dockerCmdWithError("run", "-v", "test:/foo:copy", "volumecopy")
4041 c.Assert(err, checker.NotNil, check.Commentf(out))
4042 // do not error out when copy isn't explicitly set even though it's already populated
4043 out, _ = dockerCmd(c, "run", "-v", "test:/foo", "volumecopy")
4044 c.Assert(strings.TrimSpace(out), checker.Equals, "hello")
4046 // do not allow copy modes on volumes-from
4047 dockerCmd(c, "run", "--name=test", "-v", "/foo", "busybox", "true")
4048 out, _, err = dockerCmdWithError("run", "--volumes-from=test:copy", "busybox", "true")
4049 c.Assert(err, checker.NotNil, check.Commentf(out))
4050 out, _, err = dockerCmdWithError("run", "--volumes-from=test:nocopy", "busybox", "true")
4051 c.Assert(err, checker.NotNil, check.Commentf(out))
4053 // do not allow copy modes on binds
4054 out, _, err = dockerCmdWithError("run", "-v", "/foo:/bar:copy", "busybox", "true")
4055 c.Assert(err, checker.NotNil, check.Commentf(out))
4056 out, _, err = dockerCmdWithError("run", "-v", "/foo:/bar:nocopy", "busybox", "true")
4057 c.Assert(err, checker.NotNil, check.Commentf(out))
4060 // Test case for #21976
4061 func (s *DockerSuite) TestRunDNSInHostMode(c *check.C) {
4062 testRequires(c, DaemonIsLinux, NotUserNamespace)
4064 expectedOutput := "nameserver 127.0.0.1"
4065 expectedWarning := "Localhost DNS setting"
4066 cli.DockerCmd(c, "run", "--dns=127.0.0.1", "--net=host", "busybox", "cat", "/etc/resolv.conf").Assert(c, icmd.Expected{
4067 Out: expectedOutput,
4068 Err: expectedWarning,
4071 expectedOutput = "nameserver 1.2.3.4"
4072 cli.DockerCmd(c, "run", "--dns=1.2.3.4", "--net=host", "busybox", "cat", "/etc/resolv.conf").Assert(c, icmd.Expected{
4073 Out: expectedOutput,
4076 expectedOutput = "search example.com"
4077 cli.DockerCmd(c, "run", "--dns-search=example.com", "--net=host", "busybox", "cat", "/etc/resolv.conf").Assert(c, icmd.Expected{
4078 Out: expectedOutput,
4081 expectedOutput = "options timeout:3"
4082 cli.DockerCmd(c, "run", "--dns-opt=timeout:3", "--net=host", "busybox", "cat", "/etc/resolv.conf").Assert(c, icmd.Expected{
4083 Out: expectedOutput,
4086 expectedOutput1 := "nameserver 1.2.3.4"
4087 expectedOutput2 := "search example.com"
4088 expectedOutput3 := "options timeout:3"
4089 out := cli.DockerCmd(c, "run", "--dns=1.2.3.4", "--dns-search=example.com", "--dns-opt=timeout:3", "--net=host", "busybox", "cat", "/etc/resolv.conf").Combined()
4090 c.Assert(out, checker.Contains, expectedOutput1, check.Commentf("Expected '%s', but got %q", expectedOutput1, out))
4091 c.Assert(out, checker.Contains, expectedOutput2, check.Commentf("Expected '%s', but got %q", expectedOutput2, out))
4092 c.Assert(out, checker.Contains, expectedOutput3, check.Commentf("Expected '%s', but got %q", expectedOutput3, out))
4095 // Test case for #21976
4096 func (s *DockerSuite) TestRunAddHostInHostMode(c *check.C) {
4097 testRequires(c, DaemonIsLinux, NotUserNamespace)
4099 expectedOutput := "1.2.3.4\textra"
4100 out, _ := dockerCmd(c, "run", "--add-host=extra:1.2.3.4", "--net=host", "busybox", "cat", "/etc/hosts")
4101 c.Assert(out, checker.Contains, expectedOutput, check.Commentf("Expected '%s', but got %q", expectedOutput, out))
4104 func (s *DockerSuite) TestRunRmAndWait(c *check.C) {
4105 dockerCmd(c, "run", "--name=test", "--rm", "-d", "busybox", "sh", "-c", "sleep 3;exit 2")
4107 out, code, err := dockerCmdWithError("wait", "test")
4108 c.Assert(err, checker.IsNil, check.Commentf("out: %s; exit code: %d", out, code))
4109 c.Assert(out, checker.Equals, "2\n", check.Commentf("exit code: %d", code))
4110 c.Assert(code, checker.Equals, 0)
4113 // Test that auto-remove is performed by the daemon (API 1.25 and above)
4114 func (s *DockerSuite) TestRunRm(c *check.C) {
4115 name := "miss-me-when-im-gone"
4116 cli.DockerCmd(c, "run", "--name="+name, "--rm", "busybox")
4118 cli.Docker(cli.Inspect(name), cli.Format(".name")).Assert(c, icmd.Expected{
4120 Err: "No such object: " + name,
4124 // Test that auto-remove is performed by the client on API versions that do not support daemon-side api-remove (API < 1.25)
4125 func (s *DockerSuite) TestRunRmPre125Api(c *check.C) {
4126 name := "miss-me-when-im-gone"
4127 envs := appendBaseEnv(false, "DOCKER_API_VERSION=1.24")
4128 cli.Docker(cli.Args("run", "--name="+name, "--rm", "busybox"), cli.WithEnvironmentVariables(envs...)).Assert(c, icmd.Success)
4130 cli.Docker(cli.Inspect(name), cli.Format(".name")).Assert(c, icmd.Expected{
4132 Err: "No such object: " + name,
4136 // Test case for #23498
4137 func (s *DockerSuite) TestRunUnsetEntrypoint(c *check.C) {
4138 testRequires(c, DaemonIsLinux)
4139 name := "test-entrypoint"
4140 dockerfile := `FROM busybox
4141 ADD entrypoint.sh /entrypoint.sh
4142 RUN chmod 755 /entrypoint.sh
4143 ENTRYPOINT ["/entrypoint.sh"]
4146 ctx := fakecontext.New(c, "",
4147 fakecontext.WithDockerfile(dockerfile),
4148 fakecontext.WithFiles(map[string]string{
4149 "entrypoint.sh": `#!/bin/sh
4150 echo "I am an entrypoint"
4155 cli.BuildCmd(c, name, build.WithExternalBuildContext(ctx))
4157 out := cli.DockerCmd(c, "run", "--entrypoint=", "-t", name, "echo", "foo").Combined()
4158 c.Assert(strings.TrimSpace(out), check.Equals, "foo")
4160 // CMD will be reset as well (the same as setting a custom entrypoint)
4161 cli.Docker(cli.Args("run", "--entrypoint=", "-t", name)).Assert(c, icmd.Expected{
4163 Err: "No command specified",
4167 func (s *DockerDaemonSuite) TestRunWithUlimitAndDaemonDefault(c *check.C) {
4168 s.d.StartWithBusybox(c, "--debug", "--default-ulimit=nofile=65535")
4171 _, err := s.d.Cmd("run", "--name", name, "-d", "busybox", "top")
4172 c.Assert(err, checker.IsNil)
4173 c.Assert(s.d.WaitRun(name), check.IsNil)
4175 out, err := s.d.Cmd("inspect", "--format", "{{.HostConfig.Ulimits}}", name)
4176 c.Assert(err, checker.IsNil)
4177 c.Assert(out, checker.Contains, "[nofile=65535:65535]")
4180 _, err = s.d.Cmd("run", "--name", name, "--ulimit=nofile=42", "-d", "busybox", "top")
4181 c.Assert(err, checker.IsNil)
4182 c.Assert(s.d.WaitRun(name), check.IsNil)
4184 out, err = s.d.Cmd("inspect", "--format", "{{.HostConfig.Ulimits}}", name)
4185 c.Assert(err, checker.IsNil)
4186 c.Assert(out, checker.Contains, "[nofile=42:42]")
4189 func (s *DockerSuite) TestRunStoppedLoggingDriverNoLeak(c *check.C) {
4190 c.Skip("Splunk log-driver isn't supported")
4192 nroutines, err := getGoroutineNumber()
4193 c.Assert(err, checker.IsNil)
4195 out, _, err := dockerCmdWithError("run", "--name=fail", "--log-driver=splunk", "busybox", "true")
4196 c.Assert(err, checker.NotNil)
4197 c.Assert(out, checker.Contains, "failed to initialize logging driver", check.Commentf("error should be about logging driver, got output %s", out))
4199 // NGoroutines is not updated right away, so we need to wait before failing
4200 c.Assert(waitForGoroutines(nroutines), checker.IsNil)
4203 // Handles error conditions for --credentialspec. Validating E2E success cases
4204 // requires additional infrastructure (AD for example) on CI servers.
4205 func (s *DockerSuite) TestRunCredentialSpecFailures(c *check.C) {
4206 testRequires(c, DaemonIsWindows)
4207 attempts := []struct{ value, expectedError string }{
4208 {"rubbish", "invalid credential spec security option - value must be prefixed file:// or registry://"},
4209 {"rubbish://", "invalid credential spec security option - value must be prefixed file:// or registry://"},
4210 {"file://", "no value supplied for file:// credential spec security option"},
4211 {"registry://", "no value supplied for registry:// credential spec security option"},
4212 {`file://c:\blah.txt`, "path cannot be absolute"},
4213 {`file://doesnotexist.txt`, "The system cannot find the file specified"},
4215 for _, attempt := range attempts {
4216 _, _, err := dockerCmdWithError("run", "--security-opt=credentialspec="+attempt.value, "busybox", "true")
4217 c.Assert(err, checker.NotNil, check.Commentf("%s expected non-nil err", attempt.value))
4218 c.Assert(err.Error(), checker.Contains, attempt.expectedError, check.Commentf("%s expected %s got %s", attempt.value, attempt.expectedError, err))
4222 // Windows specific test to validate credential specs with a well-formed spec.
4223 // Note it won't actually do anything in CI configuration with the spec, but
4224 // it should not fail to run a container.
4225 func (s *DockerSuite) TestRunCredentialSpecWellFormed(c *check.C) {
4226 testRequires(c, DaemonIsWindows, SameHostDaemon)
4227 validCS := readFile(`fixtures\credentialspecs\valid.json`, c)
4228 writeFile(filepath.Join(testEnv.DockerBasePath(), `credentialspecs\valid.json`), validCS, c)
4229 dockerCmd(c, "run", `--security-opt=credentialspec=file://valid.json`, "busybox", "true")
4232 // Windows specific test to ensure that a servicing app container is started
4233 // if necessary once a container exits. It does this by forcing a no-op
4234 // servicing event and verifying the event from Hyper-V-Compute
4235 func (s *DockerSuite) TestRunServicingContainer(c *check.C) {
4236 testRequires(c, DaemonIsWindows, SameHostDaemon)
4238 out := cli.DockerCmd(c, "run", "-d", testEnv.MinimalBaseImage(), "cmd", "/c", "mkdir c:\\programdata\\Microsoft\\Windows\\ContainerUpdates\\000_000_d99f45d0-ffc8-4af7-bd9c-ea6a62e035c9_200 && sc control cexecsvc 255").Combined()
4239 containerID := strings.TrimSpace(out)
4240 cli.WaitExited(c, containerID, 60*time.Second)
4242 result := icmd.RunCommand("powershell", "echo", `(Get-WinEvent -ProviderName "Microsoft-Windows-Hyper-V-Compute" -FilterXPath 'Event[System[EventID=2010]]' -MaxEvents 1).Message`)
4243 result.Assert(c, icmd.Success)
4244 out2 := result.Combined()
4245 c.Assert(out2, checker.Contains, `"Servicing":true`, check.Commentf("Servicing container does not appear to have been started: %s", out2))
4246 c.Assert(out2, checker.Contains, `Windows Container (Servicing)`, check.Commentf("Didn't find 'Windows Container (Servicing): %s", out2))
4247 c.Assert(out2, checker.Contains, containerID+"_servicing", check.Commentf("Didn't find '%s_servicing': %s", containerID+"_servicing", out2))
4250 func (s *DockerSuite) TestRunDuplicateMount(c *check.C) {
4251 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
4253 tmpFile, err := ioutil.TempFile("", "touch-me")
4254 c.Assert(err, checker.IsNil)
4255 defer tmpFile.Close()
4257 data := "touch-me-foo-bar\n"
4258 if _, err := tmpFile.Write([]byte(data)); err != nil {
4263 out, _ := dockerCmd(c, "run", "--name", name, "-v", "/tmp:/tmp", "-v", "/tmp:/tmp", "busybox", "sh", "-c", "cat "+tmpFile.Name()+" && ls /")
4264 c.Assert(out, checker.Not(checker.Contains), "tmp:")
4265 c.Assert(out, checker.Contains, data)
4267 out = inspectFieldJSON(c, name, "Config.Volumes")
4268 c.Assert(out, checker.Contains, "null")
4271 func (s *DockerSuite) TestRunWindowsWithCPUCount(c *check.C) {
4272 testRequires(c, DaemonIsWindows)
4274 out, _ := dockerCmd(c, "run", "--cpu-count=1", "--name", "test", "busybox", "echo", "testing")
4275 c.Assert(strings.TrimSpace(out), checker.Equals, "testing")
4277 out = inspectField(c, "test", "HostConfig.CPUCount")
4278 c.Assert(out, check.Equals, "1")
4281 func (s *DockerSuite) TestRunWindowsWithCPUShares(c *check.C) {
4282 testRequires(c, DaemonIsWindows)
4284 out, _ := dockerCmd(c, "run", "--cpu-shares=1000", "--name", "test", "busybox", "echo", "testing")
4285 c.Assert(strings.TrimSpace(out), checker.Equals, "testing")
4287 out = inspectField(c, "test", "HostConfig.CPUShares")
4288 c.Assert(out, check.Equals, "1000")
4291 func (s *DockerSuite) TestRunWindowsWithCPUPercent(c *check.C) {
4292 testRequires(c, DaemonIsWindows)
4294 out, _ := dockerCmd(c, "run", "--cpu-percent=80", "--name", "test", "busybox", "echo", "testing")
4295 c.Assert(strings.TrimSpace(out), checker.Equals, "testing")
4297 out = inspectField(c, "test", "HostConfig.CPUPercent")
4298 c.Assert(out, check.Equals, "80")
4301 func (s *DockerSuite) TestRunProcessIsolationWithCPUCountCPUSharesAndCPUPercent(c *check.C) {
4302 testRequires(c, DaemonIsWindows, IsolationIsProcess)
4304 out, _ := dockerCmd(c, "run", "--cpu-count=1", "--cpu-shares=1000", "--cpu-percent=80", "--name", "test", "busybox", "echo", "testing")
4305 c.Assert(strings.TrimSpace(out), checker.Contains, "WARNING: Conflicting options: CPU count takes priority over CPU shares on Windows Server Containers. CPU shares discarded")
4306 c.Assert(strings.TrimSpace(out), checker.Contains, "WARNING: Conflicting options: CPU count takes priority over CPU percent on Windows Server Containers. CPU percent discarded")
4307 c.Assert(strings.TrimSpace(out), checker.Contains, "testing")
4309 out = inspectField(c, "test", "HostConfig.CPUCount")
4310 c.Assert(out, check.Equals, "1")
4312 out = inspectField(c, "test", "HostConfig.CPUShares")
4313 c.Assert(out, check.Equals, "0")
4315 out = inspectField(c, "test", "HostConfig.CPUPercent")
4316 c.Assert(out, check.Equals, "0")
4319 func (s *DockerSuite) TestRunHypervIsolationWithCPUCountCPUSharesAndCPUPercent(c *check.C) {
4320 testRequires(c, DaemonIsWindows, IsolationIsHyperv)
4322 out, _ := dockerCmd(c, "run", "--cpu-count=1", "--cpu-shares=1000", "--cpu-percent=80", "--name", "test", "busybox", "echo", "testing")
4323 c.Assert(strings.TrimSpace(out), checker.Contains, "testing")
4325 out = inspectField(c, "test", "HostConfig.CPUCount")
4326 c.Assert(out, check.Equals, "1")
4328 out = inspectField(c, "test", "HostConfig.CPUShares")
4329 c.Assert(out, check.Equals, "1000")
4331 out = inspectField(c, "test", "HostConfig.CPUPercent")
4332 c.Assert(out, check.Equals, "80")
4336 func (s *DockerSuite) TestRunEmptyEnv(c *check.C) {
4337 testRequires(c, DaemonIsLinux)
4339 expectedOutput := "invalid environment variable:"
4341 out, _, err := dockerCmdWithError("run", "-e", "", "busybox", "true")
4342 c.Assert(err, checker.NotNil)
4343 c.Assert(out, checker.Contains, expectedOutput)
4345 out, _, err = dockerCmdWithError("run", "-e", "=", "busybox", "true")
4346 c.Assert(err, checker.NotNil)
4347 c.Assert(out, checker.Contains, expectedOutput)
4349 out, _, err = dockerCmdWithError("run", "-e", "=foo", "busybox", "true")
4350 c.Assert(err, checker.NotNil)
4351 c.Assert(out, checker.Contains, expectedOutput)
4355 func (s *DockerSuite) TestSlowStdinClosing(c *check.C) {
4356 name := "testslowstdinclosing"
4357 repeat := 3 // regression happened 50% of the time
4358 for i := 0; i < repeat; i++ {
4360 Command: []string{dockerBinary, "run", "--rm", "--name", name, "-i", "busybox", "cat"},
4361 Stdin: &delayedReader{},
4363 done := make(chan error, 1)
4365 err := icmd.RunCmd(cmd).Error
4370 case <-time.After(15 * time.Second):
4371 c.Fatal("running container timed out") // cleanup in teardown
4373 c.Assert(err, checker.IsNil)
4378 type delayedReader struct{}
4380 func (s *delayedReader) Read([]byte) (int, error) {
4381 time.Sleep(500 * time.Millisecond)
4385 // #28823 (originally #28639)
4386 func (s *DockerSuite) TestRunMountReadOnlyDevShm(c *check.C) {
4387 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
4388 emptyDir, err := ioutil.TempDir("", "test-read-only-dev-shm")
4389 c.Assert(err, check.IsNil)
4390 defer os.RemoveAll(emptyDir)
4391 out, _, err := dockerCmdWithError("run", "--rm", "--read-only",
4392 "-v", fmt.Sprintf("%s:/dev/shm:ro", emptyDir),
4393 "busybox", "touch", "/dev/shm/foo")
4394 c.Assert(err, checker.NotNil, check.Commentf(out))
4395 c.Assert(out, checker.Contains, "Read-only file system")
4398 func (s *DockerSuite) TestRunMount(c *check.C) {
4399 testRequires(c, DaemonIsLinux, SameHostDaemon, NotUserNamespace)
4401 // mnt1, mnt2, and testCatFooBar are commonly used in multiple test cases
4402 tmpDir, err := ioutil.TempDir("", "mount")
4406 defer os.RemoveAll(tmpDir)
4407 mnt1, mnt2 := path.Join(tmpDir, "mnt1"), path.Join(tmpDir, "mnt2")
4408 if err := os.Mkdir(mnt1, 0755); err != nil {
4411 if err := os.Mkdir(mnt2, 0755); err != nil {
4414 if err := ioutil.WriteFile(path.Join(mnt1, "test1"), []byte("test1"), 0644); err != nil {
4417 if err := ioutil.WriteFile(path.Join(mnt2, "test2"), []byte("test2"), 0644); err != nil {
4420 testCatFooBar := func(cName string) error {
4421 out, _ := dockerCmd(c, "exec", cName, "cat", "/foo/test1")
4423 return fmt.Errorf("%s not mounted on /foo", mnt1)
4425 out, _ = dockerCmd(c, "exec", cName, "cat", "/bar/test2")
4427 return fmt.Errorf("%s not mounted on /bar", mnt2)
4432 type testCase struct {
4433 equivalents [][]string
4435 // fn should be nil if valid==false
4436 fn func(cName string) error
4438 cases := []testCase{
4440 equivalents: [][]string{
4442 "--mount", fmt.Sprintf("type=bind,src=%s,dst=/foo", mnt1),
4443 "--mount", fmt.Sprintf("type=bind,src=%s,dst=/bar", mnt2),
4446 "--mount", fmt.Sprintf("type=bind,src=%s,dst=/foo", mnt1),
4447 "--mount", fmt.Sprintf("type=bind,src=%s,target=/bar", mnt2),
4450 "--volume", mnt1 + ":/foo",
4451 "--mount", fmt.Sprintf("type=bind,src=%s,target=/bar", mnt2),
4458 equivalents: [][]string{
4460 "--mount", fmt.Sprintf("type=volume,src=%s,dst=/foo", mnt1),
4461 "--mount", fmt.Sprintf("type=volume,src=%s,dst=/bar", mnt2),
4464 "--mount", fmt.Sprintf("type=volume,src=%s,dst=/foo", mnt1),
4465 "--mount", fmt.Sprintf("type=volume,src=%s,target=/bar", mnt2),
4471 equivalents: [][]string{
4473 "--mount", fmt.Sprintf("type=bind,src=%s,dst=/foo", mnt1),
4474 "--mount", fmt.Sprintf("type=volume,src=%s,dst=/bar", mnt2),
4477 "--volume", mnt1 + ":/foo",
4478 "--mount", fmt.Sprintf("type=volume,src=%s,target=/bar", mnt2),
4485 equivalents: [][]string{
4488 "--mount", "type=volume,dst=/bar",
4492 fn: func(cName string) error {
4493 _, _, err := dockerCmdWithError("exec", cName, "touch", "/bar/icanwritehere")
4498 equivalents: [][]string{
4501 "--mount", fmt.Sprintf("type=bind,src=%s,dst=/foo", mnt1),
4502 "--mount", "type=volume,dst=/bar",
4506 "--volume", fmt.Sprintf("%s:/foo", mnt1),
4507 "--mount", "type=volume,dst=/bar",
4511 fn: func(cName string) error {
4512 out, _ := dockerCmd(c, "exec", cName, "cat", "/foo/test1")
4514 return fmt.Errorf("%s not mounted on /foo", mnt1)
4516 _, _, err := dockerCmdWithError("exec", cName, "touch", "/bar/icanwritehere")
4521 equivalents: [][]string{
4523 "--mount", fmt.Sprintf("type=bind,src=%s,dst=/foo", mnt1),
4524 "--mount", fmt.Sprintf("type=bind,src=%s,dst=/foo", mnt2),
4527 "--mount", fmt.Sprintf("type=bind,src=%s,dst=/foo", mnt1),
4528 "--mount", fmt.Sprintf("type=bind,src=%s,target=/foo", mnt2),
4531 "--volume", fmt.Sprintf("%s:/foo", mnt1),
4532 "--mount", fmt.Sprintf("type=bind,src=%s,target=/foo", mnt2),
4538 equivalents: [][]string{
4540 "--volume", fmt.Sprintf("%s:/foo", mnt1),
4541 "--mount", fmt.Sprintf("type=volume,src=%s,target=/foo", mnt2),
4547 equivalents: [][]string{
4549 "--mount", "type=volume,target=/foo",
4550 "--mount", "type=volume,target=/foo",
4557 for i, testCase := range cases {
4558 for j, opts := range testCase.equivalents {
4559 cName := fmt.Sprintf("mount-%d-%d", i, j)
4560 _, _, err := dockerCmdWithError(append([]string{"run", "-i", "-d", "--name", cName},
4561 append(opts, []string{"busybox", "top"}...)...)...)
4563 c.Assert(err, check.IsNil,
4564 check.Commentf("got error while creating a container with %v (%s)", opts, cName))
4565 c.Assert(testCase.fn(cName), check.IsNil,
4566 check.Commentf("got error while executing test for %v (%s)", opts, cName))
4567 dockerCmd(c, "rm", "-f", cName)
4569 c.Assert(err, checker.NotNil,
4570 check.Commentf("got nil while creating a container with %v (%s)", opts, cName))
4576 // Test that passing a FQDN as hostname properly sets hostname, and
4577 // /etc/hostname. Test case for 29100
4578 func (s *DockerSuite) TestRunHostnameFQDN(c *check.C) {
4579 testRequires(c, DaemonIsLinux)
4581 expectedOutput := "foobar.example.com\nfoobar.example.com\nfoobar\nexample.com\nfoobar.example.com"
4582 out, _ := dockerCmd(c, "run", "--hostname=foobar.example.com", "busybox", "sh", "-c", `cat /etc/hostname && hostname && hostname -s && hostname -d && hostname -f`)
4583 c.Assert(strings.TrimSpace(out), checker.Equals, expectedOutput)
4585 out, _ = dockerCmd(c, "run", "--hostname=foobar.example.com", "busybox", "sh", "-c", `cat /etc/hosts`)
4586 expectedOutput = "foobar.example.com foobar"
4587 c.Assert(strings.TrimSpace(out), checker.Contains, expectedOutput)
4590 // Test case for 29129
4591 func (s *DockerSuite) TestRunHostnameInHostMode(c *check.C) {
4592 testRequires(c, DaemonIsLinux, NotUserNamespace)
4594 expectedOutput := "foobar\nfoobar"
4595 out, _ := dockerCmd(c, "run", "--net=host", "--hostname=foobar", "busybox", "sh", "-c", `echo $HOSTNAME && hostname`)
4596 c.Assert(strings.TrimSpace(out), checker.Equals, expectedOutput)
4599 func (s *DockerSuite) TestRunAddDeviceCgroupRule(c *check.C) {
4600 testRequires(c, DaemonIsLinux)
4602 deviceRule := "c 7:128 rwm"
4604 out, _ := dockerCmd(c, "run", "--rm", "busybox", "cat", "/sys/fs/cgroup/devices/devices.list")
4605 if strings.Contains(out, deviceRule) {
4606 c.Fatalf("%s shouldn't been in the device.list", deviceRule)
4609 out, _ = dockerCmd(c, "run", "--rm", fmt.Sprintf("--device-cgroup-rule=%s", deviceRule), "busybox", "grep", deviceRule, "/sys/fs/cgroup/devices/devices.list")
4610 c.Assert(strings.TrimSpace(out), checker.Equals, deviceRule)
4613 // Verifies that running as local system is operating correctly on Windows
4614 func (s *DockerSuite) TestWindowsRunAsSystem(c *check.C) {
4615 testRequires(c, DaemonIsWindows)
4616 if testEnv.DaemonKernelVersionNumeric() < 15000 {
4617 c.Skip("Requires build 15000 or later")
4619 out, _ := dockerCmd(c, "run", "--net=none", `--user=nt authority\system`, "--hostname=XYZZY", minimalBaseImage(), "cmd", "/c", `@echo %USERNAME%`)
4620 c.Assert(strings.TrimSpace(out), checker.Equals, "XYZZY$")