github.com/walkingsparrow/docker@v1.4.2-0.20151218153551-b708a2249bfa/integration-cli/docker_cli_run_test.go (about) 1 package main 2 3 import ( 4 "bufio" 5 "bytes" 6 "fmt" 7 "io/ioutil" 8 "net" 9 "os" 10 "os/exec" 11 "path" 12 "path/filepath" 13 "reflect" 14 "regexp" 15 "sort" 16 "strconv" 17 "strings" 18 "sync" 19 "time" 20 21 "github.com/docker/docker/pkg/integration/checker" 22 "github.com/docker/docker/pkg/mount" 23 "github.com/docker/docker/pkg/nat" 24 "github.com/docker/docker/runconfig" 25 "github.com/docker/libnetwork/resolvconf" 26 "github.com/go-check/check" 27 ) 28 29 // "test123" should be printed by docker run 30 func (s *DockerSuite) TestRunEchoStdout(c *check.C) { 31 out, _ := dockerCmd(c, "run", "busybox", "echo", "test123") 32 if out != "test123\n" { 33 c.Fatalf("container should've printed 'test123', got '%s'", out) 34 } 35 } 36 37 // "test" should be printed 38 func (s *DockerSuite) TestRunEchoNamedContainer(c *check.C) { 39 out, _ := dockerCmd(c, "run", "--name", "testfoonamedcontainer", "busybox", "echo", "test") 40 if out != "test\n" { 41 c.Errorf("container should've printed 'test'") 42 } 43 } 44 45 // docker run should not leak file descriptors. This test relies on Unix 46 // specific functionality and cannot run on Windows. 47 func (s *DockerSuite) TestRunLeakyFileDescriptors(c *check.C) { 48 testRequires(c, DaemonIsLinux) 49 out, _ := dockerCmd(c, "run", "busybox", "ls", "-C", "/proc/self/fd") 50 51 // normally, we should only get 0, 1, and 2, but 3 gets created by "ls" when it does "opendir" on the "fd" directory 52 if out != "0 1 2 3\n" { 53 c.Errorf("container should've printed '0 1 2 3', not: %s", out) 54 } 55 } 56 57 // it should be possible to lookup Google DNS 58 // this will fail when Internet access is unavailable 59 func (s *DockerSuite) TestRunLookupGoogleDns(c *check.C) { 60 testRequires(c, Network) 61 image := DefaultImage 62 if daemonPlatform == "windows" { 63 // nslookup isn't present in Windows busybox. Is built-in. 64 image = WindowsBaseImage 65 } 66 dockerCmd(c, "run", image, "nslookup", "google.com") 67 } 68 69 // the exit code should be 0 70 func (s *DockerSuite) TestRunExitCodeZero(c *check.C) { 71 dockerCmd(c, "run", "busybox", "true") 72 } 73 74 // the exit code should be 1 75 func (s *DockerSuite) TestRunExitCodeOne(c *check.C) { 76 _, exitCode, err := dockerCmdWithError("run", "busybox", "false") 77 if err != nil && !strings.Contains("exit status 1", fmt.Sprintf("%s", err)) { 78 c.Fatal(err) 79 } 80 if exitCode != 1 { 81 c.Errorf("container should've exited with exit code 1. Got %d", exitCode) 82 } 83 } 84 85 // it should be possible to pipe in data via stdin to a process running in a container 86 func (s *DockerSuite) TestRunStdinPipe(c *check.C) { 87 // TODO Windows: This needs some work to make compatible. 88 testRequires(c, DaemonIsLinux) 89 runCmd := exec.Command(dockerBinary, "run", "-i", "-a", "stdin", "busybox", "cat") 90 runCmd.Stdin = strings.NewReader("blahblah") 91 out, _, _, err := runCommandWithStdoutStderr(runCmd) 92 if err != nil { 93 c.Fatalf("failed to run container: %v, output: %q", err, out) 94 } 95 96 out = strings.TrimSpace(out) 97 dockerCmd(c, "wait", out) 98 99 logsOut, _ := dockerCmd(c, "logs", out) 100 101 containerLogs := strings.TrimSpace(logsOut) 102 if containerLogs != "blahblah" { 103 c.Errorf("logs didn't print the container's logs %s", containerLogs) 104 } 105 106 dockerCmd(c, "rm", out) 107 } 108 109 // the container's ID should be printed when starting a container in detached mode 110 func (s *DockerSuite) TestRunDetachedContainerIDPrinting(c *check.C) { 111 out, _ := dockerCmd(c, "run", "-d", "busybox", "true") 112 113 out = strings.TrimSpace(out) 114 dockerCmd(c, "wait", out) 115 116 rmOut, _ := dockerCmd(c, "rm", out) 117 118 rmOut = strings.TrimSpace(rmOut) 119 if rmOut != out { 120 c.Errorf("rm didn't print the container ID %s %s", out, rmOut) 121 } 122 } 123 124 // the working directory should be set correctly 125 func (s *DockerSuite) TestRunWorkingDirectory(c *check.C) { 126 // TODO Windows: There's a Windows bug stopping this from working. 127 testRequires(c, DaemonIsLinux) 128 dir := "/root" 129 image := "busybox" 130 if daemonPlatform == "windows" { 131 dir = `/windows` 132 image = WindowsBaseImage 133 } 134 135 // First with -w 136 out, _ := dockerCmd(c, "run", "-w", dir, image, "pwd") 137 out = strings.TrimSpace(out) 138 if out != dir { 139 c.Errorf("-w failed to set working directory") 140 } 141 142 // Then with --workdir 143 out, _ = dockerCmd(c, "run", "--workdir", dir, image, "pwd") 144 out = strings.TrimSpace(out) 145 if out != dir { 146 c.Errorf("--workdir failed to set working directory") 147 } 148 } 149 150 // pinging Google's DNS resolver should fail when we disable the networking 151 func (s *DockerSuite) TestRunWithoutNetworking(c *check.C) { 152 count := "-c" 153 image := "busybox" 154 if daemonPlatform == "windows" { 155 count = "-n" 156 image = WindowsBaseImage 157 } 158 159 // First using the long form --net 160 out, exitCode, err := dockerCmdWithError("run", "--net=none", image, "ping", count, "1", "8.8.8.8") 161 if err != nil && exitCode != 1 { 162 c.Fatal(out, err) 163 } 164 if exitCode != 1 { 165 c.Errorf("--net=none should've disabled the network; the container shouldn't have been able to ping 8.8.8.8") 166 } 167 } 168 169 //test --link use container name to link target 170 func (s *DockerSuite) TestRunLinksContainerWithContainerName(c *check.C) { 171 // TODO Windows: This test cannot run on a Windows daemon as the networking 172 // settings are not populated back yet on inspect. 173 testRequires(c, DaemonIsLinux) 174 dockerCmd(c, "run", "-i", "-t", "-d", "--name", "parent", "busybox") 175 176 ip, err := inspectField("parent", "NetworkSettings.Networks.bridge.IPAddress") 177 c.Assert(err, check.IsNil) 178 179 out, _ := dockerCmd(c, "run", "--link", "parent:test", "busybox", "/bin/cat", "/etc/hosts") 180 if !strings.Contains(out, ip+" test") { 181 c.Fatalf("use a container name to link target failed") 182 } 183 } 184 185 //test --link use container id to link target 186 func (s *DockerSuite) TestRunLinksContainerWithContainerId(c *check.C) { 187 // TODO Windows: This test cannot run on a Windows daemon as the networking 188 // settings are not populated back yet on inspect. 189 testRequires(c, DaemonIsLinux) 190 cID, _ := dockerCmd(c, "run", "-i", "-t", "-d", "busybox") 191 192 cID = strings.TrimSpace(cID) 193 ip, err := inspectField(cID, "NetworkSettings.Networks.bridge.IPAddress") 194 c.Assert(err, check.IsNil) 195 196 out, _ := dockerCmd(c, "run", "--link", cID+":test", "busybox", "/bin/cat", "/etc/hosts") 197 if !strings.Contains(out, ip+" test") { 198 c.Fatalf("use a container id to link target failed") 199 } 200 } 201 202 // Issue 9677. 203 func (s *DockerSuite) TestRunWithDaemonFlags(c *check.C) { 204 out, _, err := dockerCmdWithError("--exec-opt", "foo=bar", "run", "-i", "busybox", "true") 205 if err != nil { 206 if !strings.Contains(out, "flag provided but not defined: --exec-opt") { // no daemon (client-only) 207 c.Fatal(err, out) 208 } 209 } 210 } 211 212 // Regression test for #4979 213 func (s *DockerSuite) TestRunWithVolumesFromExited(c *check.C) { 214 215 var ( 216 out string 217 exitCode int 218 ) 219 220 // Create a file in a volume 221 if daemonPlatform == "windows" { 222 out, exitCode = dockerCmd(c, "run", "--name", "test-data", "--volume", `c:\some\dir`, WindowsBaseImage, `cmd /c echo hello > c:\some\dir\file`) 223 } else { 224 out, exitCode = dockerCmd(c, "run", "--name", "test-data", "--volume", "/some/dir", "busybox", "touch", "/some/dir/file") 225 } 226 if exitCode != 0 { 227 c.Fatal("1", out, exitCode) 228 } 229 230 // Read the file from another container using --volumes-from to access the volume in the second container 231 if daemonPlatform == "windows" { 232 out, exitCode = dockerCmd(c, "run", "--volumes-from", "test-data", WindowsBaseImage, `cmd /c type c:\some\dir\file`) 233 } else { 234 out, exitCode = dockerCmd(c, "run", "--volumes-from", "test-data", "busybox", "cat", "/some/dir/file") 235 } 236 if exitCode != 0 { 237 c.Fatal("2", out, exitCode) 238 } 239 } 240 241 // Volume path is a symlink which also exists on the host, and the host side is a file not a dir 242 // But the volume call is just a normal volume, not a bind mount 243 func (s *DockerSuite) TestRunCreateVolumesInSymlinkDir(c *check.C) { 244 var ( 245 dockerFile string 246 containerPath string 247 cmd string 248 ) 249 testRequires(c, SameHostDaemon) 250 name := "test-volume-symlink" 251 252 dir, err := ioutil.TempDir("", name) 253 if err != nil { 254 c.Fatal(err) 255 } 256 defer os.RemoveAll(dir) 257 258 f, err := os.OpenFile(filepath.Join(dir, "test"), os.O_CREATE, 0700) 259 if err != nil { 260 c.Fatal(err) 261 } 262 f.Close() 263 264 if daemonPlatform == "windows" { 265 dockerFile = fmt.Sprintf("FROM %s\nRUN mkdir %s\nRUN mklink /D c:\\test %s", WindowsBaseImage, dir, dir) 266 containerPath = `c:\test\test` 267 cmd = "tasklist" 268 } else { 269 dockerFile = fmt.Sprintf("FROM busybox\nRUN mkdir -p %s\nRUN ln -s %s /test", dir, dir) 270 containerPath = "/test/test" 271 cmd = "true" 272 } 273 if _, err := buildImage(name, dockerFile, false); err != nil { 274 c.Fatal(err) 275 } 276 277 dockerCmd(c, "run", "-v", containerPath, name, cmd) 278 } 279 280 func (s *DockerSuite) TestRunVolumesMountedAsReadonly(c *check.C) { 281 // TODO Windows (Post TP4): This test cannot run on a Windows daemon as 282 // Windows does not support read-only bind mounts. 283 testRequires(c, DaemonIsLinux) 284 if _, code, err := dockerCmdWithError("run", "-v", "/test:/test:ro", "busybox", "touch", "/test/somefile"); err == nil || code == 0 { 285 c.Fatalf("run should fail because volume is ro: exit code %d", code) 286 } 287 } 288 289 func (s *DockerSuite) TestRunVolumesFromInReadonlyModeFails(c *check.C) { 290 // TODO Windows (Post TP4): This test cannot run on a Windows daemon as 291 // Windows does not support read-only bind mounts. Modified for when ro is supported. 292 testRequires(c, DaemonIsLinux) 293 var ( 294 volumeDir string 295 fileInVol string 296 ) 297 if daemonPlatform == "windows" { 298 volumeDir = `c:/test` // Forward-slash as using busybox 299 fileInVol = `c:/test/file` 300 } else { 301 testRequires(c, DaemonIsLinux) 302 volumeDir = "/test" 303 fileInVol = `/test/file` 304 } 305 dockerCmd(c, "run", "--name", "parent", "-v", volumeDir, "busybox", "true") 306 307 if _, code, err := dockerCmdWithError("run", "--volumes-from", "parent:ro", "busybox", "touch", fileInVol); err == nil || code == 0 { 308 c.Fatalf("run should fail because volume is ro: exit code %d", code) 309 } 310 } 311 312 // Regression test for #1201 313 func (s *DockerSuite) TestRunVolumesFromInReadWriteMode(c *check.C) { 314 var ( 315 volumeDir string 316 fileInVol string 317 ) 318 if daemonPlatform == "windows" { 319 volumeDir = `c:/test` // Forward-slash as using busybox 320 fileInVol = `c:/test/file` 321 } else { 322 testRequires(c, DaemonIsLinux) 323 volumeDir = "/test" 324 fileInVol = "/test/file" 325 } 326 327 dockerCmd(c, "run", "--name", "parent", "-v", volumeDir, "busybox", "true") 328 dockerCmd(c, "run", "--volumes-from", "parent:rw", "busybox", "touch", fileInVol) 329 330 if out, _, err := dockerCmdWithError("run", "--volumes-from", "parent:bar", "busybox", "touch", fileInVol); err == nil || !strings.Contains(out, `invalid mode: "bar"`) { 331 c.Fatalf("running --volumes-from parent:bar should have failed with invalid mode: %q", out) 332 } 333 334 dockerCmd(c, "run", "--volumes-from", "parent", "busybox", "touch", fileInVol) 335 } 336 337 func (s *DockerSuite) TestVolumesFromGetsProperMode(c *check.C) { 338 // TODO Windows: This test cannot yet run on a Windows daemon as Windows does 339 // not support read-only bind mounts as at TP4 340 testRequires(c, DaemonIsLinux) 341 dockerCmd(c, "run", "--name", "parent", "-v", "/test:/test:ro", "busybox", "true") 342 343 // Expect this "rw" mode to be be ignored since the inherited volume is "ro" 344 if _, _, err := dockerCmdWithError("run", "--volumes-from", "parent:rw", "busybox", "touch", "/test/file"); err == nil { 345 c.Fatal("Expected volumes-from to inherit read-only volume even when passing in `rw`") 346 } 347 348 dockerCmd(c, "run", "--name", "parent2", "-v", "/test:/test:ro", "busybox", "true") 349 350 // Expect this to be read-only since both are "ro" 351 if _, _, err := dockerCmdWithError("run", "--volumes-from", "parent2:ro", "busybox", "touch", "/test/file"); err == nil { 352 c.Fatal("Expected volumes-from to inherit read-only volume even when passing in `ro`") 353 } 354 } 355 356 // Test for GH#10618 357 func (s *DockerSuite) TestRunNoDupVolumes(c *check.C) { 358 path1 := randomTmpDirPath("test1", daemonPlatform) 359 path2 := randomTmpDirPath("test2", daemonPlatform) 360 361 someplace := ":/someplace" 362 if daemonPlatform == "windows" { 363 // Windows requires that the source directory exists before calling HCS 364 testRequires(c, SameHostDaemon) 365 someplace = `:c:\someplace` 366 if err := os.MkdirAll(path1, 0755); err != nil { 367 c.Fatalf("Failed to create %s: %q", path1, err) 368 } 369 defer os.RemoveAll(path1) 370 if err := os.MkdirAll(path2, 0755); err != nil { 371 c.Fatalf("Failed to create %s: %q", path1, err) 372 } 373 defer os.RemoveAll(path2) 374 } 375 mountstr1 := path1 + someplace 376 mountstr2 := path2 + someplace 377 378 if out, _, err := dockerCmdWithError("run", "-v", mountstr1, "-v", mountstr2, "busybox", "true"); err == nil { 379 c.Fatal("Expected error about duplicate mount definitions") 380 } else { 381 if !strings.Contains(out, "Duplicate mount point") { 382 c.Fatalf("Expected 'duplicate mount point' error, got %v", out) 383 } 384 } 385 } 386 387 // Test for #1351 388 func (s *DockerSuite) TestRunApplyVolumesFromBeforeVolumes(c *check.C) { 389 prefix := "" 390 if daemonPlatform == "windows" { 391 prefix = `c:` 392 } 393 dockerCmd(c, "run", "--name", "parent", "-v", prefix+"/test", "busybox", "touch", prefix+"/test/foo") 394 dockerCmd(c, "run", "--volumes-from", "parent", "-v", prefix+"/test", "busybox", "cat", prefix+"/test/foo") 395 } 396 397 func (s *DockerSuite) TestRunMultipleVolumesFrom(c *check.C) { 398 prefix := "" 399 if daemonPlatform == "windows" { 400 prefix = `c:` 401 } 402 dockerCmd(c, "run", "--name", "parent1", "-v", prefix+"/test", "busybox", "touch", prefix+"/test/foo") 403 dockerCmd(c, "run", "--name", "parent2", "-v", prefix+"/other", "busybox", "touch", prefix+"/other/bar") 404 dockerCmd(c, "run", "--volumes-from", "parent1", "--volumes-from", "parent2", "busybox", "sh", "-c", "cat /test/foo && cat /other/bar") 405 } 406 407 // this tests verifies the ID format for the container 408 func (s *DockerSuite) TestRunVerifyContainerID(c *check.C) { 409 out, exit, err := dockerCmdWithError("run", "-d", "busybox", "true") 410 if err != nil { 411 c.Fatal(err) 412 } 413 if exit != 0 { 414 c.Fatalf("expected exit code 0 received %d", exit) 415 } 416 417 match, err := regexp.MatchString("^[0-9a-f]{64}$", strings.TrimSuffix(out, "\n")) 418 if err != nil { 419 c.Fatal(err) 420 } 421 if !match { 422 c.Fatalf("Invalid container ID: %s", out) 423 } 424 } 425 426 // Test that creating a container with a volume doesn't crash. Regression test for #995. 427 func (s *DockerSuite) TestRunCreateVolume(c *check.C) { 428 prefix := "" 429 if daemonPlatform == "windows" { 430 prefix = `c:` 431 } 432 dockerCmd(c, "run", "-v", prefix+"/var/lib/data", "busybox", "true") 433 } 434 435 // Test that creating a volume with a symlink in its path works correctly. Test for #5152. 436 // Note that this bug happens only with symlinks with a target that starts with '/'. 437 func (s *DockerSuite) TestRunCreateVolumeWithSymlink(c *check.C) { 438 // Cannot run on Windows as relies on Linux-specific functionality (sh -c mount...) 439 testRequires(c, DaemonIsLinux) 440 image := "docker-test-createvolumewithsymlink" 441 442 buildCmd := exec.Command(dockerBinary, "build", "-t", image, "-") 443 buildCmd.Stdin = strings.NewReader(`FROM busybox 444 RUN ln -s home /bar`) 445 buildCmd.Dir = workingDirectory 446 err := buildCmd.Run() 447 if err != nil { 448 c.Fatalf("could not build '%s': %v", image, err) 449 } 450 451 _, exitCode, err := dockerCmdWithError("run", "-v", "/bar/foo", "--name", "test-createvolumewithsymlink", image, "sh", "-c", "mount | grep -q /home/foo") 452 if err != nil || exitCode != 0 { 453 c.Fatalf("[run] err: %v, exitcode: %d", err, exitCode) 454 } 455 456 volPath, err := inspectMountSourceField("test-createvolumewithsymlink", "/bar/foo") 457 if err != nil { 458 c.Fatalf("[inspect] err: %v", err) 459 } 460 461 _, exitCode, err = dockerCmdWithError("rm", "-v", "test-createvolumewithsymlink") 462 if err != nil || exitCode != 0 { 463 c.Fatalf("[rm] err: %v, exitcode: %d", err, exitCode) 464 } 465 466 _, err = os.Stat(volPath) 467 if !os.IsNotExist(err) { 468 c.Fatalf("[open] (expecting 'file does not exist' error) err: %v, volPath: %s", err, volPath) 469 } 470 } 471 472 // Tests that a volume path that has a symlink exists in a container mounting it with `--volumes-from`. 473 func (s *DockerSuite) TestRunVolumesFromSymlinkPath(c *check.C) { 474 name := "docker-test-volumesfromsymlinkpath" 475 prefix := "" 476 dfContents := `FROM busybox 477 RUN ln -s home /foo 478 VOLUME ["/foo/bar"]` 479 480 if daemonPlatform == "windows" { 481 prefix = `c:` 482 dfContents = `FROM ` + WindowsBaseImage + ` 483 RUN mkdir c:\home 484 RUN mklink /D c:\foo c:\home 485 VOLUME ["c:/foo/bar"] 486 ENTRYPOINT c:\windows\system32\cmd.exe` 487 } 488 489 buildCmd := exec.Command(dockerBinary, "build", "-t", name, "-") 490 buildCmd.Stdin = strings.NewReader(dfContents) 491 buildCmd.Dir = workingDirectory 492 err := buildCmd.Run() 493 if err != nil { 494 c.Fatalf("could not build 'docker-test-volumesfromsymlinkpath': %v", err) 495 } 496 497 out, exitCode, err := dockerCmdWithError("run", "--name", "test-volumesfromsymlinkpath", name) 498 if err != nil || exitCode != 0 { 499 c.Fatalf("[run] (volume) err: %v, exitcode: %d, out: %s", err, exitCode, out) 500 } 501 502 _, exitCode, err = dockerCmdWithError("run", "--volumes-from", "test-volumesfromsymlinkpath", "busybox", "sh", "-c", "ls "+prefix+"/foo | grep -q bar") 503 if err != nil || exitCode != 0 { 504 c.Fatalf("[run] err: %v, exitcode: %d", err, exitCode) 505 } 506 } 507 508 func (s *DockerSuite) TestRunExitCode(c *check.C) { 509 var ( 510 exit int 511 err error 512 ) 513 514 _, exit, err = dockerCmdWithError("run", "busybox", "/bin/sh", "-c", "exit 72") 515 516 if err == nil { 517 c.Fatal("should not have a non nil error") 518 } 519 if exit != 72 { 520 c.Fatalf("expected exit code 72 received %d", exit) 521 } 522 } 523 524 func (s *DockerSuite) TestRunUserDefaults(c *check.C) { 525 expected := "uid=0(root) gid=0(root)" 526 if daemonPlatform == "windows" { 527 expected = "uid=1000(SYSTEM) gid=1000(SYSTEM)" 528 } 529 out, _ := dockerCmd(c, "run", "busybox", "id") 530 if !strings.Contains(out, expected) { 531 c.Fatalf("expected '%s' got %s", expected, out) 532 } 533 } 534 535 func (s *DockerSuite) TestRunUserByName(c *check.C) { 536 // TODO Windows: This test cannot run on a Windows daemon as Windows does 537 // not support the use of -u 538 testRequires(c, DaemonIsLinux) 539 out, _ := dockerCmd(c, "run", "-u", "root", "busybox", "id") 540 if !strings.Contains(out, "uid=0(root) gid=0(root)") { 541 c.Fatalf("expected root user got %s", out) 542 } 543 } 544 545 func (s *DockerSuite) TestRunUserByID(c *check.C) { 546 // TODO Windows: This test cannot run on a Windows daemon as Windows does 547 // not support the use of -u 548 testRequires(c, DaemonIsLinux) 549 out, _ := dockerCmd(c, "run", "-u", "1", "busybox", "id") 550 if !strings.Contains(out, "uid=1(daemon) gid=1(daemon)") { 551 c.Fatalf("expected daemon user got %s", out) 552 } 553 } 554 555 func (s *DockerSuite) TestRunUserByIDBig(c *check.C) { 556 // TODO Windows: This test cannot run on a Windows daemon as Windows does 557 // not support the use of -u 558 testRequires(c, DaemonIsLinux) 559 out, _, err := dockerCmdWithError("run", "-u", "2147483648", "busybox", "id") 560 if err == nil { 561 c.Fatal("No error, but must be.", out) 562 } 563 if !strings.Contains(out, "Uids and gids must be in range") { 564 c.Fatalf("expected error about uids range, got %s", out) 565 } 566 } 567 568 func (s *DockerSuite) TestRunUserByIDNegative(c *check.C) { 569 // TODO Windows: This test cannot run on a Windows daemon as Windows does 570 // not support the use of -u 571 testRequires(c, DaemonIsLinux) 572 out, _, err := dockerCmdWithError("run", "-u", "-1", "busybox", "id") 573 if err == nil { 574 c.Fatal("No error, but must be.", out) 575 } 576 if !strings.Contains(out, "Uids and gids must be in range") { 577 c.Fatalf("expected error about uids range, got %s", out) 578 } 579 } 580 581 func (s *DockerSuite) TestRunUserByIDZero(c *check.C) { 582 // TODO Windows: This test cannot run on a Windows daemon as Windows does 583 // not support the use of -u 584 testRequires(c, DaemonIsLinux) 585 out, _, err := dockerCmdWithError("run", "-u", "0", "busybox", "id") 586 if err != nil { 587 c.Fatal(err, out) 588 } 589 if !strings.Contains(out, "uid=0(root) gid=0(root) groups=10(wheel)") { 590 c.Fatalf("expected daemon user got %s", out) 591 } 592 } 593 594 func (s *DockerSuite) TestRunUserNotFound(c *check.C) { 595 // TODO Windows: This test cannot run on a Windows daemon as Windows does 596 // not support the use of -u 597 testRequires(c, DaemonIsLinux) 598 _, _, err := dockerCmdWithError("run", "-u", "notme", "busybox", "id") 599 if err == nil { 600 c.Fatal("unknown user should cause container to fail") 601 } 602 } 603 604 func (s *DockerSuite) TestRunTwoConcurrentContainers(c *check.C) { 605 // TODO Windows. There are two bugs in TP4 which means this test cannot 606 // be reliably enabled. The first is a race condition where sometimes 607 // HCS CreateComputeSystem() will fail "Invalid class string". #4985252 and 608 // #4493430. 609 // 610 // The second, which is seen more readily by increasing the number of concurrent 611 // containers to 5 or more, is that CSRSS hangs. This may fixed in the TP4 ZDP. 612 // #4898773. 613 testRequires(c, DaemonIsLinux) 614 sleepTime := "2" 615 if daemonPlatform == "windows" { 616 sleepTime = "5" // Make more reliable on Windows 617 } 618 group := sync.WaitGroup{} 619 group.Add(2) 620 621 errChan := make(chan error, 2) 622 for i := 0; i < 2; i++ { 623 go func() { 624 defer group.Done() 625 _, _, err := dockerCmdWithError("run", "busybox", "sleep", sleepTime) 626 errChan <- err 627 }() 628 } 629 630 group.Wait() 631 close(errChan) 632 633 for err := range errChan { 634 c.Assert(err, check.IsNil) 635 } 636 } 637 638 func (s *DockerSuite) TestRunEnvironment(c *check.C) { 639 // TODO Windows: Environment handling is different between Linux and 640 // Windows and this test relies currently on unix functionality. 641 testRequires(c, DaemonIsLinux) 642 cmd := exec.Command(dockerBinary, "run", "-h", "testing", "-e=FALSE=true", "-e=TRUE", "-e=TRICKY", "-e=HOME=", "busybox", "env") 643 cmd.Env = append(os.Environ(), 644 "TRUE=false", 645 "TRICKY=tri\ncky\n", 646 ) 647 648 out, _, err := runCommandWithOutput(cmd) 649 if err != nil { 650 c.Fatal(err, out) 651 } 652 653 actualEnv := strings.Split(strings.TrimSpace(out), "\n") 654 sort.Strings(actualEnv) 655 656 goodEnv := []string{ 657 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 658 "HOSTNAME=testing", 659 "FALSE=true", 660 "TRUE=false", 661 "TRICKY=tri", 662 "cky", 663 "", 664 "HOME=/root", 665 } 666 sort.Strings(goodEnv) 667 if len(goodEnv) != len(actualEnv) { 668 c.Fatalf("Wrong environment: should be %d variables, not: %q\n", len(goodEnv), strings.Join(actualEnv, ", ")) 669 } 670 for i := range goodEnv { 671 if actualEnv[i] != goodEnv[i] { 672 c.Fatalf("Wrong environment variable: should be %s, not %s", goodEnv[i], actualEnv[i]) 673 } 674 } 675 } 676 677 func (s *DockerSuite) TestRunEnvironmentErase(c *check.C) { 678 // TODO Windows: Environment handling is different between Linux and 679 // Windows and this test relies currently on unix functionality. 680 testRequires(c, DaemonIsLinux) 681 682 // Test to make sure that when we use -e on env vars that are 683 // not set in our local env that they're removed (if present) in 684 // the container 685 686 cmd := exec.Command(dockerBinary, "run", "-e", "FOO", "-e", "HOSTNAME", "busybox", "env") 687 cmd.Env = appendBaseEnv([]string{}) 688 689 out, _, err := runCommandWithOutput(cmd) 690 if err != nil { 691 c.Fatal(err, out) 692 } 693 694 actualEnv := strings.Split(strings.TrimSpace(out), "\n") 695 sort.Strings(actualEnv) 696 697 goodEnv := []string{ 698 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 699 "HOME=/root", 700 } 701 sort.Strings(goodEnv) 702 if len(goodEnv) != len(actualEnv) { 703 c.Fatalf("Wrong environment: should be %d variables, not: %q\n", len(goodEnv), strings.Join(actualEnv, ", ")) 704 } 705 for i := range goodEnv { 706 if actualEnv[i] != goodEnv[i] { 707 c.Fatalf("Wrong environment variable: should be %s, not %s", goodEnv[i], actualEnv[i]) 708 } 709 } 710 } 711 712 func (s *DockerSuite) TestRunEnvironmentOverride(c *check.C) { 713 // TODO Windows: Environment handling is different between Linux and 714 // Windows and this test relies currently on unix functionality. 715 testRequires(c, DaemonIsLinux) 716 717 // Test to make sure that when we use -e on env vars that are 718 // already in the env that we're overriding them 719 720 cmd := exec.Command(dockerBinary, "run", "-e", "HOSTNAME", "-e", "HOME=/root2", "busybox", "env") 721 cmd.Env = appendBaseEnv([]string{"HOSTNAME=bar"}) 722 723 out, _, err := runCommandWithOutput(cmd) 724 if err != nil { 725 c.Fatal(err, out) 726 } 727 728 actualEnv := strings.Split(strings.TrimSpace(out), "\n") 729 sort.Strings(actualEnv) 730 731 goodEnv := []string{ 732 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 733 "HOME=/root2", 734 "HOSTNAME=bar", 735 } 736 sort.Strings(goodEnv) 737 if len(goodEnv) != len(actualEnv) { 738 c.Fatalf("Wrong environment: should be %d variables, not: %q\n", len(goodEnv), strings.Join(actualEnv, ", ")) 739 } 740 for i := range goodEnv { 741 if actualEnv[i] != goodEnv[i] { 742 c.Fatalf("Wrong environment variable: should be %s, not %s", goodEnv[i], actualEnv[i]) 743 } 744 } 745 } 746 747 func (s *DockerSuite) TestRunContainerNetwork(c *check.C) { 748 if daemonPlatform == "windows" { 749 // Windows busybox does not have ping. Use built in ping instead. 750 dockerCmd(c, "run", WindowsBaseImage, "ping", "-n", "1", "127.0.0.1") 751 } else { 752 dockerCmd(c, "run", "busybox", "ping", "-c", "1", "127.0.0.1") 753 } 754 } 755 756 func (s *DockerSuite) TestRunNetHostNotAllowedWithLinks(c *check.C) { 757 // TODO Windows: This is Linux specific as --link is not supported and 758 // this will be deprecated in favor of container networking model. 759 testRequires(c, DaemonIsLinux, NotUserNamespace) 760 dockerCmd(c, "run", "--name", "linked", "busybox", "true") 761 762 _, _, err := dockerCmdWithError("run", "--net=host", "--link", "linked:linked", "busybox", "true") 763 if err == nil { 764 c.Fatal("Expected error") 765 } 766 } 767 768 // #7851 hostname outside container shows FQDN, inside only shortname 769 // For testing purposes it is not required to set host's hostname directly 770 // and use "--net=host" (as the original issue submitter did), as the same 771 // codepath is executed with "docker run -h <hostname>". Both were manually 772 // tested, but this testcase takes the simpler path of using "run -h .." 773 func (s *DockerSuite) TestRunFullHostnameSet(c *check.C) { 774 // TODO Windows: -h is not yet functional. 775 testRequires(c, DaemonIsLinux) 776 out, _ := dockerCmd(c, "run", "-h", "foo.bar.baz", "busybox", "hostname") 777 if actual := strings.Trim(out, "\r\n"); actual != "foo.bar.baz" { 778 c.Fatalf("expected hostname 'foo.bar.baz', received %s", actual) 779 } 780 } 781 782 func (s *DockerSuite) TestRunPrivilegedCanMknod(c *check.C) { 783 // Not applicable for Windows as Windows daemon does not support 784 // the concept of --privileged, and mknod is a Unix concept. 785 testRequires(c, DaemonIsLinux, NotUserNamespace) 786 out, _ := dockerCmd(c, "run", "--privileged", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok") 787 if actual := strings.Trim(out, "\r\n"); actual != "ok" { 788 c.Fatalf("expected output ok received %s", actual) 789 } 790 } 791 792 func (s *DockerSuite) TestRunUnprivilegedCanMknod(c *check.C) { 793 // Not applicable for Windows as Windows daemon does not support 794 // the concept of --privileged, and mknod is a Unix concept. 795 testRequires(c, DaemonIsLinux, NotUserNamespace) 796 out, _ := dockerCmd(c, "run", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok") 797 if actual := strings.Trim(out, "\r\n"); actual != "ok" { 798 c.Fatalf("expected output ok received %s", actual) 799 } 800 } 801 802 func (s *DockerSuite) TestRunCapDropInvalid(c *check.C) { 803 // Not applicable for Windows as there is no concept of --cap-drop 804 testRequires(c, DaemonIsLinux) 805 out, _, err := dockerCmdWithError("run", "--cap-drop=CHPASS", "busybox", "ls") 806 if err == nil { 807 c.Fatal(err, out) 808 } 809 } 810 811 func (s *DockerSuite) TestRunCapDropCannotMknod(c *check.C) { 812 // Not applicable for Windows as there is no concept of --cap-drop or mknod 813 testRequires(c, DaemonIsLinux) 814 out, _, err := dockerCmdWithError("run", "--cap-drop=MKNOD", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok") 815 816 if err == nil { 817 c.Fatal(err, out) 818 } 819 if actual := strings.Trim(out, "\r\n"); actual == "ok" { 820 c.Fatalf("expected output not ok received %s", actual) 821 } 822 } 823 824 func (s *DockerSuite) TestRunCapDropCannotMknodLowerCase(c *check.C) { 825 // Not applicable for Windows as there is no concept of --cap-drop or mknod 826 testRequires(c, DaemonIsLinux) 827 out, _, err := dockerCmdWithError("run", "--cap-drop=mknod", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok") 828 829 if err == nil { 830 c.Fatal(err, out) 831 } 832 if actual := strings.Trim(out, "\r\n"); actual == "ok" { 833 c.Fatalf("expected output not ok received %s", actual) 834 } 835 } 836 837 func (s *DockerSuite) TestRunCapDropALLCannotMknod(c *check.C) { 838 // Not applicable for Windows as there is no concept of --cap-drop or mknod 839 testRequires(c, DaemonIsLinux) 840 out, _, err := dockerCmdWithError("run", "--cap-drop=ALL", "--cap-add=SETGID", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok") 841 if err == nil { 842 c.Fatal(err, out) 843 } 844 if actual := strings.Trim(out, "\r\n"); actual == "ok" { 845 c.Fatalf("expected output not ok received %s", actual) 846 } 847 } 848 849 func (s *DockerSuite) TestRunCapDropALLAddMknodCanMknod(c *check.C) { 850 // Not applicable for Windows as there is no concept of --cap-drop or mknod 851 testRequires(c, DaemonIsLinux, NotUserNamespace) 852 out, _ := dockerCmd(c, "run", "--cap-drop=ALL", "--cap-add=MKNOD", "--cap-add=SETGID", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok") 853 854 if actual := strings.Trim(out, "\r\n"); actual != "ok" { 855 c.Fatalf("expected output ok received %s", actual) 856 } 857 } 858 859 func (s *DockerSuite) TestRunCapAddInvalid(c *check.C) { 860 // Not applicable for Windows as there is no concept of --cap-add 861 testRequires(c, DaemonIsLinux) 862 out, _, err := dockerCmdWithError("run", "--cap-add=CHPASS", "busybox", "ls") 863 if err == nil { 864 c.Fatal(err, out) 865 } 866 } 867 868 func (s *DockerSuite) TestRunCapAddCanDownInterface(c *check.C) { 869 // Not applicable for Windows as there is no concept of --cap-add 870 testRequires(c, DaemonIsLinux) 871 out, _ := dockerCmd(c, "run", "--cap-add=NET_ADMIN", "busybox", "sh", "-c", "ip link set eth0 down && echo ok") 872 873 if actual := strings.Trim(out, "\r\n"); actual != "ok" { 874 c.Fatalf("expected output ok received %s", actual) 875 } 876 } 877 878 func (s *DockerSuite) TestRunCapAddALLCanDownInterface(c *check.C) { 879 // Not applicable for Windows as there is no concept of --cap-add 880 testRequires(c, DaemonIsLinux) 881 out, _ := dockerCmd(c, "run", "--cap-add=ALL", "busybox", "sh", "-c", "ip link set eth0 down && echo ok") 882 883 if actual := strings.Trim(out, "\r\n"); actual != "ok" { 884 c.Fatalf("expected output ok received %s", actual) 885 } 886 } 887 888 func (s *DockerSuite) TestRunCapAddALLDropNetAdminCanDownInterface(c *check.C) { 889 // Not applicable for Windows as there is no concept of --cap-add 890 testRequires(c, DaemonIsLinux) 891 out, _, err := dockerCmdWithError("run", "--cap-add=ALL", "--cap-drop=NET_ADMIN", "busybox", "sh", "-c", "ip link set eth0 down && echo ok") 892 if err == nil { 893 c.Fatal(err, out) 894 } 895 if actual := strings.Trim(out, "\r\n"); actual == "ok" { 896 c.Fatalf("expected output not ok received %s", actual) 897 } 898 } 899 900 func (s *DockerSuite) TestRunGroupAdd(c *check.C) { 901 // Not applicable for Windows as there is no concept of --group-add 902 testRequires(c, DaemonIsLinux) 903 out, _ := dockerCmd(c, "run", "--group-add=audio", "--group-add=staff", "--group-add=777", "busybox", "sh", "-c", "id") 904 905 groupsList := "uid=0(root) gid=0(root) groups=10(wheel),29(audio),50(staff),777" 906 if actual := strings.Trim(out, "\r\n"); actual != groupsList { 907 c.Fatalf("expected output %s received %s", groupsList, actual) 908 } 909 } 910 911 func (s *DockerSuite) TestRunPrivilegedCanMount(c *check.C) { 912 // Not applicable for Windows as there is no concept of --privileged 913 testRequires(c, DaemonIsLinux, NotUserNamespace) 914 out, _ := dockerCmd(c, "run", "--privileged", "busybox", "sh", "-c", "mount -t tmpfs none /tmp && echo ok") 915 916 if actual := strings.Trim(out, "\r\n"); actual != "ok" { 917 c.Fatalf("expected output ok received %s", actual) 918 } 919 } 920 921 func (s *DockerSuite) TestRunUnprivilegedCannotMount(c *check.C) { 922 // Not applicable for Windows as there is no concept of unprivileged 923 testRequires(c, DaemonIsLinux) 924 out, _, err := dockerCmdWithError("run", "busybox", "sh", "-c", "mount -t tmpfs none /tmp && echo ok") 925 926 if err == nil { 927 c.Fatal(err, out) 928 } 929 if actual := strings.Trim(out, "\r\n"); actual == "ok" { 930 c.Fatalf("expected output not ok received %s", actual) 931 } 932 } 933 934 func (s *DockerSuite) TestRunSysNotWritableInNonPrivilegedContainers(c *check.C) { 935 // Not applicable for Windows as there is no concept of unprivileged 936 testRequires(c, DaemonIsLinux) 937 if _, code, err := dockerCmdWithError("run", "busybox", "touch", "/sys/kernel/profiling"); err == nil || code == 0 { 938 c.Fatal("sys should not be writable in a non privileged container") 939 } 940 } 941 942 func (s *DockerSuite) TestRunSysWritableInPrivilegedContainers(c *check.C) { 943 // Not applicable for Windows as there is no concept of unprivileged 944 testRequires(c, DaemonIsLinux, NotUserNamespace) 945 if _, code, err := dockerCmdWithError("run", "--privileged", "busybox", "touch", "/sys/kernel/profiling"); err != nil || code != 0 { 946 c.Fatalf("sys should be writable in privileged container") 947 } 948 } 949 950 func (s *DockerSuite) TestRunProcNotWritableInNonPrivilegedContainers(c *check.C) { 951 // Not applicable for Windows as there is no concept of unprivileged 952 testRequires(c, DaemonIsLinux) 953 if _, code, err := dockerCmdWithError("run", "busybox", "touch", "/proc/sysrq-trigger"); err == nil || code == 0 { 954 c.Fatal("proc should not be writable in a non privileged container") 955 } 956 } 957 958 func (s *DockerSuite) TestRunProcWritableInPrivilegedContainers(c *check.C) { 959 // Not applicable for Windows as there is no concept of --privileged 960 testRequires(c, DaemonIsLinux, NotUserNamespace) 961 if _, code := dockerCmd(c, "run", "--privileged", "busybox", "touch", "/proc/sysrq-trigger"); code != 0 { 962 c.Fatalf("proc should be writable in privileged container") 963 } 964 } 965 966 func (s *DockerSuite) TestRunDeviceNumbers(c *check.C) { 967 // Not applicable on Windows as /dev/ is a Unix specific concept 968 // TODO: NotUserNamespace could be removed here if "root" "root" is replaced w user 969 testRequires(c, DaemonIsLinux, NotUserNamespace) 970 out, _ := dockerCmd(c, "run", "busybox", "sh", "-c", "ls -l /dev/null") 971 deviceLineFields := strings.Fields(out) 972 deviceLineFields[6] = "" 973 deviceLineFields[7] = "" 974 deviceLineFields[8] = "" 975 expected := []string{"crw-rw-rw-", "1", "root", "root", "1,", "3", "", "", "", "/dev/null"} 976 977 if !(reflect.DeepEqual(deviceLineFields, expected)) { 978 c.Fatalf("expected output\ncrw-rw-rw- 1 root root 1, 3 May 24 13:29 /dev/null\n received\n %s\n", out) 979 } 980 } 981 982 func (s *DockerSuite) TestRunThatCharacterDevicesActLikeCharacterDevices(c *check.C) { 983 // Not applicable on Windows as /dev/ is a Unix specific concept 984 testRequires(c, DaemonIsLinux) 985 out, _ := dockerCmd(c, "run", "busybox", "sh", "-c", "dd if=/dev/zero of=/zero bs=1k count=5 2> /dev/null ; du -h /zero") 986 if actual := strings.Trim(out, "\r\n"); actual[0] == '0' { 987 c.Fatalf("expected a new file called /zero to be create that is greater than 0 bytes long, but du says: %s", actual) 988 } 989 } 990 991 func (s *DockerSuite) TestRunUnprivilegedWithChroot(c *check.C) { 992 // Not applicable on Windows as it does not support chroot 993 testRequires(c, DaemonIsLinux) 994 dockerCmd(c, "run", "busybox", "chroot", "/", "true") 995 } 996 997 func (s *DockerSuite) TestRunAddingOptionalDevices(c *check.C) { 998 // Not applicable on Windows as Windows does not support --device 999 testRequires(c, DaemonIsLinux, NotUserNamespace) 1000 out, _ := dockerCmd(c, "run", "--device", "/dev/zero:/dev/nulo", "busybox", "sh", "-c", "ls /dev/nulo") 1001 if actual := strings.Trim(out, "\r\n"); actual != "/dev/nulo" { 1002 c.Fatalf("expected output /dev/nulo, received %s", actual) 1003 } 1004 } 1005 1006 func (s *DockerSuite) TestRunAddingOptionalDevicesNoSrc(c *check.C) { 1007 // Not applicable on Windows as Windows does not support --device 1008 testRequires(c, DaemonIsLinux, NotUserNamespace) 1009 out, _ := dockerCmd(c, "run", "--device", "/dev/zero:rw", "busybox", "sh", "-c", "ls /dev/zero") 1010 if actual := strings.Trim(out, "\r\n"); actual != "/dev/zero" { 1011 c.Fatalf("expected output /dev/zero, received %s", actual) 1012 } 1013 } 1014 1015 func (s *DockerSuite) TestRunAddingOptionalDevicesInvalidMode(c *check.C) { 1016 // Not applicable on Windows as Windows does not support --device 1017 testRequires(c, DaemonIsLinux, NotUserNamespace) 1018 _, _, err := dockerCmdWithError("run", "--device", "/dev/zero:ro", "busybox", "sh", "-c", "ls /dev/zero") 1019 if err == nil { 1020 c.Fatalf("run container with device mode ro should fail") 1021 } 1022 } 1023 1024 func (s *DockerSuite) TestRunModeHostname(c *check.C) { 1025 // Not applicable on Windows as Windows does not support -h 1026 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace) 1027 1028 out, _ := dockerCmd(c, "run", "-h=testhostname", "busybox", "cat", "/etc/hostname") 1029 1030 if actual := strings.Trim(out, "\r\n"); actual != "testhostname" { 1031 c.Fatalf("expected 'testhostname', but says: %q", actual) 1032 } 1033 1034 out, _ = dockerCmd(c, "run", "--net=host", "busybox", "cat", "/etc/hostname") 1035 1036 hostname, err := os.Hostname() 1037 if err != nil { 1038 c.Fatal(err) 1039 } 1040 if actual := strings.Trim(out, "\r\n"); actual != hostname { 1041 c.Fatalf("expected %q, but says: %q", hostname, actual) 1042 } 1043 } 1044 1045 func (s *DockerSuite) TestRunRootWorkdir(c *check.C) { 1046 out, _ := dockerCmd(c, "run", "--workdir", "/", "busybox", "pwd") 1047 expected := "/\n" 1048 if daemonPlatform == "windows" { 1049 expected = "C:" + expected 1050 } 1051 if out != expected { 1052 c.Fatalf("pwd returned %q (expected %s)", s, expected) 1053 } 1054 } 1055 1056 func (s *DockerSuite) TestRunAllowBindMountingRoot(c *check.C) { 1057 if daemonPlatform == "windows" { 1058 // Windows busybox will fail with Permission Denied on items such as pagefile.sys 1059 dockerCmd(c, "run", "-v", `c:\:c:\host`, WindowsBaseImage, "cmd", "-c", "dir", `c:\host`) 1060 } else { 1061 dockerCmd(c, "run", "-v", "/:/host", "busybox", "ls", "/host") 1062 } 1063 } 1064 1065 func (s *DockerSuite) TestRunDisallowBindMountingRootToRoot(c *check.C) { 1066 mount := "/:/" 1067 targetDir := "/host" 1068 if daemonPlatform == "windows" { 1069 mount = `c:\:c\` 1070 targetDir = "c:/host" // Forward slash as using busybox 1071 } 1072 out, _, err := dockerCmdWithError("run", "-v", mount, "busybox", "ls", targetDir) 1073 if err == nil { 1074 c.Fatal(out, err) 1075 } 1076 } 1077 1078 // Verify that a container gets default DNS when only localhost resolvers exist 1079 func (s *DockerSuite) TestRunDnsDefaultOptions(c *check.C) { 1080 // Not applicable on Windows as this is testing Unix specific functionality 1081 testRequires(c, SameHostDaemon, DaemonIsLinux) 1082 1083 // preserve original resolv.conf for restoring after test 1084 origResolvConf, err := ioutil.ReadFile("/etc/resolv.conf") 1085 if os.IsNotExist(err) { 1086 c.Fatalf("/etc/resolv.conf does not exist") 1087 } 1088 // defer restored original conf 1089 defer func() { 1090 if err := ioutil.WriteFile("/etc/resolv.conf", origResolvConf, 0644); err != nil { 1091 c.Fatal(err) 1092 } 1093 }() 1094 1095 // test 3 cases: standard IPv4 localhost, commented out localhost, and IPv6 localhost 1096 // 2 are removed from the file at container start, and the 3rd (commented out) one is ignored by 1097 // GetNameservers(), leading to a replacement of nameservers with the default set 1098 tmpResolvConf := []byte("nameserver 127.0.0.1\n#nameserver 127.0.2.1\nnameserver ::1") 1099 if err := ioutil.WriteFile("/etc/resolv.conf", tmpResolvConf, 0644); err != nil { 1100 c.Fatal(err) 1101 } 1102 1103 actual, _ := dockerCmd(c, "run", "busybox", "cat", "/etc/resolv.conf") 1104 // check that the actual defaults are appended to the commented out 1105 // localhost resolver (which should be preserved) 1106 // NOTE: if we ever change the defaults from google dns, this will break 1107 expected := "#nameserver 127.0.2.1\n\nnameserver 8.8.8.8\nnameserver 8.8.4.4\n" 1108 if actual != expected { 1109 c.Fatalf("expected resolv.conf be: %q, but was: %q", expected, actual) 1110 } 1111 } 1112 1113 func (s *DockerSuite) TestRunDnsOptions(c *check.C) { 1114 // Not applicable on Windows as Windows does not support --dns*, or 1115 // the Unix-specific functionality of resolv.conf. 1116 testRequires(c, DaemonIsLinux) 1117 out, stderr, _ := dockerCmdWithStdoutStderr(c, "run", "--dns=127.0.0.1", "--dns-search=mydomain", "--dns-opt=ndots:9", "busybox", "cat", "/etc/resolv.conf") 1118 1119 // The client will get a warning on stderr when setting DNS to a localhost address; verify this: 1120 if !strings.Contains(stderr, "Localhost DNS setting") { 1121 c.Fatalf("Expected warning on stderr about localhost resolver, but got %q", stderr) 1122 } 1123 1124 actual := strings.Replace(strings.Trim(out, "\r\n"), "\n", " ", -1) 1125 if actual != "search mydomain nameserver 127.0.0.1 options ndots:9" { 1126 c.Fatalf("expected 'search mydomain nameserver 127.0.0.1 options ndots:9', but says: %q", actual) 1127 } 1128 1129 out, stderr, _ = dockerCmdWithStdoutStderr(c, "run", "--dns=127.0.0.1", "--dns-search=.", "--dns-opt=ndots:3", "busybox", "cat", "/etc/resolv.conf") 1130 1131 actual = strings.Replace(strings.Trim(strings.Trim(out, "\r\n"), " "), "\n", " ", -1) 1132 if actual != "nameserver 127.0.0.1 options ndots:3" { 1133 c.Fatalf("expected 'nameserver 127.0.0.1 options ndots:3', but says: %q", actual) 1134 } 1135 } 1136 1137 func (s *DockerSuite) TestRunDnsRepeatOptions(c *check.C) { 1138 testRequires(c, DaemonIsLinux) 1139 out, _, _ := dockerCmdWithStdoutStderr(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") 1140 1141 actual := strings.Replace(strings.Trim(out, "\r\n"), "\n", " ", -1) 1142 if actual != "search mydomain mydomain2 nameserver 1.1.1.1 nameserver 2.2.2.2 options ndots:9 timeout:3" { 1143 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) 1144 } 1145 } 1146 1147 func (s *DockerSuite) TestRunDnsOptionsBasedOnHostResolvConf(c *check.C) { 1148 // Not applicable on Windows as testing Unix specific functionality 1149 testRequires(c, SameHostDaemon, DaemonIsLinux) 1150 1151 origResolvConf, err := ioutil.ReadFile("/etc/resolv.conf") 1152 if os.IsNotExist(err) { 1153 c.Fatalf("/etc/resolv.conf does not exist") 1154 } 1155 1156 hostNamservers := resolvconf.GetNameservers(origResolvConf) 1157 hostSearch := resolvconf.GetSearchDomains(origResolvConf) 1158 1159 var out string 1160 out, _ = dockerCmd(c, "run", "--dns=127.0.0.1", "busybox", "cat", "/etc/resolv.conf") 1161 1162 if actualNameservers := resolvconf.GetNameservers([]byte(out)); string(actualNameservers[0]) != "127.0.0.1" { 1163 c.Fatalf("expected '127.0.0.1', but says: %q", string(actualNameservers[0])) 1164 } 1165 1166 actualSearch := resolvconf.GetSearchDomains([]byte(out)) 1167 if len(actualSearch) != len(hostSearch) { 1168 c.Fatalf("expected %q search domain(s), but it has: %q", len(hostSearch), len(actualSearch)) 1169 } 1170 for i := range actualSearch { 1171 if actualSearch[i] != hostSearch[i] { 1172 c.Fatalf("expected %q domain, but says: %q", actualSearch[i], hostSearch[i]) 1173 } 1174 } 1175 1176 out, _ = dockerCmd(c, "run", "--dns-search=mydomain", "busybox", "cat", "/etc/resolv.conf") 1177 1178 actualNameservers := resolvconf.GetNameservers([]byte(out)) 1179 if len(actualNameservers) != len(hostNamservers) { 1180 c.Fatalf("expected %q nameserver(s), but it has: %q", len(hostNamservers), len(actualNameservers)) 1181 } 1182 for i := range actualNameservers { 1183 if actualNameservers[i] != hostNamservers[i] { 1184 c.Fatalf("expected %q nameserver, but says: %q", actualNameservers[i], hostNamservers[i]) 1185 } 1186 } 1187 1188 if actualSearch = resolvconf.GetSearchDomains([]byte(out)); string(actualSearch[0]) != "mydomain" { 1189 c.Fatalf("expected 'mydomain', but says: %q", string(actualSearch[0])) 1190 } 1191 1192 // test with file 1193 tmpResolvConf := []byte("search example.com\nnameserver 12.34.56.78\nnameserver 127.0.0.1") 1194 if err := ioutil.WriteFile("/etc/resolv.conf", tmpResolvConf, 0644); err != nil { 1195 c.Fatal(err) 1196 } 1197 // put the old resolvconf back 1198 defer func() { 1199 if err := ioutil.WriteFile("/etc/resolv.conf", origResolvConf, 0644); err != nil { 1200 c.Fatal(err) 1201 } 1202 }() 1203 1204 resolvConf, err := ioutil.ReadFile("/etc/resolv.conf") 1205 if os.IsNotExist(err) { 1206 c.Fatalf("/etc/resolv.conf does not exist") 1207 } 1208 1209 hostNamservers = resolvconf.GetNameservers(resolvConf) 1210 hostSearch = resolvconf.GetSearchDomains(resolvConf) 1211 1212 out, _ = dockerCmd(c, "run", "busybox", "cat", "/etc/resolv.conf") 1213 if actualNameservers = resolvconf.GetNameservers([]byte(out)); string(actualNameservers[0]) != "12.34.56.78" || len(actualNameservers) != 1 { 1214 c.Fatalf("expected '12.34.56.78', but has: %v", actualNameservers) 1215 } 1216 1217 actualSearch = resolvconf.GetSearchDomains([]byte(out)) 1218 if len(actualSearch) != len(hostSearch) { 1219 c.Fatalf("expected %q search domain(s), but it has: %q", len(hostSearch), len(actualSearch)) 1220 } 1221 for i := range actualSearch { 1222 if actualSearch[i] != hostSearch[i] { 1223 c.Fatalf("expected %q domain, but says: %q", actualSearch[i], hostSearch[i]) 1224 } 1225 } 1226 } 1227 1228 // Test to see if a non-root user can resolve a DNS name. Also 1229 // check if the container resolv.conf file has at least 0644 perm. 1230 func (s *DockerSuite) TestRunNonRootUserResolvName(c *check.C) { 1231 // Not applicable on Windows as Windows does not support --user 1232 testRequires(c, SameHostDaemon, Network, DaemonIsLinux) 1233 1234 dockerCmd(c, "run", "--name=testperm", "--user=nobody", "busybox", "nslookup", "apt.dockerproject.org") 1235 1236 cID, err := getIDByName("testperm") 1237 if err != nil { 1238 c.Fatal(err) 1239 } 1240 1241 fmode := (os.FileMode)(0644) 1242 finfo, err := os.Stat(containerStorageFile(cID, "resolv.conf")) 1243 if err != nil { 1244 c.Fatal(err) 1245 } 1246 1247 if (finfo.Mode() & fmode) != fmode { 1248 c.Fatalf("Expected container resolv.conf mode to be at least %s, instead got %s", fmode.String(), finfo.Mode().String()) 1249 } 1250 } 1251 1252 // Test if container resolv.conf gets updated the next time it restarts 1253 // if host /etc/resolv.conf has changed. This only applies if the container 1254 // uses the host's /etc/resolv.conf and does not have any dns options provided. 1255 func (s *DockerSuite) TestRunResolvconfUpdate(c *check.C) { 1256 // Not applicable on Windows as testing unix specific functionality 1257 testRequires(c, SameHostDaemon, DaemonIsLinux) 1258 1259 tmpResolvConf := []byte("search pommesfrites.fr\nnameserver 12.34.56.78\n") 1260 tmpLocalhostResolvConf := []byte("nameserver 127.0.0.1") 1261 1262 //take a copy of resolv.conf for restoring after test completes 1263 resolvConfSystem, err := ioutil.ReadFile("/etc/resolv.conf") 1264 if err != nil { 1265 c.Fatal(err) 1266 } 1267 1268 // This test case is meant to test monitoring resolv.conf when it is 1269 // a regular file not a bind mounc. So we unmount resolv.conf and replace 1270 // it with a file containing the original settings. 1271 cmd := exec.Command("umount", "/etc/resolv.conf") 1272 if _, err = runCommand(cmd); err != nil { 1273 c.Fatal(err) 1274 } 1275 1276 //cleanup 1277 defer func() { 1278 if err := ioutil.WriteFile("/etc/resolv.conf", resolvConfSystem, 0644); err != nil { 1279 c.Fatal(err) 1280 } 1281 }() 1282 1283 //1. test that a restarting container gets an updated resolv.conf 1284 dockerCmd(c, "run", "--name='first'", "busybox", "true") 1285 containerID1, err := getIDByName("first") 1286 if err != nil { 1287 c.Fatal(err) 1288 } 1289 1290 // replace resolv.conf with our temporary copy 1291 bytesResolvConf := []byte(tmpResolvConf) 1292 if err := ioutil.WriteFile("/etc/resolv.conf", bytesResolvConf, 0644); err != nil { 1293 c.Fatal(err) 1294 } 1295 1296 // start the container again to pickup changes 1297 dockerCmd(c, "start", "first") 1298 1299 // check for update in container 1300 containerResolv, err := readContainerFile(containerID1, "resolv.conf") 1301 if err != nil { 1302 c.Fatal(err) 1303 } 1304 if !bytes.Equal(containerResolv, bytesResolvConf) { 1305 c.Fatalf("Restarted container does not have updated resolv.conf; expected %q, got %q", tmpResolvConf, string(containerResolv)) 1306 } 1307 1308 /* //make a change to resolv.conf (in this case replacing our tmp copy with orig copy) 1309 if err := ioutil.WriteFile("/etc/resolv.conf", resolvConfSystem, 0644); err != nil { 1310 c.Fatal(err) 1311 } */ 1312 //2. test that a restarting container does not receive resolv.conf updates 1313 // if it modified the container copy of the starting point resolv.conf 1314 dockerCmd(c, "run", "--name='second'", "busybox", "sh", "-c", "echo 'search mylittlepony.com' >>/etc/resolv.conf") 1315 containerID2, err := getIDByName("second") 1316 if err != nil { 1317 c.Fatal(err) 1318 } 1319 1320 //make a change to resolv.conf (in this case replacing our tmp copy with orig copy) 1321 if err := ioutil.WriteFile("/etc/resolv.conf", resolvConfSystem, 0644); err != nil { 1322 c.Fatal(err) 1323 } 1324 1325 // start the container again 1326 dockerCmd(c, "start", "second") 1327 1328 // check for update in container 1329 containerResolv, err = readContainerFile(containerID2, "resolv.conf") 1330 if err != nil { 1331 c.Fatal(err) 1332 } 1333 1334 if bytes.Equal(containerResolv, resolvConfSystem) { 1335 c.Fatalf("Container's resolv.conf should not have been updated with host resolv.conf: %q", string(containerResolv)) 1336 } 1337 1338 //3. test that a running container's resolv.conf is not modified while running 1339 out, _ := dockerCmd(c, "run", "-d", "busybox", "top") 1340 runningContainerID := strings.TrimSpace(out) 1341 1342 // replace resolv.conf 1343 if err := ioutil.WriteFile("/etc/resolv.conf", bytesResolvConf, 0644); err != nil { 1344 c.Fatal(err) 1345 } 1346 1347 // check for update in container 1348 containerResolv, err = readContainerFile(runningContainerID, "resolv.conf") 1349 if err != nil { 1350 c.Fatal(err) 1351 } 1352 1353 if bytes.Equal(containerResolv, bytesResolvConf) { 1354 c.Fatalf("Running container should not have updated resolv.conf; expected %q, got %q", string(resolvConfSystem), string(containerResolv)) 1355 } 1356 1357 //4. test that a running container's resolv.conf is updated upon restart 1358 // (the above container is still running..) 1359 dockerCmd(c, "restart", runningContainerID) 1360 1361 // check for update in container 1362 containerResolv, err = readContainerFile(runningContainerID, "resolv.conf") 1363 if err != nil { 1364 c.Fatal(err) 1365 } 1366 if !bytes.Equal(containerResolv, bytesResolvConf) { 1367 c.Fatalf("Restarted container should have updated resolv.conf; expected %q, got %q", string(bytesResolvConf), string(containerResolv)) 1368 } 1369 1370 //5. test that additions of a localhost resolver are cleaned from 1371 // host resolv.conf before updating container's resolv.conf copies 1372 1373 // replace resolv.conf with a localhost-only nameserver copy 1374 bytesResolvConf = []byte(tmpLocalhostResolvConf) 1375 if err = ioutil.WriteFile("/etc/resolv.conf", bytesResolvConf, 0644); err != nil { 1376 c.Fatal(err) 1377 } 1378 1379 // start the container again to pickup changes 1380 dockerCmd(c, "start", "first") 1381 1382 // our first exited container ID should have been updated, but with default DNS 1383 // after the cleanup of resolv.conf found only a localhost nameserver: 1384 containerResolv, err = readContainerFile(containerID1, "resolv.conf") 1385 if err != nil { 1386 c.Fatal(err) 1387 } 1388 1389 expected := "\nnameserver 8.8.8.8\nnameserver 8.8.4.4\n" 1390 if !bytes.Equal(containerResolv, []byte(expected)) { 1391 c.Fatalf("Container does not have cleaned/replaced DNS in resolv.conf; expected %q, got %q", expected, string(containerResolv)) 1392 } 1393 1394 //6. Test that replacing (as opposed to modifying) resolv.conf triggers an update 1395 // of containers' resolv.conf. 1396 1397 // Restore the original resolv.conf 1398 if err := ioutil.WriteFile("/etc/resolv.conf", resolvConfSystem, 0644); err != nil { 1399 c.Fatal(err) 1400 } 1401 1402 // Run the container so it picks up the old settings 1403 dockerCmd(c, "run", "--name='third'", "busybox", "true") 1404 containerID3, err := getIDByName("third") 1405 if err != nil { 1406 c.Fatal(err) 1407 } 1408 1409 // Create a modified resolv.conf.aside and override resolv.conf with it 1410 bytesResolvConf = []byte(tmpResolvConf) 1411 if err := ioutil.WriteFile("/etc/resolv.conf.aside", bytesResolvConf, 0644); err != nil { 1412 c.Fatal(err) 1413 } 1414 1415 err = os.Rename("/etc/resolv.conf.aside", "/etc/resolv.conf") 1416 if err != nil { 1417 c.Fatal(err) 1418 } 1419 1420 // start the container again to pickup changes 1421 dockerCmd(c, "start", "third") 1422 1423 // check for update in container 1424 containerResolv, err = readContainerFile(containerID3, "resolv.conf") 1425 if err != nil { 1426 c.Fatal(err) 1427 } 1428 if !bytes.Equal(containerResolv, bytesResolvConf) { 1429 c.Fatalf("Stopped container does not have updated resolv.conf; expected\n%q\n got\n%q", tmpResolvConf, string(containerResolv)) 1430 } 1431 1432 //cleanup, restore original resolv.conf happens in defer func() 1433 } 1434 1435 func (s *DockerSuite) TestRunAddHost(c *check.C) { 1436 // Not applicable on Windows as it does not support --add-host 1437 testRequires(c, DaemonIsLinux) 1438 out, _ := dockerCmd(c, "run", "--add-host=extra:86.75.30.9", "busybox", "grep", "extra", "/etc/hosts") 1439 1440 actual := strings.Trim(out, "\r\n") 1441 if actual != "86.75.30.9\textra" { 1442 c.Fatalf("expected '86.75.30.9\textra', but says: %q", actual) 1443 } 1444 } 1445 1446 // Regression test for #6983 1447 func (s *DockerSuite) TestRunAttachStdErrOnlyTTYMode(c *check.C) { 1448 _, exitCode := dockerCmd(c, "run", "-t", "-a", "stderr", "busybox", "true") 1449 if exitCode != 0 { 1450 c.Fatalf("Container should have exited with error code 0") 1451 } 1452 } 1453 1454 // Regression test for #6983 1455 func (s *DockerSuite) TestRunAttachStdOutOnlyTTYMode(c *check.C) { 1456 _, exitCode := dockerCmd(c, "run", "-t", "-a", "stdout", "busybox", "true") 1457 if exitCode != 0 { 1458 c.Fatalf("Container should have exited with error code 0") 1459 } 1460 } 1461 1462 // Regression test for #6983 1463 func (s *DockerSuite) TestRunAttachStdOutAndErrTTYMode(c *check.C) { 1464 _, exitCode := dockerCmd(c, "run", "-t", "-a", "stdout", "-a", "stderr", "busybox", "true") 1465 if exitCode != 0 { 1466 c.Fatalf("Container should have exited with error code 0") 1467 } 1468 } 1469 1470 // Test for #10388 - this will run the same test as TestRunAttachStdOutAndErrTTYMode 1471 // but using --attach instead of -a to make sure we read the flag correctly 1472 func (s *DockerSuite) TestRunAttachWithDetach(c *check.C) { 1473 cmd := exec.Command(dockerBinary, "run", "-d", "--attach", "stdout", "busybox", "true") 1474 _, stderr, _, err := runCommandWithStdoutStderr(cmd) 1475 if err == nil { 1476 c.Fatal("Container should have exited with error code different than 0") 1477 } else if !strings.Contains(stderr, "Conflicting options: -a and -d") { 1478 c.Fatal("Should have been returned an error with conflicting options -a and -d") 1479 } 1480 } 1481 1482 func (s *DockerSuite) TestRunState(c *check.C) { 1483 // TODO Windows: This needs some rework as Windows busybox does not support top 1484 testRequires(c, DaemonIsLinux) 1485 out, _ := dockerCmd(c, "run", "-d", "busybox", "top") 1486 1487 id := strings.TrimSpace(out) 1488 state, err := inspectField(id, "State.Running") 1489 c.Assert(err, check.IsNil) 1490 if state != "true" { 1491 c.Fatal("Container state is 'not running'") 1492 } 1493 pid1, err := inspectField(id, "State.Pid") 1494 c.Assert(err, check.IsNil) 1495 if pid1 == "0" { 1496 c.Fatal("Container state Pid 0") 1497 } 1498 1499 dockerCmd(c, "stop", id) 1500 state, err = inspectField(id, "State.Running") 1501 c.Assert(err, check.IsNil) 1502 if state != "false" { 1503 c.Fatal("Container state is 'running'") 1504 } 1505 pid2, err := inspectField(id, "State.Pid") 1506 c.Assert(err, check.IsNil) 1507 if pid2 == pid1 { 1508 c.Fatalf("Container state Pid %s, but expected %s", pid2, pid1) 1509 } 1510 1511 dockerCmd(c, "start", id) 1512 state, err = inspectField(id, "State.Running") 1513 c.Assert(err, check.IsNil) 1514 if state != "true" { 1515 c.Fatal("Container state is 'not running'") 1516 } 1517 pid3, err := inspectField(id, "State.Pid") 1518 c.Assert(err, check.IsNil) 1519 if pid3 == pid1 { 1520 c.Fatalf("Container state Pid %s, but expected %s", pid2, pid1) 1521 } 1522 } 1523 1524 // Test for #1737 1525 func (s *DockerSuite) TestRunCopyVolumeUidGid(c *check.C) { 1526 // Not applicable on Windows as it does not support uid or gid in this way 1527 testRequires(c, DaemonIsLinux) 1528 name := "testrunvolumesuidgid" 1529 _, err := buildImage(name, 1530 `FROM busybox 1531 RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd 1532 RUN echo 'dockerio:x:1001:' >> /etc/group 1533 RUN mkdir -p /hello && touch /hello/test && chown dockerio.dockerio /hello`, 1534 true) 1535 if err != nil { 1536 c.Fatal(err) 1537 } 1538 1539 // Test that the uid and gid is copied from the image to the volume 1540 out, _ := dockerCmd(c, "run", "--rm", "-v", "/hello", name, "sh", "-c", "ls -l / | grep hello | awk '{print $3\":\"$4}'") 1541 out = strings.TrimSpace(out) 1542 if out != "dockerio:dockerio" { 1543 c.Fatalf("Wrong /hello ownership: %s, expected dockerio:dockerio", out) 1544 } 1545 } 1546 1547 // Test for #1582 1548 func (s *DockerSuite) TestRunCopyVolumeContent(c *check.C) { 1549 // TODO Windows, post TP4. Windows does not yet support volume functionality 1550 // that copies from the image to the volume. 1551 testRequires(c, DaemonIsLinux) 1552 name := "testruncopyvolumecontent" 1553 _, err := buildImage(name, 1554 `FROM busybox 1555 RUN mkdir -p /hello/local && echo hello > /hello/local/world`, 1556 true) 1557 if err != nil { 1558 c.Fatal(err) 1559 } 1560 1561 // Test that the content is copied from the image to the volume 1562 out, _ := dockerCmd(c, "run", "--rm", "-v", "/hello", name, "find", "/hello") 1563 if !(strings.Contains(out, "/hello/local/world") && strings.Contains(out, "/hello/local")) { 1564 c.Fatal("Container failed to transfer content to volume") 1565 } 1566 } 1567 1568 func (s *DockerSuite) TestRunCleanupCmdOnEntrypoint(c *check.C) { 1569 name := "testrunmdcleanuponentrypoint" 1570 if _, err := buildImage(name, 1571 `FROM busybox 1572 ENTRYPOINT ["echo"] 1573 CMD ["testingpoint"]`, 1574 true); err != nil { 1575 c.Fatal(err) 1576 } 1577 1578 out, exit := dockerCmd(c, "run", "--entrypoint", "whoami", name) 1579 if exit != 0 { 1580 c.Fatalf("expected exit code 0 received %d, out: %q", exit, out) 1581 } 1582 out = strings.TrimSpace(out) 1583 expected := "root" 1584 if daemonPlatform == "windows" { 1585 expected = `nt authority\system` 1586 } 1587 if out != expected { 1588 c.Fatalf("Expected output %s, got %q", expected, out) 1589 } 1590 } 1591 1592 // TestRunWorkdirExistsAndIsFile checks that if 'docker run -w' with existing file can be detected 1593 func (s *DockerSuite) TestRunWorkdirExistsAndIsFile(c *check.C) { 1594 existingFile := "/bin/cat" 1595 expected := "Cannot mkdir: /bin/cat is not a directory" 1596 if daemonPlatform == "windows" { 1597 existingFile = `\windows\system32\ntdll.dll` 1598 expected = "The directory name is invalid" 1599 } 1600 1601 out, exitCode, err := dockerCmdWithError("run", "-w", existingFile, "busybox") 1602 if !(err != nil && exitCode == 125 && strings.Contains(out, expected)) { 1603 c.Fatalf("Docker must complains about making dir with exitCode 125 but we got out: %s, exitCode: %d", out, exitCode) 1604 } 1605 } 1606 1607 func (s *DockerSuite) TestRunExitOnStdinClose(c *check.C) { 1608 name := "testrunexitonstdinclose" 1609 1610 meow := "/bin/cat" 1611 delay := 1 1612 if daemonPlatform == "windows" { 1613 meow = "cat" 1614 delay = 5 1615 } 1616 runCmd := exec.Command(dockerBinary, "run", "--name", name, "-i", "busybox", meow) 1617 1618 stdin, err := runCmd.StdinPipe() 1619 if err != nil { 1620 c.Fatal(err) 1621 } 1622 stdout, err := runCmd.StdoutPipe() 1623 if err != nil { 1624 c.Fatal(err) 1625 } 1626 1627 if err := runCmd.Start(); err != nil { 1628 c.Fatal(err) 1629 } 1630 if _, err := stdin.Write([]byte("hello\n")); err != nil { 1631 c.Fatal(err) 1632 } 1633 1634 r := bufio.NewReader(stdout) 1635 line, err := r.ReadString('\n') 1636 if err != nil { 1637 c.Fatal(err) 1638 } 1639 line = strings.TrimSpace(line) 1640 if line != "hello" { 1641 c.Fatalf("Output should be 'hello', got '%q'", line) 1642 } 1643 if err := stdin.Close(); err != nil { 1644 c.Fatal(err) 1645 } 1646 finish := make(chan error) 1647 go func() { 1648 finish <- runCmd.Wait() 1649 close(finish) 1650 }() 1651 select { 1652 case err := <-finish: 1653 c.Assert(err, check.IsNil) 1654 case <-time.After(time.Duration(delay) * time.Second): 1655 c.Fatal("docker run failed to exit on stdin close") 1656 } 1657 state, err := inspectField(name, "State.Running") 1658 c.Assert(err, check.IsNil) 1659 1660 if state != "false" { 1661 c.Fatal("Container must be stopped after stdin closing") 1662 } 1663 } 1664 1665 // Test for #2267 1666 func (s *DockerSuite) TestRunWriteHostsFileAndNotCommit(c *check.C) { 1667 // Cannot run on Windows as Windows does not support diff. 1668 testRequires(c, DaemonIsLinux) 1669 name := "writehosts" 1670 out, _ := dockerCmd(c, "run", "--name", name, "busybox", "sh", "-c", "echo test2267 >> /etc/hosts && cat /etc/hosts") 1671 if !strings.Contains(out, "test2267") { 1672 c.Fatal("/etc/hosts should contain 'test2267'") 1673 } 1674 1675 out, _ = dockerCmd(c, "diff", name) 1676 if len(strings.Trim(out, "\r\n")) != 0 && !eqToBaseDiff(out, c) { 1677 c.Fatal("diff should be empty") 1678 } 1679 } 1680 1681 func eqToBaseDiff(out string, c *check.C) bool { 1682 out1, _ := dockerCmd(c, "run", "-d", "busybox", "echo", "hello") 1683 cID := strings.TrimSpace(out1) 1684 1685 baseDiff, _ := dockerCmd(c, "diff", cID) 1686 baseArr := strings.Split(baseDiff, "\n") 1687 sort.Strings(baseArr) 1688 outArr := strings.Split(out, "\n") 1689 sort.Strings(outArr) 1690 return sliceEq(baseArr, outArr) 1691 } 1692 1693 func sliceEq(a, b []string) bool { 1694 if len(a) != len(b) { 1695 return false 1696 } 1697 1698 for i := range a { 1699 if a[i] != b[i] { 1700 return false 1701 } 1702 } 1703 1704 return true 1705 } 1706 1707 // Test for #2267 1708 func (s *DockerSuite) TestRunWriteHostnameFileAndNotCommit(c *check.C) { 1709 // Cannot run on Windows as Windows does not support diff. 1710 testRequires(c, DaemonIsLinux) 1711 name := "writehostname" 1712 out, _ := dockerCmd(c, "run", "--name", name, "busybox", "sh", "-c", "echo test2267 >> /etc/hostname && cat /etc/hostname") 1713 if !strings.Contains(out, "test2267") { 1714 c.Fatal("/etc/hostname should contain 'test2267'") 1715 } 1716 1717 out, _ = dockerCmd(c, "diff", name) 1718 if len(strings.Trim(out, "\r\n")) != 0 && !eqToBaseDiff(out, c) { 1719 c.Fatal("diff should be empty") 1720 } 1721 } 1722 1723 // Test for #2267 1724 func (s *DockerSuite) TestRunWriteResolvFileAndNotCommit(c *check.C) { 1725 // Cannot run on Windows as Windows does not support diff. 1726 testRequires(c, DaemonIsLinux) 1727 name := "writeresolv" 1728 out, _ := dockerCmd(c, "run", "--name", name, "busybox", "sh", "-c", "echo test2267 >> /etc/resolv.conf && cat /etc/resolv.conf") 1729 if !strings.Contains(out, "test2267") { 1730 c.Fatal("/etc/resolv.conf should contain 'test2267'") 1731 } 1732 1733 out, _ = dockerCmd(c, "diff", name) 1734 if len(strings.Trim(out, "\r\n")) != 0 && !eqToBaseDiff(out, c) { 1735 c.Fatal("diff should be empty") 1736 } 1737 } 1738 1739 func (s *DockerSuite) TestRunWithBadDevice(c *check.C) { 1740 // Cannot run on Windows as Windows does not support --device 1741 testRequires(c, DaemonIsLinux) 1742 name := "baddevice" 1743 out, _, err := dockerCmdWithError("run", "--name", name, "--device", "/etc", "busybox", "true") 1744 1745 if err == nil { 1746 c.Fatal("Run should fail with bad device") 1747 } 1748 expected := `"/etc": not a device node` 1749 if !strings.Contains(out, expected) { 1750 c.Fatalf("Output should contain %q, actual out: %q", expected, out) 1751 } 1752 } 1753 1754 func (s *DockerSuite) TestRunEntrypoint(c *check.C) { 1755 name := "entrypoint" 1756 1757 // Note Windows does not have an echo.exe built in. 1758 var out, expected string 1759 if daemonPlatform == "windows" { 1760 out, _ = dockerCmd(c, "run", "--name", name, "--entrypoint", "cmd /s /c echo", "busybox", "foobar") 1761 expected = "foobar\r\n" 1762 } else { 1763 out, _ = dockerCmd(c, "run", "--name", name, "--entrypoint", "/bin/echo", "busybox", "-n", "foobar") 1764 expected = "foobar" 1765 } 1766 1767 if out != expected { 1768 c.Fatalf("Output should be %q, actual out: %q", expected, out) 1769 } 1770 } 1771 1772 func (s *DockerSuite) TestRunBindMounts(c *check.C) { 1773 testRequires(c, SameHostDaemon) 1774 if daemonPlatform == "linux" { 1775 testRequires(c, DaemonIsLinux, NotUserNamespace) 1776 } 1777 1778 tmpDir, err := ioutil.TempDir("", "docker-test-container") 1779 if err != nil { 1780 c.Fatal(err) 1781 } 1782 1783 defer os.RemoveAll(tmpDir) 1784 writeFile(path.Join(tmpDir, "touch-me"), "", c) 1785 1786 // TODO Windows Post TP4. Windows does not yet support :ro binds 1787 if daemonPlatform != "windows" { 1788 // Test reading from a read-only bind mount 1789 out, _ := dockerCmd(c, "run", "-v", fmt.Sprintf("%s:/tmp:ro", tmpDir), "busybox", "ls", "/tmp") 1790 if !strings.Contains(out, "touch-me") { 1791 c.Fatal("Container failed to read from bind mount") 1792 } 1793 } 1794 1795 // test writing to bind mount 1796 if daemonPlatform == "windows" { 1797 dockerCmd(c, "run", "-v", fmt.Sprintf(`%s:c:\tmp:rw`, tmpDir), "busybox", "touch", "c:/tmp/holla") 1798 } else { 1799 dockerCmd(c, "run", "-v", fmt.Sprintf("%s:/tmp:rw", tmpDir), "busybox", "touch", "/tmp/holla") 1800 } 1801 1802 readFile(path.Join(tmpDir, "holla"), c) // Will fail if the file doesn't exist 1803 1804 // test mounting to an illegal destination directory 1805 _, _, err = dockerCmdWithError("run", "-v", fmt.Sprintf("%s:.", tmpDir), "busybox", "ls", ".") 1806 if err == nil { 1807 c.Fatal("Container bind mounted illegal directory") 1808 } 1809 1810 // Windows does not (and likely never will) support mounting a single file 1811 if daemonPlatform != "windows" { 1812 // test mount a file 1813 dockerCmd(c, "run", "-v", fmt.Sprintf("%s/holla:/tmp/holla:rw", tmpDir), "busybox", "sh", "-c", "echo -n 'yotta' > /tmp/holla") 1814 content := readFile(path.Join(tmpDir, "holla"), c) // Will fail if the file doesn't exist 1815 expected := "yotta" 1816 if content != expected { 1817 c.Fatalf("Output should be %q, actual out: %q", expected, content) 1818 } 1819 } 1820 } 1821 1822 // Ensure that CIDFile gets deleted if it's empty 1823 // Perform this test by making `docker run` fail 1824 func (s *DockerSuite) TestRunCidFileCleanupIfEmpty(c *check.C) { 1825 tmpDir, err := ioutil.TempDir("", "TestRunCidFile") 1826 if err != nil { 1827 c.Fatal(err) 1828 } 1829 defer os.RemoveAll(tmpDir) 1830 tmpCidFile := path.Join(tmpDir, "cid") 1831 1832 image := "emptyfs" 1833 if daemonPlatform == "windows" { 1834 // Windows can't support an emptyfs image. Just use the regular Windows image 1835 image = WindowsBaseImage 1836 } 1837 out, _, err := dockerCmdWithError("run", "--cidfile", tmpCidFile, image) 1838 if err == nil { 1839 c.Fatalf("Run without command must fail. out=%s", out) 1840 } else if !strings.Contains(out, "No command specified") { 1841 c.Fatalf("Run without command failed with wrong output. out=%s\nerr=%v", out, err) 1842 } 1843 1844 if _, err := os.Stat(tmpCidFile); err == nil { 1845 c.Fatalf("empty CIDFile %q should've been deleted", tmpCidFile) 1846 } 1847 } 1848 1849 // #2098 - Docker cidFiles only contain short version of the containerId 1850 //sudo docker run --cidfile /tmp/docker_tesc.cid ubuntu echo "test" 1851 // TestRunCidFile tests that run --cidfile returns the longid 1852 func (s *DockerSuite) TestRunCidFileCheckIDLength(c *check.C) { 1853 tmpDir, err := ioutil.TempDir("", "TestRunCidFile") 1854 if err != nil { 1855 c.Fatal(err) 1856 } 1857 tmpCidFile := path.Join(tmpDir, "cid") 1858 defer os.RemoveAll(tmpDir) 1859 1860 out, _ := dockerCmd(c, "run", "-d", "--cidfile", tmpCidFile, "busybox", "true") 1861 1862 id := strings.TrimSpace(out) 1863 buffer, err := ioutil.ReadFile(tmpCidFile) 1864 if err != nil { 1865 c.Fatal(err) 1866 } 1867 cid := string(buffer) 1868 if len(cid) != 64 { 1869 c.Fatalf("--cidfile should be a long id, not %q", id) 1870 } 1871 if cid != id { 1872 c.Fatalf("cid must be equal to %s, got %s", id, cid) 1873 } 1874 } 1875 1876 func (s *DockerSuite) TestRunSetMacAddress(c *check.C) { 1877 mac := "12:34:56:78:9a:bc" 1878 var out string 1879 if daemonPlatform == "windows" { 1880 out, _ = dockerCmd(c, "run", "-i", "--rm", fmt.Sprintf("--mac-address=%s", mac), "busybox", "sh", "-c", "ipconfig /all | grep 'Physical Address' | awk '{print $12}'") 1881 mac = strings.Replace(strings.ToUpper(mac), ":", "-", -1) // To Windows-style MACs 1882 } else { 1883 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}'") 1884 } 1885 1886 actualMac := strings.TrimSpace(out) 1887 if actualMac != mac { 1888 c.Fatalf("Set MAC address with --mac-address failed. The container has an incorrect MAC address: %q, expected: %q", actualMac, mac) 1889 } 1890 } 1891 1892 func (s *DockerSuite) TestRunInspectMacAddress(c *check.C) { 1893 // TODO Windows. Network settings are not propagated back to inspect. 1894 testRequires(c, DaemonIsLinux) 1895 mac := "12:34:56:78:9a:bc" 1896 out, _ := dockerCmd(c, "run", "-d", "--mac-address="+mac, "busybox", "top") 1897 1898 id := strings.TrimSpace(out) 1899 inspectedMac, err := inspectField(id, "NetworkSettings.Networks.bridge.MacAddress") 1900 c.Assert(err, check.IsNil) 1901 if inspectedMac != mac { 1902 c.Fatalf("docker inspect outputs wrong MAC address: %q, should be: %q", inspectedMac, mac) 1903 } 1904 } 1905 1906 // test docker run use a invalid mac address 1907 func (s *DockerSuite) TestRunWithInvalidMacAddress(c *check.C) { 1908 out, _, err := dockerCmdWithError("run", "--mac-address", "92:d0:c6:0a:29", "busybox") 1909 //use a invalid mac address should with a error out 1910 if err == nil || !strings.Contains(out, "is not a valid mac address") { 1911 c.Fatalf("run with an invalid --mac-address should with error out") 1912 } 1913 } 1914 1915 func (s *DockerSuite) TestRunDeallocatePortOnMissingIptablesRule(c *check.C) { 1916 // TODO Windows. Network settings are not propagated back to inspect. 1917 testRequires(c, SameHostDaemon, DaemonIsLinux) 1918 1919 out, _ := dockerCmd(c, "run", "-d", "-p", "23:23", "busybox", "top") 1920 1921 id := strings.TrimSpace(out) 1922 ip, err := inspectField(id, "NetworkSettings.Networks.bridge.IPAddress") 1923 c.Assert(err, check.IsNil) 1924 iptCmd := exec.Command("iptables", "-D", "DOCKER", "-d", fmt.Sprintf("%s/32", ip), 1925 "!", "-i", "docker0", "-o", "docker0", "-p", "tcp", "-m", "tcp", "--dport", "23", "-j", "ACCEPT") 1926 out, _, err = runCommandWithOutput(iptCmd) 1927 if err != nil { 1928 c.Fatal(err, out) 1929 } 1930 if err := deleteContainer(id); err != nil { 1931 c.Fatal(err) 1932 } 1933 1934 dockerCmd(c, "run", "-d", "-p", "23:23", "busybox", "top") 1935 } 1936 1937 func (s *DockerSuite) TestRunPortInUse(c *check.C) { 1938 // TODO Windows. The duplicate NAT message returned by Windows will be 1939 // changing as is currently completely undecipherable. Does need modifying 1940 // to run sh rather than top though as top isn't in Windows busybox. 1941 testRequires(c, SameHostDaemon, DaemonIsLinux) 1942 1943 port := "1234" 1944 dockerCmd(c, "run", "-d", "-p", port+":80", "busybox", "top") 1945 1946 out, _, err := dockerCmdWithError("run", "-d", "-p", port+":80", "busybox", "top") 1947 if err == nil { 1948 c.Fatalf("Binding on used port must fail") 1949 } 1950 if !strings.Contains(out, "port is already allocated") { 1951 c.Fatalf("Out must be about \"port is already allocated\", got %s", out) 1952 } 1953 } 1954 1955 // https://github.com/docker/docker/issues/12148 1956 func (s *DockerSuite) TestRunAllocatePortInReservedRange(c *check.C) { 1957 // TODO Windows. -P is not yet supported 1958 testRequires(c, DaemonIsLinux) 1959 // allocate a dynamic port to get the most recent 1960 out, _ := dockerCmd(c, "run", "-d", "-P", "-p", "80", "busybox", "top") 1961 1962 id := strings.TrimSpace(out) 1963 out, _ = dockerCmd(c, "port", id, "80") 1964 1965 strPort := strings.Split(strings.TrimSpace(out), ":")[1] 1966 port, err := strconv.ParseInt(strPort, 10, 64) 1967 if err != nil { 1968 c.Fatalf("invalid port, got: %s, error: %s", strPort, err) 1969 } 1970 1971 // allocate a static port and a dynamic port together, with static port 1972 // takes the next recent port in dynamic port range. 1973 dockerCmd(c, "run", "-d", "-P", "-p", "80", "-p", fmt.Sprintf("%d:8080", port+1), "busybox", "top") 1974 } 1975 1976 // Regression test for #7792 1977 func (s *DockerSuite) TestRunMountOrdering(c *check.C) { 1978 // TODO Windows: Post TP4. Updated, but Windows does not support nested mounts currently. 1979 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace) 1980 prefix := "" 1981 if daemonPlatform == "windows" { 1982 prefix = "c:" 1983 } 1984 1985 tmpDir, err := ioutil.TempDir("", "docker_nested_mount_test") 1986 if err != nil { 1987 c.Fatal(err) 1988 } 1989 defer os.RemoveAll(tmpDir) 1990 1991 tmpDir2, err := ioutil.TempDir("", "docker_nested_mount_test2") 1992 if err != nil { 1993 c.Fatal(err) 1994 } 1995 defer os.RemoveAll(tmpDir2) 1996 1997 // Create a temporary tmpfs mounc. 1998 fooDir := filepath.Join(tmpDir, "foo") 1999 if err := os.MkdirAll(filepath.Join(tmpDir, "foo"), 0755); err != nil { 2000 c.Fatalf("failed to mkdir at %s - %s", fooDir, err) 2001 } 2002 2003 if err := ioutil.WriteFile(fmt.Sprintf("%s/touch-me", fooDir), []byte{}, 0644); err != nil { 2004 c.Fatal(err) 2005 } 2006 2007 if err := ioutil.WriteFile(fmt.Sprintf("%s/touch-me", tmpDir), []byte{}, 0644); err != nil { 2008 c.Fatal(err) 2009 } 2010 2011 if err := ioutil.WriteFile(fmt.Sprintf("%s/touch-me", tmpDir2), []byte{}, 0644); err != nil { 2012 c.Fatal(err) 2013 } 2014 2015 dockerCmd(c, "run", 2016 "-v", fmt.Sprintf("%s:"+prefix+"/tmp", tmpDir), 2017 "-v", fmt.Sprintf("%s:"+prefix+"/tmp/foo", fooDir), 2018 "-v", fmt.Sprintf("%s:"+prefix+"/tmp/tmp2", tmpDir2), 2019 "-v", fmt.Sprintf("%s:"+prefix+"/tmp/tmp2/foo", fooDir), 2020 "busybox:latest", "sh", "-c", 2021 "ls "+prefix+"/tmp/touch-me && ls "+prefix+"/tmp/foo/touch-me && ls "+prefix+"/tmp/tmp2/touch-me && ls "+prefix+"/tmp/tmp2/foo/touch-me") 2022 } 2023 2024 // Regression test for https://github.com/docker/docker/issues/8259 2025 func (s *DockerSuite) TestRunReuseBindVolumeThatIsSymlink(c *check.C) { 2026 // Not applicable on Windows as Windows does not support volumes 2027 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace) 2028 prefix := "" 2029 if daemonPlatform == "windows" { 2030 prefix = "c:" 2031 } 2032 2033 tmpDir, err := ioutil.TempDir(os.TempDir(), "testlink") 2034 if err != nil { 2035 c.Fatal(err) 2036 } 2037 defer os.RemoveAll(tmpDir) 2038 2039 linkPath := os.TempDir() + "/testlink2" 2040 if err := os.Symlink(tmpDir, linkPath); err != nil { 2041 c.Fatal(err) 2042 } 2043 defer os.RemoveAll(linkPath) 2044 2045 // Create first container 2046 dockerCmd(c, "run", "-v", fmt.Sprintf("%s:"+prefix+"/tmp/test", linkPath), "busybox", "ls", prefix+"/tmp/test") 2047 2048 // Create second container with same symlinked path 2049 // This will fail if the referenced issue is hit with a "Volume exists" error 2050 dockerCmd(c, "run", "-v", fmt.Sprintf("%s:"+prefix+"/tmp/test", linkPath), "busybox", "ls", prefix+"/tmp/test") 2051 } 2052 2053 //GH#10604: Test an "/etc" volume doesn't overlay special bind mounts in container 2054 func (s *DockerSuite) TestRunCreateVolumeEtc(c *check.C) { 2055 // While Windows supports volumes, it does not support --add-host hence 2056 // this test is not applicable on Windows. 2057 testRequires(c, DaemonIsLinux) 2058 out, _ := dockerCmd(c, "run", "--dns=127.0.0.1", "-v", "/etc", "busybox", "cat", "/etc/resolv.conf") 2059 if !strings.Contains(out, "nameserver 127.0.0.1") { 2060 c.Fatal("/etc volume mount hides /etc/resolv.conf") 2061 } 2062 2063 out, _ = dockerCmd(c, "run", "-h=test123", "-v", "/etc", "busybox", "cat", "/etc/hostname") 2064 if !strings.Contains(out, "test123") { 2065 c.Fatal("/etc volume mount hides /etc/hostname") 2066 } 2067 2068 out, _ = dockerCmd(c, "run", "--add-host=test:192.168.0.1", "-v", "/etc", "busybox", "cat", "/etc/hosts") 2069 out = strings.Replace(out, "\n", " ", -1) 2070 if !strings.Contains(out, "192.168.0.1\ttest") || !strings.Contains(out, "127.0.0.1\tlocalhost") { 2071 c.Fatal("/etc volume mount hides /etc/hosts") 2072 } 2073 } 2074 2075 func (s *DockerSuite) TestVolumesNoCopyData(c *check.C) { 2076 // TODO Windows (Post TP4). Windows does not support volumes which 2077 // are pre-populated such as is built in the dockerfile used in this test. 2078 testRequires(c, DaemonIsLinux) 2079 if _, err := buildImage("dataimage", 2080 `FROM busybox 2081 RUN mkdir -p /foo 2082 RUN touch /foo/bar`, 2083 true); err != nil { 2084 c.Fatal(err) 2085 } 2086 2087 dockerCmd(c, "run", "--name", "test", "-v", "/foo", "busybox") 2088 2089 if out, _, err := dockerCmdWithError("run", "--volumes-from", "test", "dataimage", "ls", "-lh", "/foo/bar"); err == nil || !strings.Contains(out, "No such file or directory") { 2090 c.Fatalf("Data was copied on volumes-from but shouldn't be:\n%q", out) 2091 } 2092 2093 tmpDir := randomTmpDirPath("docker_test_bind_mount_copy_data", daemonPlatform) 2094 if out, _, err := dockerCmdWithError("run", "-v", tmpDir+":/foo", "dataimage", "ls", "-lh", "/foo/bar"); err == nil || !strings.Contains(out, "No such file or directory") { 2095 c.Fatalf("Data was copied on bind-mount but shouldn't be:\n%q", out) 2096 } 2097 } 2098 2099 func (s *DockerSuite) TestRunNoOutputFromPullInStdout(c *check.C) { 2100 // just run with unknown image 2101 cmd := exec.Command(dockerBinary, "run", "asdfsg") 2102 stdout := bytes.NewBuffer(nil) 2103 cmd.Stdout = stdout 2104 if err := cmd.Run(); err == nil { 2105 c.Fatal("Run with unknown image should fail") 2106 } 2107 if stdout.Len() != 0 { 2108 c.Fatalf("Stdout contains output from pull: %s", stdout) 2109 } 2110 } 2111 2112 func (s *DockerSuite) TestRunVolumesCleanPaths(c *check.C) { 2113 testRequires(c, SameHostDaemon) 2114 prefix := "" 2115 slash := `/` 2116 if daemonPlatform == "windows" { 2117 prefix = "c:" 2118 slash = `\` 2119 } 2120 if _, err := buildImage("run_volumes_clean_paths", 2121 `FROM busybox 2122 VOLUME `+prefix+`/foo/`, 2123 true); err != nil { 2124 c.Fatal(err) 2125 } 2126 2127 dockerCmd(c, "run", "-v", prefix+"/foo", "-v", prefix+"/bar/", "--name", "dark_helmet", "run_volumes_clean_paths") 2128 2129 out, err := inspectMountSourceField("dark_helmet", prefix+slash+"foo"+slash) 2130 if err != errMountNotFound { 2131 c.Fatalf("Found unexpected volume entry for '%s/foo/' in volumes\n%q", prefix, out) 2132 } 2133 2134 out, err = inspectMountSourceField("dark_helmet", prefix+slash+`foo`) 2135 c.Assert(err, check.IsNil) 2136 if !strings.Contains(strings.ToLower(out), strings.ToLower(volumesConfigPath)) { 2137 c.Fatalf("Volume was not defined for %s/foo\n%q", prefix, out) 2138 } 2139 2140 out, err = inspectMountSourceField("dark_helmet", prefix+slash+"bar"+slash) 2141 if err != errMountNotFound { 2142 c.Fatalf("Found unexpected volume entry for '%s/bar/' in volumes\n%q", prefix, out) 2143 } 2144 2145 out, err = inspectMountSourceField("dark_helmet", prefix+slash+"bar") 2146 c.Assert(err, check.IsNil) 2147 if !strings.Contains(strings.ToLower(out), strings.ToLower(volumesConfigPath)) { 2148 c.Fatalf("Volume was not defined for %s/bar\n%q", prefix, out) 2149 } 2150 } 2151 2152 // Regression test for #3631 2153 func (s *DockerSuite) TestRunSlowStdoutConsumer(c *check.C) { 2154 // TODO Windows: This should be able to run on Windows if can find an 2155 // alternate to /dev/zero and /dev/stdout. 2156 testRequires(c, DaemonIsLinux) 2157 cont := exec.Command(dockerBinary, "run", "--rm", "busybox", "/bin/sh", "-c", "dd if=/dev/zero of=/dev/stdout bs=1024 count=2000 | catv") 2158 2159 stdout, err := cont.StdoutPipe() 2160 if err != nil { 2161 c.Fatal(err) 2162 } 2163 2164 if err := cont.Start(); err != nil { 2165 c.Fatal(err) 2166 } 2167 n, err := consumeWithSpeed(stdout, 10000, 5*time.Millisecond, nil) 2168 if err != nil { 2169 c.Fatal(err) 2170 } 2171 2172 expected := 2 * 1024 * 2000 2173 if n != expected { 2174 c.Fatalf("Expected %d, got %d", expected, n) 2175 } 2176 } 2177 2178 func (s *DockerSuite) TestRunAllowPortRangeThroughExpose(c *check.C) { 2179 // TODO Windows: -P is not currently supported. Also network 2180 // settings are not propagated back. 2181 testRequires(c, DaemonIsLinux) 2182 out, _ := dockerCmd(c, "run", "-d", "--expose", "3000-3003", "-P", "busybox", "top") 2183 2184 id := strings.TrimSpace(out) 2185 portstr, err := inspectFieldJSON(id, "NetworkSettings.Ports") 2186 c.Assert(err, check.IsNil) 2187 var ports nat.PortMap 2188 if err = unmarshalJSON([]byte(portstr), &ports); err != nil { 2189 c.Fatal(err) 2190 } 2191 for port, binding := range ports { 2192 portnum, _ := strconv.Atoi(strings.Split(string(port), "/")[0]) 2193 if portnum < 3000 || portnum > 3003 { 2194 c.Fatalf("Port %d is out of range ", portnum) 2195 } 2196 if binding == nil || len(binding) != 1 || len(binding[0].HostPort) == 0 { 2197 c.Fatalf("Port is not mapped for the port %s", port) 2198 } 2199 } 2200 } 2201 2202 // test docker run expose a invalid port 2203 func (s *DockerSuite) TestRunExposePort(c *check.C) { 2204 out, _, err := dockerCmdWithError("run", "--expose", "80000", "busybox") 2205 //expose a invalid port should with a error out 2206 if err == nil || !strings.Contains(out, "Invalid range format for --expose") { 2207 c.Fatalf("run --expose a invalid port should with error out") 2208 } 2209 } 2210 2211 func (s *DockerSuite) TestRunUnknownCommand(c *check.C) { 2212 out, _, _ := dockerCmdWithStdoutStderr(c, "create", "busybox", "/bin/nada") 2213 2214 cID := strings.TrimSpace(out) 2215 _, _, err := dockerCmdWithError("start", cID) 2216 2217 // Windows and Linux are different here by architectural design. Linux will 2218 // fail to start the container, so an error is expected. Windows will 2219 // successfully start the container, and once started attempt to execute 2220 // the command which will fail. 2221 if daemonPlatform == "windows" { 2222 // Wait for it to exit. 2223 waitExited(cID, 30*time.Second) 2224 c.Assert(err, check.IsNil) 2225 } else { 2226 c.Assert(err, check.NotNil) 2227 } 2228 2229 rc, err := inspectField(cID, "State.ExitCode") 2230 c.Assert(err, check.IsNil) 2231 if rc == "0" { 2232 c.Fatalf("ExitCode(%v) cannot be 0", rc) 2233 } 2234 } 2235 2236 func (s *DockerSuite) TestRunModeIpcHost(c *check.C) { 2237 // Not applicable on Windows as uses Unix-specific capabilities 2238 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace) 2239 2240 hostIpc, err := os.Readlink("/proc/1/ns/ipc") 2241 if err != nil { 2242 c.Fatal(err) 2243 } 2244 2245 out, _ := dockerCmd(c, "run", "--ipc=host", "busybox", "readlink", "/proc/self/ns/ipc") 2246 out = strings.Trim(out, "\n") 2247 if hostIpc != out { 2248 c.Fatalf("IPC different with --ipc=host %s != %s\n", hostIpc, out) 2249 } 2250 2251 out, _ = dockerCmd(c, "run", "busybox", "readlink", "/proc/self/ns/ipc") 2252 out = strings.Trim(out, "\n") 2253 if hostIpc == out { 2254 c.Fatalf("IPC should be different without --ipc=host %s == %s\n", hostIpc, out) 2255 } 2256 } 2257 2258 func (s *DockerSuite) TestRunModeIpcContainer(c *check.C) { 2259 // Not applicable on Windows as uses Unix-specific capabilities 2260 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace) 2261 2262 out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", "echo -n test > /dev/shm/test && top") 2263 2264 id := strings.TrimSpace(out) 2265 state, err := inspectField(id, "State.Running") 2266 c.Assert(err, check.IsNil) 2267 if state != "true" { 2268 c.Fatal("Container state is 'not running'") 2269 } 2270 pid1, err := inspectField(id, "State.Pid") 2271 c.Assert(err, check.IsNil) 2272 2273 parentContainerIpc, err := os.Readlink(fmt.Sprintf("/proc/%s/ns/ipc", pid1)) 2274 if err != nil { 2275 c.Fatal(err) 2276 } 2277 2278 out, _ = dockerCmd(c, "run", fmt.Sprintf("--ipc=container:%s", id), "busybox", "readlink", "/proc/self/ns/ipc") 2279 out = strings.Trim(out, "\n") 2280 if parentContainerIpc != out { 2281 c.Fatalf("IPC different with --ipc=container:%s %s != %s\n", id, parentContainerIpc, out) 2282 } 2283 2284 catOutput, _ := dockerCmd(c, "run", fmt.Sprintf("--ipc=container:%s", id), "busybox", "cat", "/dev/shm/test") 2285 if catOutput != "test" { 2286 c.Fatalf("Output of /dev/shm/test expected test but found: %s", catOutput) 2287 } 2288 } 2289 2290 func (s *DockerSuite) TestRunModeIpcContainerNotExists(c *check.C) { 2291 // Not applicable on Windows as uses Unix-specific capabilities 2292 testRequires(c, DaemonIsLinux, NotUserNamespace) 2293 out, _, err := dockerCmdWithError("run", "-d", "--ipc", "container:abcd1234", "busybox", "top") 2294 if !strings.Contains(out, "abcd1234") || err == nil { 2295 c.Fatalf("run IPC from a non exists container should with correct error out") 2296 } 2297 } 2298 2299 func (s *DockerSuite) TestRunModeIpcContainerNotRunning(c *check.C) { 2300 // Not applicable on Windows as uses Unix-specific capabilities 2301 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace) 2302 2303 out, _ := dockerCmd(c, "create", "busybox") 2304 2305 id := strings.TrimSpace(out) 2306 out, _, err := dockerCmdWithError("run", fmt.Sprintf("--ipc=container:%s", id), "busybox") 2307 if err == nil { 2308 c.Fatalf("Run container with ipc mode container should fail with non running container: %s\n%s", out, err) 2309 } 2310 } 2311 2312 func (s *DockerSuite) TestRunMountShmMqueueFromHost(c *check.C) { 2313 // Not applicable on Windows as uses Unix-specific capabilities 2314 testRequires(c, SameHostDaemon, DaemonIsLinux) 2315 2316 dockerCmd(c, "run", "-d", "--name", "shmfromhost", "-v", "/dev/shm:/dev/shm", "busybox", "sh", "-c", "echo -n test > /dev/shm/test && top") 2317 volPath, err := inspectMountSourceField("shmfromhost", "/dev/shm") 2318 c.Assert(err, check.IsNil) 2319 if volPath != "/dev/shm" { 2320 c.Fatalf("volumePath should have been /dev/shm, was %s", volPath) 2321 } 2322 2323 out, _ := dockerCmd(c, "run", "--name", "ipchost", "--ipc", "host", "busybox", "cat", "/dev/shm/test") 2324 if out != "test" { 2325 c.Fatalf("Output of /dev/shm/test expected test but found: %s", out) 2326 } 2327 } 2328 2329 func (s *DockerSuite) TestContainerNetworkMode(c *check.C) { 2330 // Not applicable on Windows as uses Unix-specific capabilities 2331 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace) 2332 2333 out, _ := dockerCmd(c, "run", "-d", "busybox", "top") 2334 id := strings.TrimSpace(out) 2335 c.Assert(waitRun(id), check.IsNil) 2336 pid1, err := inspectField(id, "State.Pid") 2337 c.Assert(err, check.IsNil) 2338 2339 parentContainerNet, err := os.Readlink(fmt.Sprintf("/proc/%s/ns/net", pid1)) 2340 if err != nil { 2341 c.Fatal(err) 2342 } 2343 2344 out, _ = dockerCmd(c, "run", fmt.Sprintf("--net=container:%s", id), "busybox", "readlink", "/proc/self/ns/net") 2345 out = strings.Trim(out, "\n") 2346 if parentContainerNet != out { 2347 c.Fatalf("NET different with --net=container:%s %s != %s\n", id, parentContainerNet, out) 2348 } 2349 } 2350 2351 func (s *DockerSuite) TestRunModePidHost(c *check.C) { 2352 // Not applicable on Windows as uses Unix-specific capabilities 2353 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace) 2354 2355 hostPid, err := os.Readlink("/proc/1/ns/pid") 2356 if err != nil { 2357 c.Fatal(err) 2358 } 2359 2360 out, _ := dockerCmd(c, "run", "--pid=host", "busybox", "readlink", "/proc/self/ns/pid") 2361 out = strings.Trim(out, "\n") 2362 if hostPid != out { 2363 c.Fatalf("PID different with --pid=host %s != %s\n", hostPid, out) 2364 } 2365 2366 out, _ = dockerCmd(c, "run", "busybox", "readlink", "/proc/self/ns/pid") 2367 out = strings.Trim(out, "\n") 2368 if hostPid == out { 2369 c.Fatalf("PID should be different without --pid=host %s == %s\n", hostPid, out) 2370 } 2371 } 2372 2373 func (s *DockerSuite) TestRunModeUTSHost(c *check.C) { 2374 // Not applicable on Windows as uses Unix-specific capabilities 2375 testRequires(c, SameHostDaemon, DaemonIsLinux) 2376 2377 hostUTS, err := os.Readlink("/proc/1/ns/uts") 2378 if err != nil { 2379 c.Fatal(err) 2380 } 2381 2382 out, _ := dockerCmd(c, "run", "--uts=host", "busybox", "readlink", "/proc/self/ns/uts") 2383 out = strings.Trim(out, "\n") 2384 if hostUTS != out { 2385 c.Fatalf("UTS different with --uts=host %s != %s\n", hostUTS, out) 2386 } 2387 2388 out, _ = dockerCmd(c, "run", "busybox", "readlink", "/proc/self/ns/uts") 2389 out = strings.Trim(out, "\n") 2390 if hostUTS == out { 2391 c.Fatalf("UTS should be different without --uts=host %s == %s\n", hostUTS, out) 2392 } 2393 } 2394 2395 func (s *DockerSuite) TestRunTLSverify(c *check.C) { 2396 if out, code, err := dockerCmdWithError("ps"); err != nil || code != 0 { 2397 c.Fatalf("Should have worked: %v:\n%v", err, out) 2398 } 2399 2400 // Regardless of whether we specify true or false we need to 2401 // test to make sure tls is turned on if --tlsverify is specified at all 2402 out, code, err := dockerCmdWithError("--tlsverify=false", "ps") 2403 if err == nil || code == 0 || !strings.Contains(out, "trying to connect") { 2404 c.Fatalf("Should have failed: \net:%v\nout:%v\nerr:%v", code, out, err) 2405 } 2406 2407 out, code, err = dockerCmdWithError("--tlsverify=true", "ps") 2408 if err == nil || code == 0 || !strings.Contains(out, "cert") { 2409 c.Fatalf("Should have failed: \net:%v\nout:%v\nerr:%v", code, out, err) 2410 } 2411 } 2412 2413 func (s *DockerSuite) TestRunPortFromDockerRangeInUse(c *check.C) { 2414 // TODO Windows. Once moved to libnetwork/CNM, this may be able to be 2415 // re-instated. 2416 testRequires(c, DaemonIsLinux) 2417 // first find allocator current position 2418 out, _ := dockerCmd(c, "run", "-d", "-p", ":80", "busybox", "top") 2419 2420 id := strings.TrimSpace(out) 2421 out, _ = dockerCmd(c, "port", id) 2422 2423 out = strings.TrimSpace(out) 2424 if out == "" { 2425 c.Fatal("docker port command output is empty") 2426 } 2427 out = strings.Split(out, ":")[1] 2428 lastPort, err := strconv.Atoi(out) 2429 if err != nil { 2430 c.Fatal(err) 2431 } 2432 port := lastPort + 1 2433 l, err := net.Listen("tcp", ":"+strconv.Itoa(port)) 2434 if err != nil { 2435 c.Fatal(err) 2436 } 2437 defer l.Close() 2438 2439 out, _ = dockerCmd(c, "run", "-d", "-p", ":80", "busybox", "top") 2440 2441 id = strings.TrimSpace(out) 2442 dockerCmd(c, "port", id) 2443 } 2444 2445 func (s *DockerSuite) TestRunTtyWithPipe(c *check.C) { 2446 errChan := make(chan error) 2447 go func() { 2448 defer close(errChan) 2449 2450 cmd := exec.Command(dockerBinary, "run", "-ti", "busybox", "true") 2451 if _, err := cmd.StdinPipe(); err != nil { 2452 errChan <- err 2453 return 2454 } 2455 2456 expected := "cannot enable tty mode" 2457 if out, _, err := runCommandWithOutput(cmd); err == nil { 2458 errChan <- fmt.Errorf("run should have failed") 2459 return 2460 } else if !strings.Contains(out, expected) { 2461 errChan <- fmt.Errorf("run failed with error %q: expected %q", out, expected) 2462 return 2463 } 2464 }() 2465 2466 select { 2467 case err := <-errChan: 2468 c.Assert(err, check.IsNil) 2469 case <-time.After(6 * time.Second): 2470 c.Fatal("container is running but should have failed") 2471 } 2472 } 2473 2474 func (s *DockerSuite) TestRunNonLocalMacAddress(c *check.C) { 2475 addr := "00:16:3E:08:00:50" 2476 cmd := "ifconfig" 2477 image := "busybox" 2478 expected := addr 2479 2480 if daemonPlatform == "windows" { 2481 cmd = "ipconfig /all" 2482 image = WindowsBaseImage 2483 expected = strings.Replace(strings.ToUpper(addr), ":", "-", -1) 2484 2485 } 2486 2487 if out, _ := dockerCmd(c, "run", "--mac-address", addr, image, cmd); !strings.Contains(out, expected) { 2488 c.Fatalf("Output should have contained %q: %s", expected, out) 2489 } 2490 } 2491 2492 func (s *DockerSuite) TestRunNetHost(c *check.C) { 2493 // Not applicable on Windows as uses Unix-specific capabilities 2494 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace) 2495 2496 hostNet, err := os.Readlink("/proc/1/ns/net") 2497 if err != nil { 2498 c.Fatal(err) 2499 } 2500 2501 out, _ := dockerCmd(c, "run", "--net=host", "busybox", "readlink", "/proc/self/ns/net") 2502 out = strings.Trim(out, "\n") 2503 if hostNet != out { 2504 c.Fatalf("Net namespace different with --net=host %s != %s\n", hostNet, out) 2505 } 2506 2507 out, _ = dockerCmd(c, "run", "busybox", "readlink", "/proc/self/ns/net") 2508 out = strings.Trim(out, "\n") 2509 if hostNet == out { 2510 c.Fatalf("Net namespace should be different without --net=host %s == %s\n", hostNet, out) 2511 } 2512 } 2513 2514 func (s *DockerSuite) TestRunNetHostTwiceSameName(c *check.C) { 2515 // TODO Windows. As Windows networking evolves and converges towards 2516 // CNM, this test may be possible to enable on Windows. 2517 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace) 2518 2519 dockerCmd(c, "run", "--rm", "--name=thost", "--net=host", "busybox", "true") 2520 dockerCmd(c, "run", "--rm", "--name=thost", "--net=host", "busybox", "true") 2521 } 2522 2523 func (s *DockerSuite) TestRunNetContainerWhichHost(c *check.C) { 2524 // Not applicable on Windows as uses Unix-specific capabilities 2525 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace) 2526 2527 hostNet, err := os.Readlink("/proc/1/ns/net") 2528 if err != nil { 2529 c.Fatal(err) 2530 } 2531 2532 dockerCmd(c, "run", "-d", "--net=host", "--name=test", "busybox", "top") 2533 2534 out, _ := dockerCmd(c, "run", "--net=container:test", "busybox", "readlink", "/proc/self/ns/net") 2535 out = strings.Trim(out, "\n") 2536 if hostNet != out { 2537 c.Fatalf("Container should have host network namespace") 2538 } 2539 } 2540 2541 func (s *DockerSuite) TestRunAllowPortRangeThroughPublish(c *check.C) { 2542 // TODO Windows. This may be possible to enable in the future. However, 2543 // Windows does not currently support --expose, or populate the network 2544 // settings seen through inspect. 2545 testRequires(c, DaemonIsLinux) 2546 out, _ := dockerCmd(c, "run", "-d", "--expose", "3000-3003", "-p", "3000-3003", "busybox", "top") 2547 2548 id := strings.TrimSpace(out) 2549 portstr, err := inspectFieldJSON(id, "NetworkSettings.Ports") 2550 c.Assert(err, check.IsNil) 2551 2552 var ports nat.PortMap 2553 err = unmarshalJSON([]byte(portstr), &ports) 2554 for port, binding := range ports { 2555 portnum, _ := strconv.Atoi(strings.Split(string(port), "/")[0]) 2556 if portnum < 3000 || portnum > 3003 { 2557 c.Fatalf("Port %d is out of range ", portnum) 2558 } 2559 if binding == nil || len(binding) != 1 || len(binding[0].HostPort) == 0 { 2560 c.Fatal("Port is not mapped for the port "+port, out) 2561 } 2562 } 2563 } 2564 2565 func (s *DockerSuite) TestRunSetDefaultRestartPolicy(c *check.C) { 2566 dockerCmd(c, "run", "-d", "--name", "test", "busybox", "sleep", "30") 2567 out, err := inspectField("test", "HostConfig.RestartPolicy.Name") 2568 c.Assert(err, check.IsNil) 2569 if out != "no" { 2570 c.Fatalf("Set default restart policy failed") 2571 } 2572 } 2573 2574 func (s *DockerSuite) TestRunRestartMaxRetries(c *check.C) { 2575 out, _ := dockerCmd(c, "run", "-d", "--restart=on-failure:3", "busybox", "false") 2576 timeout := 10 * time.Second 2577 if daemonPlatform == "windows" { 2578 timeout = 45 * time.Second 2579 } 2580 2581 id := strings.TrimSpace(string(out)) 2582 if err := waitInspect(id, "{{ .State.Restarting }} {{ .State.Running }}", "false false", timeout); err != nil { 2583 c.Fatal(err) 2584 } 2585 2586 count, err := inspectField(id, "RestartCount") 2587 c.Assert(err, check.IsNil) 2588 if count != "3" { 2589 c.Fatalf("Container was restarted %s times, expected %d", count, 3) 2590 } 2591 2592 MaximumRetryCount, err := inspectField(id, "HostConfig.RestartPolicy.MaximumRetryCount") 2593 c.Assert(err, check.IsNil) 2594 if MaximumRetryCount != "3" { 2595 c.Fatalf("Container Maximum Retry Count is %s, expected %s", MaximumRetryCount, "3") 2596 } 2597 } 2598 2599 func (s *DockerSuite) TestRunContainerWithWritableRootfs(c *check.C) { 2600 dockerCmd(c, "run", "--rm", "busybox", "touch", "/file") 2601 } 2602 2603 func (s *DockerSuite) TestRunContainerWithReadonlyRootfs(c *check.C) { 2604 // Not applicable on Windows which does not support --read-only 2605 testRequires(c, DaemonIsLinux) 2606 2607 for _, f := range []string{"/file", "/etc/hosts", "/etc/resolv.conf", "/etc/hostname", "/sys/kernel", "/dev/.dont.touch.me"} { 2608 testReadOnlyFile(f, c) 2609 } 2610 } 2611 2612 func (s *DockerSuite) TestPermissionsPtsReadonlyRootfs(c *check.C) { 2613 // Not applicable on Windows due to use of Unix specific functionality, plus 2614 // the use of --read-only which is not supported. 2615 // --read-only + userns has remount issues 2616 testRequires(c, DaemonIsLinux, NotUserNamespace) 2617 2618 // Ensure we have not broken writing /dev/pts 2619 out, status := dockerCmd(c, "run", "--read-only", "--rm", "busybox", "mount") 2620 if status != 0 { 2621 c.Fatal("Could not obtain mounts when checking /dev/pts mntpnt.") 2622 } 2623 expected := "type devpts (rw," 2624 if !strings.Contains(string(out), expected) { 2625 c.Fatalf("expected output to contain %s but contains %s", expected, out) 2626 } 2627 } 2628 2629 func testReadOnlyFile(filename string, c *check.C) { 2630 // Not applicable on Windows which does not support --read-only 2631 testRequires(c, DaemonIsLinux, NotUserNamespace) 2632 2633 out, _, err := dockerCmdWithError("run", "--read-only", "--rm", "busybox", "touch", filename) 2634 if err == nil { 2635 c.Fatal("expected container to error on run with read only error") 2636 } 2637 expected := "Read-only file system" 2638 if !strings.Contains(string(out), expected) { 2639 c.Fatalf("expected output from failure to contain %s but contains %s", expected, out) 2640 } 2641 2642 out, _, err = dockerCmdWithError("run", "--read-only", "--privileged", "--rm", "busybox", "touch", filename) 2643 if err == nil { 2644 c.Fatal("expected container to error on run with read only error") 2645 } 2646 expected = "Read-only file system" 2647 if !strings.Contains(string(out), expected) { 2648 c.Fatalf("expected output from failure to contain %s but contains %s", expected, out) 2649 } 2650 } 2651 2652 func (s *DockerSuite) TestRunContainerWithReadonlyEtcHostsAndLinkedContainer(c *check.C) { 2653 // Not applicable on Windows which does not support --link 2654 // --read-only + userns has remount issues 2655 testRequires(c, DaemonIsLinux, NotUserNamespace) 2656 2657 dockerCmd(c, "run", "-d", "--name", "test-etc-hosts-ro-linked", "busybox", "top") 2658 2659 out, _ := dockerCmd(c, "run", "--read-only", "--link", "test-etc-hosts-ro-linked:testlinked", "busybox", "cat", "/etc/hosts") 2660 if !strings.Contains(string(out), "testlinked") { 2661 c.Fatal("Expected /etc/hosts to be updated even if --read-only enabled") 2662 } 2663 } 2664 2665 func (s *DockerSuite) TestRunContainerWithReadonlyRootfsWithDnsFlag(c *check.C) { 2666 // Not applicable on Windows which does not support either --read-only or --dns. 2667 // --read-only + userns has remount issues 2668 testRequires(c, DaemonIsLinux, NotUserNamespace) 2669 2670 out, _ := dockerCmd(c, "run", "--read-only", "--dns", "1.1.1.1", "busybox", "/bin/cat", "/etc/resolv.conf") 2671 if !strings.Contains(string(out), "1.1.1.1") { 2672 c.Fatal("Expected /etc/resolv.conf to be updated even if --read-only enabled and --dns flag used") 2673 } 2674 } 2675 2676 func (s *DockerSuite) TestRunContainerWithReadonlyRootfsWithAddHostFlag(c *check.C) { 2677 // Not applicable on Windows which does not support --read-only 2678 // --read-only + userns has remount issues 2679 testRequires(c, DaemonIsLinux, NotUserNamespace) 2680 2681 out, _ := dockerCmd(c, "run", "--read-only", "--add-host", "testreadonly:127.0.0.1", "busybox", "/bin/cat", "/etc/hosts") 2682 if !strings.Contains(string(out), "testreadonly") { 2683 c.Fatal("Expected /etc/hosts to be updated even if --read-only enabled and --add-host flag used") 2684 } 2685 } 2686 2687 func (s *DockerSuite) TestRunVolumesFromRestartAfterRemoved(c *check.C) { 2688 prefix := "" 2689 if daemonPlatform == "windows" { 2690 prefix = "c:" 2691 } 2692 dockerCmd(c, "run", "-d", "--name", "voltest", "-v", prefix+"/foo", "busybox", "sleep", "60") 2693 dockerCmd(c, "run", "-d", "--name", "restarter", "--volumes-from", "voltest", "busybox", "sleep", "60") 2694 2695 // Remove the main volume container and restart the consuming container 2696 dockerCmd(c, "rm", "-f", "voltest") 2697 2698 // This should not fail since the volumes-from were already applied 2699 dockerCmd(c, "restart", "restarter") 2700 } 2701 2702 // run container with --rm should remove container if exit code != 0 2703 func (s *DockerSuite) TestRunContainerWithRmFlagExitCodeNotEqualToZero(c *check.C) { 2704 name := "flowers" 2705 out, _, err := dockerCmdWithError("run", "--name", name, "--rm", "busybox", "ls", "/notexists") 2706 if err == nil { 2707 c.Fatal("Expected docker run to fail", out, err) 2708 } 2709 2710 out, err = getAllContainers() 2711 if err != nil { 2712 c.Fatal(out, err) 2713 } 2714 2715 if out != "" { 2716 c.Fatal("Expected not to have containers", out) 2717 } 2718 } 2719 2720 func (s *DockerSuite) TestRunContainerWithRmFlagCannotStartContainer(c *check.C) { 2721 name := "sparkles" 2722 out, _, err := dockerCmdWithError("run", "--name", name, "--rm", "busybox", "commandNotFound") 2723 if err == nil { 2724 c.Fatal("Expected docker run to fail", out, err) 2725 } 2726 2727 out, err = getAllContainers() 2728 if err != nil { 2729 c.Fatal(out, err) 2730 } 2731 2732 if out != "" { 2733 c.Fatal("Expected not to have containers", out) 2734 } 2735 } 2736 2737 func (s *DockerSuite) TestRunPidHostWithChildIsKillable(c *check.C) { 2738 // Not applicable on Windows as uses Unix specific functionality 2739 testRequires(c, DaemonIsLinux, NotUserNamespace) 2740 name := "ibuildthecloud" 2741 dockerCmd(c, "run", "-d", "--pid=host", "--name", name, "busybox", "sh", "-c", "sleep 30; echo hi") 2742 2743 c.Assert(waitRun(name), check.IsNil) 2744 2745 errchan := make(chan error) 2746 go func() { 2747 if out, _, err := dockerCmdWithError("kill", name); err != nil { 2748 errchan <- fmt.Errorf("%v:\n%s", err, out) 2749 } 2750 close(errchan) 2751 }() 2752 select { 2753 case err := <-errchan: 2754 c.Assert(err, check.IsNil) 2755 case <-time.After(5 * time.Second): 2756 c.Fatal("Kill container timed out") 2757 } 2758 } 2759 2760 func (s *DockerSuite) TestRunWithTooSmallMemoryLimit(c *check.C) { 2761 // TODO Windows. This may be possible to enable once Windows supports 2762 // memory limits on containers 2763 testRequires(c, DaemonIsLinux) 2764 // this memory limit is 1 byte less than the min, which is 4MB 2765 // https://github.com/docker/docker/blob/v1.5.0/daemon/create.go#L22 2766 out, _, err := dockerCmdWithError("run", "-m", "4194303", "busybox") 2767 if err == nil || !strings.Contains(out, "Minimum memory limit allowed is 4MB") { 2768 c.Fatalf("expected run to fail when using too low a memory limit: %q", out) 2769 } 2770 } 2771 2772 func (s *DockerSuite) TestRunWriteToProcAsound(c *check.C) { 2773 // Not applicable on Windows as uses Unix specific functionality 2774 testRequires(c, DaemonIsLinux) 2775 _, code, err := dockerCmdWithError("run", "busybox", "sh", "-c", "echo 111 >> /proc/asound/version") 2776 if err == nil || code == 0 { 2777 c.Fatal("standard container should not be able to write to /proc/asound") 2778 } 2779 } 2780 2781 func (s *DockerSuite) TestRunReadProcTimer(c *check.C) { 2782 // Not applicable on Windows as uses Unix specific functionality 2783 testRequires(c, DaemonIsLinux) 2784 out, code, err := dockerCmdWithError("run", "busybox", "cat", "/proc/timer_stats") 2785 if code != 0 { 2786 return 2787 } 2788 if err != nil { 2789 c.Fatal(err) 2790 } 2791 if strings.Trim(out, "\n ") != "" { 2792 c.Fatalf("expected to receive no output from /proc/timer_stats but received %q", out) 2793 } 2794 } 2795 2796 func (s *DockerSuite) TestRunReadProcLatency(c *check.C) { 2797 // Not applicable on Windows as uses Unix specific functionality 2798 testRequires(c, DaemonIsLinux) 2799 // some kernels don't have this configured so skip the test if this file is not found 2800 // on the host running the tests. 2801 if _, err := os.Stat("/proc/latency_stats"); err != nil { 2802 c.Skip("kernel doesnt have latency_stats configured") 2803 return 2804 } 2805 out, code, err := dockerCmdWithError("run", "busybox", "cat", "/proc/latency_stats") 2806 if code != 0 { 2807 return 2808 } 2809 if err != nil { 2810 c.Fatal(err) 2811 } 2812 if strings.Trim(out, "\n ") != "" { 2813 c.Fatalf("expected to receive no output from /proc/latency_stats but received %q", out) 2814 } 2815 } 2816 2817 func (s *DockerSuite) TestRunReadFilteredProc(c *check.C) { 2818 // Not applicable on Windows as uses Unix specific functionality 2819 testRequires(c, Apparmor, DaemonIsLinux, NotUserNamespace) 2820 2821 testReadPaths := []string{ 2822 "/proc/latency_stats", 2823 "/proc/timer_stats", 2824 "/proc/kcore", 2825 } 2826 for i, filePath := range testReadPaths { 2827 name := fmt.Sprintf("procsieve-%d", i) 2828 shellCmd := fmt.Sprintf("exec 3<%s", filePath) 2829 2830 out, exitCode, err := dockerCmdWithError("run", "--privileged", "--security-opt", "apparmor:docker-default", "--name", name, "busybox", "sh", "-c", shellCmd) 2831 if exitCode != 0 { 2832 return 2833 } 2834 if err != nil { 2835 c.Fatalf("Open FD for read should have failed with permission denied, got: %s, %v", out, err) 2836 } 2837 } 2838 } 2839 2840 func (s *DockerSuite) TestMountIntoProc(c *check.C) { 2841 // Not applicable on Windows as uses Unix specific functionality 2842 testRequires(c, DaemonIsLinux) 2843 _, code, err := dockerCmdWithError("run", "-v", "/proc//sys", "busybox", "true") 2844 if err == nil || code == 0 { 2845 c.Fatal("container should not be able to mount into /proc") 2846 } 2847 } 2848 2849 func (s *DockerSuite) TestMountIntoSys(c *check.C) { 2850 // Not applicable on Windows as uses Unix specific functionality 2851 testRequires(c, DaemonIsLinux) 2852 testRequires(c, NotUserNamespace) 2853 dockerCmd(c, "run", "-v", "/sys/fs/cgroup", "busybox", "true") 2854 } 2855 2856 func (s *DockerSuite) TestRunUnshareProc(c *check.C) { 2857 // Not applicable on Windows as uses Unix specific functionality 2858 testRequires(c, Apparmor, DaemonIsLinux, NotUserNamespace) 2859 2860 name := "acidburn" 2861 if out, _, err := dockerCmdWithError("run", "--name", name, "jess/unshare", "unshare", "-p", "-m", "-f", "-r", "--mount-proc=/proc", "mount"); err == nil || !strings.Contains(out, "Permission denied") { 2862 c.Fatalf("unshare with --mount-proc should have failed with permission denied, got: %s, %v", out, err) 2863 } 2864 2865 name = "cereal" 2866 if out, _, err := dockerCmdWithError("run", "--name", name, "jess/unshare", "unshare", "-p", "-m", "-f", "-r", "mount", "-t", "proc", "none", "/proc"); err == nil || !strings.Contains(out, "Permission denied") { 2867 c.Fatalf("unshare and mount of /proc should have failed with permission denied, got: %s, %v", out, err) 2868 } 2869 2870 /* Ensure still fails if running privileged with the default policy */ 2871 name = "crashoverride" 2872 if out, _, err := dockerCmdWithError("run", "--privileged", "--security-opt", "apparmor:docker-default", "--name", name, "jess/unshare", "unshare", "-p", "-m", "-f", "-r", "mount", "-t", "proc", "none", "/proc"); err == nil || !(strings.Contains(strings.ToLower(out), "permission denied") || strings.Contains(strings.ToLower(out), "operation not permitted")) { 2873 c.Fatalf("privileged unshare with apparmor should have failed with permission denied, got: %s, %v", out, err) 2874 } 2875 } 2876 2877 func (s *DockerSuite) TestRunPublishPort(c *check.C) { 2878 // TODO Windows: This may be possible once Windows moves to libnetwork and CNM 2879 testRequires(c, DaemonIsLinux) 2880 dockerCmd(c, "run", "-d", "--name", "test", "--expose", "8080", "busybox", "top") 2881 out, _ := dockerCmd(c, "port", "test") 2882 out = strings.Trim(out, "\r\n") 2883 if out != "" { 2884 c.Fatalf("run without --publish-all should not publish port, out should be nil, but got: %s", out) 2885 } 2886 } 2887 2888 // Issue #10184. 2889 func (s *DockerSuite) TestDevicePermissions(c *check.C) { 2890 // Not applicable on Windows as uses Unix specific functionality 2891 testRequires(c, DaemonIsLinux) 2892 const permissions = "crw-rw-rw-" 2893 out, status := dockerCmd(c, "run", "--device", "/dev/fuse:/dev/fuse:mrw", "busybox:latest", "ls", "-l", "/dev/fuse") 2894 if status != 0 { 2895 c.Fatalf("expected status 0, got %d", status) 2896 } 2897 if !strings.HasPrefix(out, permissions) { 2898 c.Fatalf("output should begin with %q, got %q", permissions, out) 2899 } 2900 } 2901 2902 func (s *DockerSuite) TestRunCapAddCHOWN(c *check.C) { 2903 // Not applicable on Windows as uses Unix specific functionality 2904 testRequires(c, DaemonIsLinux) 2905 out, _ := dockerCmd(c, "run", "--cap-drop=ALL", "--cap-add=CHOWN", "busybox", "sh", "-c", "adduser -D -H newuser && chown newuser /home && echo ok") 2906 2907 if actual := strings.Trim(out, "\r\n"); actual != "ok" { 2908 c.Fatalf("expected output ok received %s", actual) 2909 } 2910 } 2911 2912 // https://github.com/docker/docker/pull/14498 2913 func (s *DockerSuite) TestVolumeFromMixedRWOptions(c *check.C) { 2914 // TODO Windows post TP4. Enable the read-only bits once they are 2915 // supported on the platform. 2916 prefix := "" 2917 slash := `/` 2918 if daemonPlatform == "windows" { 2919 prefix = "c:" 2920 slash = `\` 2921 } 2922 2923 dockerCmd(c, "run", "--name", "parent", "-v", prefix+"/test", "busybox", "true") 2924 if daemonPlatform != "windows" { 2925 dockerCmd(c, "run", "--volumes-from", "parent:ro", "--name", "test-volumes-1", "busybox", "true") 2926 } 2927 dockerCmd(c, "run", "--volumes-from", "parent:rw", "--name", "test-volumes-2", "busybox", "true") 2928 2929 if daemonPlatform != "windows" { 2930 mRO, err := inspectMountPoint("test-volumes-1", prefix+slash+"test") 2931 c.Assert(err, check.IsNil) 2932 if mRO.RW { 2933 c.Fatalf("Expected RO volume was RW") 2934 } 2935 } 2936 2937 mRW, err := inspectMountPoint("test-volumes-2", prefix+slash+"test") 2938 c.Assert(err, check.IsNil) 2939 if !mRW.RW { 2940 c.Fatalf("Expected RW volume was RO") 2941 } 2942 } 2943 2944 func (s *DockerSuite) TestRunWriteFilteredProc(c *check.C) { 2945 // Not applicable on Windows as uses Unix specific functionality 2946 testRequires(c, Apparmor, DaemonIsLinux, NotUserNamespace) 2947 2948 testWritePaths := []string{ 2949 /* modprobe and core_pattern should both be denied by generic 2950 * policy of denials for /proc/sys/kernel. These files have been 2951 * picked to be checked as they are particularly sensitive to writes */ 2952 "/proc/sys/kernel/modprobe", 2953 "/proc/sys/kernel/core_pattern", 2954 "/proc/sysrq-trigger", 2955 "/proc/kcore", 2956 } 2957 for i, filePath := range testWritePaths { 2958 name := fmt.Sprintf("writeprocsieve-%d", i) 2959 2960 shellCmd := fmt.Sprintf("exec 3>%s", filePath) 2961 out, code, err := dockerCmdWithError("run", "--privileged", "--security-opt", "apparmor:docker-default", "--name", name, "busybox", "sh", "-c", shellCmd) 2962 if code != 0 { 2963 return 2964 } 2965 if err != nil { 2966 c.Fatalf("Open FD for write should have failed with permission denied, got: %s, %v", out, err) 2967 } 2968 } 2969 } 2970 2971 func (s *DockerSuite) TestRunNetworkFilesBindMount(c *check.C) { 2972 // Not applicable on Windows as uses Unix specific functionality 2973 testRequires(c, SameHostDaemon, DaemonIsLinux) 2974 2975 expected := "test123" 2976 2977 filename := createTmpFile(c, expected) 2978 defer os.Remove(filename) 2979 2980 nwfiles := []string{"/etc/resolv.conf", "/etc/hosts", "/etc/hostname"} 2981 2982 for i := range nwfiles { 2983 actual, _ := dockerCmd(c, "run", "-v", filename+":"+nwfiles[i], "busybox", "cat", nwfiles[i]) 2984 if actual != expected { 2985 c.Fatalf("expected %s be: %q, but was: %q", nwfiles[i], expected, actual) 2986 } 2987 } 2988 } 2989 2990 func (s *DockerSuite) TestRunNetworkFilesBindMountRO(c *check.C) { 2991 // Not applicable on Windows as uses Unix specific functionality 2992 testRequires(c, SameHostDaemon, DaemonIsLinux) 2993 2994 filename := createTmpFile(c, "test123") 2995 defer os.Remove(filename) 2996 2997 nwfiles := []string{"/etc/resolv.conf", "/etc/hosts", "/etc/hostname"} 2998 2999 for i := range nwfiles { 3000 _, exitCode, err := dockerCmdWithError("run", "-v", filename+":"+nwfiles[i]+":ro", "busybox", "touch", nwfiles[i]) 3001 if err == nil || exitCode == 0 { 3002 c.Fatalf("run should fail because bind mount of %s is ro: exit code %d", nwfiles[i], exitCode) 3003 } 3004 } 3005 } 3006 3007 func (s *DockerSuite) TestRunNetworkFilesBindMountROFilesystem(c *check.C) { 3008 // Not applicable on Windows as uses Unix specific functionality 3009 // --read-only + userns has remount issues 3010 testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace) 3011 3012 filename := createTmpFile(c, "test123") 3013 defer os.Remove(filename) 3014 3015 nwfiles := []string{"/etc/resolv.conf", "/etc/hosts", "/etc/hostname"} 3016 3017 for i := range nwfiles { 3018 _, exitCode := dockerCmd(c, "run", "-v", filename+":"+nwfiles[i], "--read-only", "busybox", "touch", nwfiles[i]) 3019 if exitCode != 0 { 3020 c.Fatalf("run should not fail because %s is mounted writable on read-only root filesystem: exit code %d", nwfiles[i], exitCode) 3021 } 3022 } 3023 3024 for i := range nwfiles { 3025 _, exitCode, err := dockerCmdWithError("run", "-v", filename+":"+nwfiles[i]+":ro", "--read-only", "busybox", "touch", nwfiles[i]) 3026 if err == nil || exitCode == 0 { 3027 c.Fatalf("run should fail because %s is mounted read-only on read-only root filesystem: exit code %d", nwfiles[i], exitCode) 3028 } 3029 } 3030 } 3031 3032 func (s *DockerTrustSuite) TestTrustedRun(c *check.C) { 3033 // Windows does not support this functionality 3034 testRequires(c, DaemonIsLinux) 3035 repoName := s.setupTrustedImage(c, "trusted-run") 3036 3037 // Try run 3038 runCmd := exec.Command(dockerBinary, "run", repoName) 3039 s.trustedCmd(runCmd) 3040 out, _, err := runCommandWithOutput(runCmd) 3041 if err != nil { 3042 c.Fatalf("Error running trusted run: %s\n%s\n", err, out) 3043 } 3044 3045 if !strings.Contains(string(out), "Tagging") { 3046 c.Fatalf("Missing expected output on trusted push:\n%s", out) 3047 } 3048 3049 dockerCmd(c, "rmi", repoName) 3050 3051 // Try untrusted run to ensure we pushed the tag to the registry 3052 runCmd = exec.Command(dockerBinary, "run", "--disable-content-trust=true", repoName) 3053 s.trustedCmd(runCmd) 3054 out, _, err = runCommandWithOutput(runCmd) 3055 if err != nil { 3056 c.Fatalf("Error running trusted run: %s\n%s", err, out) 3057 } 3058 3059 if !strings.Contains(string(out), "Status: Downloaded") { 3060 c.Fatalf("Missing expected output on trusted run with --disable-content-trust:\n%s", out) 3061 } 3062 } 3063 3064 func (s *DockerTrustSuite) TestUntrustedRun(c *check.C) { 3065 // Windows does not support this functionality 3066 testRequires(c, DaemonIsLinux) 3067 repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL) 3068 // tag the image and upload it to the private registry 3069 dockerCmd(c, "tag", "busybox", repoName) 3070 dockerCmd(c, "push", repoName) 3071 dockerCmd(c, "rmi", repoName) 3072 3073 // Try trusted run on untrusted tag 3074 runCmd := exec.Command(dockerBinary, "run", repoName) 3075 s.trustedCmd(runCmd) 3076 out, _, err := runCommandWithOutput(runCmd) 3077 if err == nil { 3078 c.Fatalf("Error expected when running trusted run with:\n%s", out) 3079 } 3080 3081 if !strings.Contains(string(out), "no trust data available") { 3082 c.Fatalf("Missing expected output on trusted run:\n%s", out) 3083 } 3084 } 3085 3086 func (s *DockerTrustSuite) TestRunWhenCertExpired(c *check.C) { 3087 // Windows does not support this functionality 3088 testRequires(c, DaemonIsLinux) 3089 c.Skip("Currently changes system time, causing instability") 3090 repoName := s.setupTrustedImage(c, "trusted-run-expired") 3091 3092 // Certificates have 10 years of expiration 3093 elevenYearsFromNow := time.Now().Add(time.Hour * 24 * 365 * 11) 3094 3095 runAtDifferentDate(elevenYearsFromNow, func() { 3096 // Try run 3097 runCmd := exec.Command(dockerBinary, "run", repoName) 3098 s.trustedCmd(runCmd) 3099 out, _, err := runCommandWithOutput(runCmd) 3100 if err == nil { 3101 c.Fatalf("Error running trusted run in the distant future: %s\n%s", err, out) 3102 } 3103 3104 if !strings.Contains(string(out), "could not validate the path to a trusted root") { 3105 c.Fatalf("Missing expected output on trusted run in the distant future:\n%s", out) 3106 } 3107 }) 3108 3109 runAtDifferentDate(elevenYearsFromNow, func() { 3110 // Try run 3111 runCmd := exec.Command(dockerBinary, "run", "--disable-content-trust", repoName) 3112 s.trustedCmd(runCmd) 3113 out, _, err := runCommandWithOutput(runCmd) 3114 if err != nil { 3115 c.Fatalf("Error running untrusted run in the distant future: %s\n%s", err, out) 3116 } 3117 3118 if !strings.Contains(string(out), "Status: Downloaded") { 3119 c.Fatalf("Missing expected output on untrusted run in the distant future:\n%s", out) 3120 } 3121 }) 3122 } 3123 3124 func (s *DockerTrustSuite) TestTrustedRunFromBadTrustServer(c *check.C) { 3125 // Windows does not support this functionality 3126 testRequires(c, DaemonIsLinux) 3127 repoName := fmt.Sprintf("%v/dockerclievilrun/trusted:latest", privateRegistryURL) 3128 evilLocalConfigDir, err := ioutil.TempDir("", "evil-local-config-dir") 3129 if err != nil { 3130 c.Fatalf("Failed to create local temp dir") 3131 } 3132 3133 // tag the image and upload it to the private registry 3134 dockerCmd(c, "tag", "busybox", repoName) 3135 3136 pushCmd := exec.Command(dockerBinary, "push", repoName) 3137 s.trustedCmd(pushCmd) 3138 out, _, err := runCommandWithOutput(pushCmd) 3139 if err != nil { 3140 c.Fatalf("Error running trusted push: %s\n%s", err, out) 3141 } 3142 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 3143 c.Fatalf("Missing expected output on trusted push:\n%s", out) 3144 } 3145 3146 dockerCmd(c, "rmi", repoName) 3147 3148 // Try run 3149 runCmd := exec.Command(dockerBinary, "run", repoName) 3150 s.trustedCmd(runCmd) 3151 out, _, err = runCommandWithOutput(runCmd) 3152 if err != nil { 3153 c.Fatalf("Error running trusted run: %s\n%s", err, out) 3154 } 3155 3156 if !strings.Contains(string(out), "Tagging") { 3157 c.Fatalf("Missing expected output on trusted push:\n%s", out) 3158 } 3159 3160 dockerCmd(c, "rmi", repoName) 3161 3162 // Kill the notary server, start a new "evil" one. 3163 s.not.Close() 3164 s.not, err = newTestNotary(c) 3165 if err != nil { 3166 c.Fatalf("Restarting notary server failed.") 3167 } 3168 3169 // In order to make an evil server, lets re-init a client (with a different trust dir) and push new data. 3170 // tag an image and upload it to the private registry 3171 dockerCmd(c, "--config", evilLocalConfigDir, "tag", "busybox", repoName) 3172 3173 // Push up to the new server 3174 pushCmd = exec.Command(dockerBinary, "--config", evilLocalConfigDir, "push", repoName) 3175 s.trustedCmd(pushCmd) 3176 out, _, err = runCommandWithOutput(pushCmd) 3177 if err != nil { 3178 c.Fatalf("Error running trusted push: %s\n%s", err, out) 3179 } 3180 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 3181 c.Fatalf("Missing expected output on trusted push:\n%s", out) 3182 } 3183 3184 // Now, try running with the original client from this new trust server. This should fail. 3185 runCmd = exec.Command(dockerBinary, "run", repoName) 3186 s.trustedCmd(runCmd) 3187 out, _, err = runCommandWithOutput(runCmd) 3188 if err == nil { 3189 c.Fatalf("Expected to fail on this run due to different remote data: %s\n%s", err, out) 3190 } 3191 3192 if !strings.Contains(string(out), "failed to validate data with current trusted certificates") { 3193 c.Fatalf("Missing expected output on trusted push:\n%s", out) 3194 } 3195 } 3196 3197 func (s *DockerSuite) TestPtraceContainerProcsFromHost(c *check.C) { 3198 // Not applicable on Windows as uses Unix specific functionality 3199 testRequires(c, DaemonIsLinux, SameHostDaemon) 3200 3201 out, _ := dockerCmd(c, "run", "-d", "busybox", "top") 3202 id := strings.TrimSpace(out) 3203 c.Assert(waitRun(id), check.IsNil) 3204 pid1, err := inspectField(id, "State.Pid") 3205 c.Assert(err, check.IsNil) 3206 3207 _, err = os.Readlink(fmt.Sprintf("/proc/%s/ns/net", pid1)) 3208 if err != nil { 3209 c.Fatal(err) 3210 } 3211 } 3212 3213 func (s *DockerSuite) TestAppArmorDeniesPtrace(c *check.C) { 3214 // Not applicable on Windows as uses Unix specific functionality 3215 testRequires(c, SameHostDaemon, Apparmor, DaemonIsLinux, NotGCCGO) 3216 3217 // Run through 'sh' so we are NOT pid 1. Pid 1 may be able to trace 3218 // itself, but pid>1 should not be able to trace pid1. 3219 _, exitCode, _ := dockerCmdWithError("run", "busybox", "sh", "-c", "sh -c readlink /proc/1/ns/net") 3220 if exitCode == 0 { 3221 c.Fatal("ptrace was not successfully restricted by AppArmor") 3222 } 3223 } 3224 3225 func (s *DockerSuite) TestAppArmorTraceSelf(c *check.C) { 3226 // Not applicable on Windows as uses Unix specific functionality 3227 testRequires(c, DaemonIsLinux, SameHostDaemon, Apparmor) 3228 3229 _, exitCode, _ := dockerCmdWithError("run", "busybox", "readlink", "/proc/1/ns/net") 3230 if exitCode != 0 { 3231 c.Fatal("ptrace of self failed.") 3232 } 3233 } 3234 3235 func (s *DockerSuite) TestAppArmorDeniesChmodProc(c *check.C) { 3236 // Not applicable on Windows as uses Unix specific functionality 3237 testRequires(c, SameHostDaemon, Apparmor, DaemonIsLinux, NotUserNamespace) 3238 _, exitCode, _ := dockerCmdWithError("run", "busybox", "chmod", "744", "/proc/cpuinfo") 3239 if exitCode == 0 { 3240 // If our test failed, attempt to repair the host system... 3241 _, exitCode, _ := dockerCmdWithError("run", "busybox", "chmod", "444", "/proc/cpuinfo") 3242 if exitCode == 0 { 3243 c.Fatal("AppArmor was unsuccessful in prohibiting chmod of /proc/* files.") 3244 } 3245 } 3246 } 3247 3248 func (s *DockerSuite) TestRunCapAddSYSTIME(c *check.C) { 3249 // Not applicable on Windows as uses Unix specific functionality 3250 testRequires(c, DaemonIsLinux) 3251 3252 dockerCmd(c, "run", "--cap-drop=ALL", "--cap-add=SYS_TIME", "busybox", "sh", "-c", "grep ^CapEff /proc/self/status | sed 's/^CapEff:\t//' | grep ^0000000002000000$") 3253 } 3254 3255 // run create container failed should clean up the container 3256 func (s *DockerSuite) TestRunCreateContainerFailedCleanUp(c *check.C) { 3257 // TODO Windows. This may be possible to enable once link is supported 3258 testRequires(c, DaemonIsLinux) 3259 name := "unique_name" 3260 _, _, err := dockerCmdWithError("run", "--name", name, "--link", "nothing:nothing", "busybox") 3261 c.Assert(err, check.NotNil, check.Commentf("Expected docker run to fail!")) 3262 3263 containerID, err := inspectField(name, "Id") 3264 c.Assert(containerID, check.Equals, "", check.Commentf("Expected not to have this container: %s!", containerID)) 3265 } 3266 3267 func (s *DockerSuite) TestRunNamedVolume(c *check.C) { 3268 prefix := "" 3269 slash := `/` 3270 if daemonPlatform == "windows" { 3271 prefix = "c:" 3272 slash = `\` 3273 } 3274 testRequires(c, DaemonIsLinux) 3275 dockerCmd(c, "run", "--name=test", "-v", "testing:"+prefix+slash+"foo", "busybox", "sh", "-c", "echo hello > "+prefix+"/foo/bar") 3276 3277 out, _ := dockerCmd(c, "run", "--volumes-from", "test", "busybox", "sh", "-c", "cat "+prefix+"/foo/bar") 3278 c.Assert(strings.TrimSpace(out), check.Equals, "hello") 3279 3280 out, _ = dockerCmd(c, "run", "-v", "testing:"+prefix+slash+"foo", "busybox", "sh", "-c", "cat "+prefix+"/foo/bar") 3281 c.Assert(strings.TrimSpace(out), check.Equals, "hello") 3282 } 3283 3284 func (s *DockerSuite) TestRunWithUlimits(c *check.C) { 3285 // Not applicable on Windows as uses Unix specific functionality 3286 testRequires(c, DaemonIsLinux) 3287 3288 out, _ := dockerCmd(c, "run", "--name=testulimits", "--ulimit", "nofile=42", "busybox", "/bin/sh", "-c", "ulimit -n") 3289 ul := strings.TrimSpace(out) 3290 if ul != "42" { 3291 c.Fatalf("expected `ulimit -n` to be 42, got %s", ul) 3292 } 3293 } 3294 3295 func (s *DockerSuite) TestRunContainerWithCgroupParent(c *check.C) { 3296 // Not applicable on Windows as uses Unix specific functionality 3297 testRequires(c, DaemonIsLinux) 3298 3299 cgroupParent := "test" 3300 name := "cgroup-test" 3301 3302 out, _, err := dockerCmdWithError("run", "--cgroup-parent", cgroupParent, "--name", name, "busybox", "cat", "/proc/self/cgroup") 3303 if err != nil { 3304 c.Fatalf("unexpected failure when running container with --cgroup-parent option - %s\n%v", string(out), err) 3305 } 3306 cgroupPaths := parseCgroupPaths(string(out)) 3307 if len(cgroupPaths) == 0 { 3308 c.Fatalf("unexpected output - %q", string(out)) 3309 } 3310 id, err := getIDByName(name) 3311 c.Assert(err, check.IsNil) 3312 expectedCgroup := path.Join(cgroupParent, id) 3313 found := false 3314 for _, path := range cgroupPaths { 3315 if strings.HasSuffix(path, expectedCgroup) { 3316 found = true 3317 break 3318 } 3319 } 3320 if !found { 3321 c.Fatalf("unexpected cgroup paths. Expected at least one cgroup path to have suffix %q. Cgroup Paths: %v", expectedCgroup, cgroupPaths) 3322 } 3323 } 3324 3325 func (s *DockerSuite) TestRunContainerWithCgroupParentAbsPath(c *check.C) { 3326 // Not applicable on Windows as uses Unix specific functionality 3327 testRequires(c, DaemonIsLinux) 3328 3329 cgroupParent := "/cgroup-parent/test" 3330 name := "cgroup-test" 3331 out, _, err := dockerCmdWithError("run", "--cgroup-parent", cgroupParent, "--name", name, "busybox", "cat", "/proc/self/cgroup") 3332 if err != nil { 3333 c.Fatalf("unexpected failure when running container with --cgroup-parent option - %s\n%v", string(out), err) 3334 } 3335 cgroupPaths := parseCgroupPaths(string(out)) 3336 if len(cgroupPaths) == 0 { 3337 c.Fatalf("unexpected output - %q", string(out)) 3338 } 3339 id, err := getIDByName(name) 3340 c.Assert(err, check.IsNil) 3341 expectedCgroup := path.Join(cgroupParent, id) 3342 found := false 3343 for _, path := range cgroupPaths { 3344 if strings.HasSuffix(path, expectedCgroup) { 3345 found = true 3346 break 3347 } 3348 } 3349 if !found { 3350 c.Fatalf("unexpected cgroup paths. Expected at least one cgroup path to have suffix %q. Cgroup Paths: %v", expectedCgroup, cgroupPaths) 3351 } 3352 } 3353 3354 func (s *DockerSuite) TestRunContainerWithCgroupMountRO(c *check.C) { 3355 // Not applicable on Windows as uses Unix specific functionality 3356 // --read-only + userns has remount issues 3357 testRequires(c, DaemonIsLinux, NotUserNamespace) 3358 3359 filename := "/sys/fs/cgroup/devices/test123" 3360 out, _, err := dockerCmdWithError("run", "busybox", "touch", filename) 3361 if err == nil { 3362 c.Fatal("expected cgroup mount point to be read-only, touch file should fail") 3363 } 3364 expected := "Read-only file system" 3365 if !strings.Contains(out, expected) { 3366 c.Fatalf("expected output from failure to contain %s but contains %s", expected, out) 3367 } 3368 } 3369 3370 func (s *DockerSuite) TestRunContainerNetworkModeToSelf(c *check.C) { 3371 // Not applicable on Windows which does not support --net=container 3372 testRequires(c, DaemonIsLinux, NotUserNamespace) 3373 out, _, err := dockerCmdWithError("run", "--name=me", "--net=container:me", "busybox", "true") 3374 if err == nil || !strings.Contains(out, "cannot join own network") { 3375 c.Fatalf("using container net mode to self should result in an error\nerr: %q\nout: %s", err, out) 3376 } 3377 } 3378 3379 func (s *DockerSuite) TestRunContainerNetModeWithDnsMacHosts(c *check.C) { 3380 // Not applicable on Windows which does not support --net=container 3381 testRequires(c, DaemonIsLinux, NotUserNamespace) 3382 out, _, err := dockerCmdWithError("run", "-d", "--name", "parent", "busybox", "top") 3383 if err != nil { 3384 c.Fatalf("failed to run container: %v, output: %q", err, out) 3385 } 3386 3387 out, _, err = dockerCmdWithError("run", "--dns", "1.2.3.4", "--net=container:parent", "busybox") 3388 if err == nil || !strings.Contains(out, runconfig.ErrConflictNetworkAndDNS.Error()) { 3389 c.Fatalf("run --net=container with --dns should error out") 3390 } 3391 3392 out, _, err = dockerCmdWithError("run", "--mac-address", "92:d0:c6:0a:29:33", "--net=container:parent", "busybox") 3393 if err == nil || !strings.Contains(out, runconfig.ErrConflictContainerNetworkAndMac.Error()) { 3394 c.Fatalf("run --net=container with --mac-address should error out") 3395 } 3396 3397 out, _, err = dockerCmdWithError("run", "--add-host", "test:192.168.2.109", "--net=container:parent", "busybox") 3398 if err == nil || !strings.Contains(out, runconfig.ErrConflictNetworkHosts.Error()) { 3399 c.Fatalf("run --net=container with --add-host should error out") 3400 } 3401 } 3402 3403 func (s *DockerSuite) TestRunContainerNetModeWithExposePort(c *check.C) { 3404 // Not applicable on Windows which does not support --net=container 3405 testRequires(c, DaemonIsLinux, NotUserNamespace) 3406 dockerCmd(c, "run", "-d", "--name", "parent", "busybox", "top") 3407 3408 out, _, err := dockerCmdWithError("run", "-p", "5000:5000", "--net=container:parent", "busybox") 3409 if err == nil || !strings.Contains(out, runconfig.ErrConflictNetworkPublishPorts.Error()) { 3410 c.Fatalf("run --net=container with -p should error out") 3411 } 3412 3413 out, _, err = dockerCmdWithError("run", "-P", "--net=container:parent", "busybox") 3414 if err == nil || !strings.Contains(out, runconfig.ErrConflictNetworkPublishPorts.Error()) { 3415 c.Fatalf("run --net=container with -P should error out") 3416 } 3417 3418 out, _, err = dockerCmdWithError("run", "--expose", "5000", "--net=container:parent", "busybox") 3419 if err == nil || !strings.Contains(out, runconfig.ErrConflictNetworkExposePorts.Error()) { 3420 c.Fatalf("run --net=container with --expose should error out") 3421 } 3422 } 3423 3424 func (s *DockerSuite) TestRunLinkToContainerNetMode(c *check.C) { 3425 // Not applicable on Windows which does not support --net=container or --link 3426 testRequires(c, DaemonIsLinux, NotUserNamespace) 3427 dockerCmd(c, "run", "--name", "test", "-d", "busybox", "top") 3428 dockerCmd(c, "run", "--name", "parent", "-d", "--net=container:test", "busybox", "top") 3429 dockerCmd(c, "run", "-d", "--link=parent:parent", "busybox", "top") 3430 dockerCmd(c, "run", "--name", "child", "-d", "--net=container:parent", "busybox", "top") 3431 dockerCmd(c, "run", "-d", "--link=child:child", "busybox", "top") 3432 } 3433 3434 func (s *DockerSuite) TestRunLoopbackOnlyExistsWhenNetworkingDisabled(c *check.C) { 3435 // TODO Windows: This may be possible to convert. 3436 testRequires(c, DaemonIsLinux) 3437 out, _ := dockerCmd(c, "run", "--net=none", "busybox", "ip", "-o", "-4", "a", "show", "up") 3438 3439 var ( 3440 count = 0 3441 parts = strings.Split(out, "\n") 3442 ) 3443 3444 for _, l := range parts { 3445 if l != "" { 3446 count++ 3447 } 3448 } 3449 3450 if count != 1 { 3451 c.Fatalf("Wrong interface count in container %d", count) 3452 } 3453 3454 if !strings.HasPrefix(out, "1: lo") { 3455 c.Fatalf("Wrong interface in test container: expected [1: lo], got %s", out) 3456 } 3457 } 3458 3459 // Issue #4681 3460 func (s *DockerSuite) TestRunLoopbackWhenNetworkDisabled(c *check.C) { 3461 if daemonPlatform == "windows" { 3462 dockerCmd(c, "run", "--net=none", WindowsBaseImage, "ping", "-n", "1", "127.0.0.1") 3463 } else { 3464 dockerCmd(c, "run", "--net=none", "busybox", "ping", "-c", "1", "127.0.0.1") 3465 } 3466 } 3467 3468 func (s *DockerSuite) TestRunModeNetContainerHostname(c *check.C) { 3469 // Windows does not support --net=container 3470 testRequires(c, DaemonIsLinux, ExecSupport, NotUserNamespace) 3471 3472 dockerCmd(c, "run", "-i", "-d", "--name", "parent", "busybox", "top") 3473 out, _ := dockerCmd(c, "exec", "parent", "cat", "/etc/hostname") 3474 out1, _ := dockerCmd(c, "run", "--net=container:parent", "busybox", "cat", "/etc/hostname") 3475 3476 if out1 != out { 3477 c.Fatal("containers with shared net namespace should have same hostname") 3478 } 3479 } 3480 3481 func (s *DockerSuite) TestRunNetworkNotInitializedNoneMode(c *check.C) { 3482 // TODO Windows: Network settings are not currently propagated. This may 3483 // be resolved in the future with the move to libnetwork and CNM. 3484 testRequires(c, DaemonIsLinux) 3485 out, _ := dockerCmd(c, "run", "-d", "--net=none", "busybox", "top") 3486 id := strings.TrimSpace(out) 3487 res, err := inspectField(id, "NetworkSettings.Networks.none.IPAddress") 3488 c.Assert(err, check.IsNil) 3489 if res != "" { 3490 c.Fatalf("For 'none' mode network must not be initialized, but container got IP: %s", res) 3491 } 3492 } 3493 3494 func (s *DockerSuite) TestTwoContainersInNetHost(c *check.C) { 3495 // Not applicable as Windows does not support --net=host 3496 testRequires(c, DaemonIsLinux, NotUserNamespace, NotUserNamespace) 3497 dockerCmd(c, "run", "-d", "--net=host", "--name=first", "busybox", "top") 3498 dockerCmd(c, "run", "-d", "--net=host", "--name=second", "busybox", "top") 3499 dockerCmd(c, "stop", "first") 3500 dockerCmd(c, "stop", "second") 3501 } 3502 3503 func (s *DockerSuite) TestContainersInUserDefinedNetwork(c *check.C) { 3504 testRequires(c, DaemonIsLinux, NotUserNamespace) 3505 dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork") 3506 dockerCmd(c, "run", "-d", "--net=testnetwork", "--name=first", "busybox", "top") 3507 c.Assert(waitRun("first"), check.IsNil) 3508 dockerCmd(c, "run", "-t", "--net=testnetwork", "--name=second", "busybox", "ping", "-c", "1", "first") 3509 } 3510 3511 func (s *DockerSuite) TestContainersInMultipleNetworks(c *check.C) { 3512 testRequires(c, DaemonIsLinux, NotUserNamespace) 3513 // Create 2 networks using bridge driver 3514 dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1") 3515 dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork2") 3516 // Run and connect containers to testnetwork1 3517 dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=first", "busybox", "top") 3518 c.Assert(waitRun("first"), check.IsNil) 3519 dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=second", "busybox", "top") 3520 c.Assert(waitRun("second"), check.IsNil) 3521 // Check connectivity between containers in testnetwork2 3522 dockerCmd(c, "exec", "first", "ping", "-c", "1", "second.testnetwork1") 3523 // Connect containers to testnetwork2 3524 dockerCmd(c, "network", "connect", "testnetwork2", "first") 3525 dockerCmd(c, "network", "connect", "testnetwork2", "second") 3526 // Check connectivity between containers 3527 dockerCmd(c, "exec", "second", "ping", "-c", "1", "first.testnetwork2") 3528 } 3529 3530 func (s *DockerSuite) TestContainersNetworkIsolation(c *check.C) { 3531 testRequires(c, DaemonIsLinux, NotUserNamespace) 3532 // Create 2 networks using bridge driver 3533 dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1") 3534 dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork2") 3535 // Run 1 container in testnetwork1 and another in testnetwork2 3536 dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=first", "busybox", "top") 3537 c.Assert(waitRun("first"), check.IsNil) 3538 dockerCmd(c, "run", "-d", "--net=testnetwork2", "--name=second", "busybox", "top") 3539 c.Assert(waitRun("second"), check.IsNil) 3540 3541 // Check Isolation between containers : ping must fail 3542 _, _, err := dockerCmdWithError("exec", "first", "ping", "-c", "1", "second") 3543 c.Assert(err, check.NotNil) 3544 // Connect first container to testnetwork2 3545 dockerCmd(c, "network", "connect", "testnetwork2", "first") 3546 // ping must succeed now 3547 _, _, err = dockerCmdWithError("exec", "first", "ping", "-c", "1", "second") 3548 c.Assert(err, check.IsNil) 3549 3550 // Disconnect first container from testnetwork2 3551 dockerCmd(c, "network", "disconnect", "testnetwork2", "first") 3552 // ping must fail again 3553 _, _, err = dockerCmdWithError("exec", "first", "ping", "-c", "1", "second") 3554 c.Assert(err, check.NotNil) 3555 } 3556 3557 func (s *DockerSuite) TestNetworkRmWithActiveContainers(c *check.C) { 3558 testRequires(c, DaemonIsLinux, NotUserNamespace) 3559 // Create 2 networks using bridge driver 3560 dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1") 3561 // Run and connect containers to testnetwork1 3562 dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=first", "busybox", "top") 3563 c.Assert(waitRun("first"), check.IsNil) 3564 dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=second", "busybox", "top") 3565 c.Assert(waitRun("second"), check.IsNil) 3566 // Network delete with active containers must fail 3567 _, _, err := dockerCmdWithError("network", "rm", "testnetwork1") 3568 c.Assert(err, check.NotNil) 3569 3570 dockerCmd(c, "stop", "first") 3571 _, _, err = dockerCmdWithError("network", "rm", "testnetwork1") 3572 c.Assert(err, check.NotNil) 3573 } 3574 3575 func (s *DockerSuite) TestContainerRestartInMultipleNetworks(c *check.C) { 3576 testRequires(c, DaemonIsLinux, NotUserNamespace) 3577 // Create 2 networks using bridge driver 3578 dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1") 3579 dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork2") 3580 3581 // Run and connect containers to testnetwork1 3582 dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=first", "busybox", "top") 3583 c.Assert(waitRun("first"), check.IsNil) 3584 dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=second", "busybox", "top") 3585 c.Assert(waitRun("second"), check.IsNil) 3586 // Check connectivity between containers in testnetwork2 3587 dockerCmd(c, "exec", "first", "ping", "-c", "1", "second.testnetwork1") 3588 // Connect containers to testnetwork2 3589 dockerCmd(c, "network", "connect", "testnetwork2", "first") 3590 dockerCmd(c, "network", "connect", "testnetwork2", "second") 3591 // Check connectivity between containers 3592 dockerCmd(c, "exec", "second", "ping", "-c", "1", "first.testnetwork2") 3593 3594 // Stop second container and test ping failures on both networks 3595 dockerCmd(c, "stop", "second") 3596 _, _, err := dockerCmdWithError("exec", "first", "ping", "-c", "1", "second.testnetwork1") 3597 c.Assert(err, check.NotNil) 3598 _, _, err = dockerCmdWithError("exec", "first", "ping", "-c", "1", "second.testnetwork2") 3599 c.Assert(err, check.NotNil) 3600 3601 // Start second container and connectivity must be restored on both networks 3602 dockerCmd(c, "start", "second") 3603 dockerCmd(c, "exec", "first", "ping", "-c", "1", "second.testnetwork1") 3604 dockerCmd(c, "exec", "second", "ping", "-c", "1", "first.testnetwork2") 3605 } 3606 3607 func (s *DockerSuite) TestContainerWithConflictingHostNetworks(c *check.C) { 3608 testRequires(c, DaemonIsLinux, NotUserNamespace) 3609 // Run a container with --net=host 3610 dockerCmd(c, "run", "-d", "--net=host", "--name=first", "busybox", "top") 3611 c.Assert(waitRun("first"), check.IsNil) 3612 3613 // Create a network using bridge driver 3614 dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1") 3615 3616 // Connecting to the user defined network must fail 3617 _, _, err := dockerCmdWithError("network", "connect", "testnetwork1", "first") 3618 c.Assert(err, check.NotNil) 3619 } 3620 3621 func (s *DockerSuite) TestContainerWithConflictingSharedNetwork(c *check.C) { 3622 testRequires(c, DaemonIsLinux, NotUserNamespace) 3623 dockerCmd(c, "run", "-d", "--name=first", "busybox", "top") 3624 c.Assert(waitRun("first"), check.IsNil) 3625 // Run second container in first container's network namespace 3626 dockerCmd(c, "run", "-d", "--net=container:first", "--name=second", "busybox", "top") 3627 c.Assert(waitRun("second"), check.IsNil) 3628 3629 // Create a network using bridge driver 3630 dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1") 3631 3632 // Connecting to the user defined network must fail 3633 out, _, err := dockerCmdWithError("network", "connect", "testnetwork1", "second") 3634 c.Assert(err, check.NotNil) 3635 c.Assert(out, checker.Contains, runconfig.ErrConflictSharedNetwork.Error()) 3636 } 3637 3638 func (s *DockerSuite) TestContainerWithConflictingNoneNetwork(c *check.C) { 3639 testRequires(c, DaemonIsLinux, NotUserNamespace) 3640 dockerCmd(c, "run", "-d", "--net=none", "--name=first", "busybox", "top") 3641 c.Assert(waitRun("first"), check.IsNil) 3642 3643 // Create a network using bridge driver 3644 dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1") 3645 3646 // Connecting to the user defined network must fail 3647 out, _, err := dockerCmdWithError("network", "connect", "testnetwork1", "first") 3648 c.Assert(err, check.NotNil) 3649 c.Assert(out, checker.Contains, runconfig.ErrConflictNoNetwork.Error()) 3650 3651 // create a container connected to testnetwork1 3652 dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=second", "busybox", "top") 3653 c.Assert(waitRun("second"), check.IsNil) 3654 3655 // Connect second container to none network. it must fail as well 3656 _, _, err = dockerCmdWithError("network", "connect", "none", "second") 3657 c.Assert(err, check.NotNil) 3658 } 3659 3660 // #11957 - stdin with no tty does not exit if stdin is not closed even though container exited 3661 func (s *DockerSuite) TestRunStdinBlockedAfterContainerExit(c *check.C) { 3662 cmd := exec.Command(dockerBinary, "run", "-i", "--name=test", "busybox", "true") 3663 in, err := cmd.StdinPipe() 3664 c.Assert(err, check.IsNil) 3665 defer in.Close() 3666 c.Assert(cmd.Start(), check.IsNil) 3667 3668 waitChan := make(chan error) 3669 go func() { 3670 waitChan <- cmd.Wait() 3671 }() 3672 3673 select { 3674 case err := <-waitChan: 3675 c.Assert(err, check.IsNil) 3676 case <-time.After(30 * time.Second): 3677 c.Fatal("timeout waiting for command to exit") 3678 } 3679 } 3680 3681 func (s *DockerSuite) TestRunWrongCpusetCpusFlagValue(c *check.C) { 3682 // TODO Windows: This needs validation (error out) in the daemon. 3683 testRequires(c, DaemonIsLinux) 3684 out, exitCode, err := dockerCmdWithError("run", "--cpuset-cpus", "1-10,11--", "busybox", "true") 3685 c.Assert(err, check.NotNil) 3686 expected := "Error response from daemon: Invalid value 1-10,11-- for cpuset cpus.\n" 3687 if !(strings.Contains(out, expected) || exitCode == 125) { 3688 c.Fatalf("Expected output to contain %q with exitCode 125, got out: %q exitCode: %v", expected, out, exitCode) 3689 } 3690 } 3691 3692 func (s *DockerSuite) TestRunWrongCpusetMemsFlagValue(c *check.C) { 3693 // TODO Windows: This needs validation (error out) in the daemon. 3694 testRequires(c, DaemonIsLinux) 3695 out, exitCode, err := dockerCmdWithError("run", "--cpuset-mems", "1-42--", "busybox", "true") 3696 c.Assert(err, check.NotNil) 3697 expected := "Error response from daemon: Invalid value 1-42-- for cpuset mems.\n" 3698 if !(strings.Contains(out, expected) || exitCode == 125) { 3699 c.Fatalf("Expected output to contain %q with exitCode 125, got out: %q exitCode: %v", expected, out, exitCode) 3700 } 3701 } 3702 3703 // TestRunNonExecutableCmd checks that 'docker run busybox foo' exits with error code 127' 3704 func (s *DockerSuite) TestRunNonExecutableCmd(c *check.C) { 3705 name := "testNonExecutableCmd" 3706 runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "foo") 3707 _, exit, _ := runCommandWithOutput(runCmd) 3708 stateExitCode := findContainerExitCode(c, name) 3709 if !(exit == 127 && strings.Contains(stateExitCode, "127")) { 3710 c.Fatalf("Run non-executable command should have errored with exit code 127, but we got exit: %d, State.ExitCode: %s", exit, stateExitCode) 3711 } 3712 } 3713 3714 // TestRunNonExistingCmd checks that 'docker run busybox /bin/foo' exits with code 127. 3715 func (s *DockerSuite) TestRunNonExistingCmd(c *check.C) { 3716 name := "testNonExistingCmd" 3717 runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "/bin/foo") 3718 _, exit, _ := runCommandWithOutput(runCmd) 3719 stateExitCode := findContainerExitCode(c, name) 3720 if !(exit == 127 && strings.Contains(stateExitCode, "127")) { 3721 c.Fatalf("Run non-existing command should have errored with exit code 127, but we got exit: %d, State.ExitCode: %s", exit, stateExitCode) 3722 } 3723 } 3724 3725 // TestCmdCannotBeInvoked checks that 'docker run busybox /etc' exits with 126. 3726 func (s *DockerSuite) TestCmdCannotBeInvoked(c *check.C) { 3727 name := "testCmdCannotBeInvoked" 3728 runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "/etc") 3729 _, exit, _ := runCommandWithOutput(runCmd) 3730 stateExitCode := findContainerExitCode(c, name) 3731 if !(exit == 126 && strings.Contains(stateExitCode, "126")) { 3732 c.Fatalf("Run cmd that cannot be invoked should have errored with code 126, but we got exit: %d, State.ExitCode: %s", exit, stateExitCode) 3733 } 3734 } 3735 3736 // TestRunNonExistingImage checks that 'docker run foo' exits with error msg 125 and contains 'Unable to find image' 3737 func (s *DockerSuite) TestRunNonExistingImage(c *check.C) { 3738 runCmd := exec.Command(dockerBinary, "run", "foo") 3739 out, exit, err := runCommandWithOutput(runCmd) 3740 if !(err != nil && exit == 125 && strings.Contains(out, "Unable to find image")) { 3741 c.Fatalf("Run non-existing image should have errored with 'Unable to find image' code 125, but we got out: %s, exit: %d, err: %s", out, exit, err) 3742 } 3743 } 3744 3745 // TestDockerFails checks that 'docker run -foo busybox' exits with 125 to signal docker run failed 3746 func (s *DockerSuite) TestDockerFails(c *check.C) { 3747 runCmd := exec.Command(dockerBinary, "run", "-foo", "busybox") 3748 out, exit, err := runCommandWithOutput(runCmd) 3749 if !(err != nil && exit == 125) { 3750 c.Fatalf("Docker run with flag not defined should exit with 125, but we got out: %s, exit: %d, err: %s", out, exit, err) 3751 } 3752 } 3753 3754 // TestRunInvalidReference invokes docker run with a bad reference. 3755 func (s *DockerSuite) TestRunInvalidReference(c *check.C) { 3756 out, exit, _ := dockerCmdWithError("run", "busybox@foo") 3757 if exit == 0 { 3758 c.Fatalf("expected non-zero exist code; received %d", exit) 3759 } 3760 3761 if !strings.Contains(out, "Error parsing reference") { 3762 c.Fatalf(`Expected "Error parsing reference" in output; got: %s`, out) 3763 } 3764 } 3765 3766 // Test fix for issue #17854 3767 func (s *DockerSuite) TestRunInitLayerPathOwnership(c *check.C) { 3768 // Not applicable on Windows as it does not support Linux uid/gid ownership 3769 testRequires(c, DaemonIsLinux) 3770 name := "testetcfileownership" 3771 _, err := buildImage(name, 3772 `FROM busybox 3773 RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd 3774 RUN echo 'dockerio:x:1001:' >> /etc/group 3775 RUN chown dockerio:dockerio /etc`, 3776 true) 3777 if err != nil { 3778 c.Fatal(err) 3779 } 3780 3781 // Test that dockerio ownership of /etc is retained at runtime 3782 out, _ := dockerCmd(c, "run", "--rm", name, "stat", "-c", "%U:%G", "/etc") 3783 out = strings.TrimSpace(out) 3784 if out != "dockerio:dockerio" { 3785 c.Fatalf("Wrong /etc ownership: expected dockerio:dockerio, got %q", out) 3786 } 3787 } 3788 3789 func (s *DockerSuite) TestRunWithOomScoreAdj(c *check.C) { 3790 testRequires(c, DaemonIsLinux) 3791 3792 expected := "642" 3793 out, _ := dockerCmd(c, "run", "--oom-score-adj", expected, "busybox", "cat", "/proc/self/oom_score_adj") 3794 oomScoreAdj := strings.TrimSpace(out) 3795 if oomScoreAdj != "642" { 3796 c.Fatalf("Expected oom_score_adj set to %q, got %q instead", expected, oomScoreAdj) 3797 } 3798 } 3799 3800 func (s *DockerSuite) TestRunWithOomScoreAdjInvalidRange(c *check.C) { 3801 testRequires(c, DaemonIsLinux) 3802 3803 out, _, err := dockerCmdWithError("run", "--oom-score-adj", "1001", "busybox", "true") 3804 c.Assert(err, check.NotNil) 3805 expected := "Invalid value 1001, range for oom score adj is [-1000, 1000]." 3806 if !strings.Contains(out, expected) { 3807 c.Fatalf("Expected output to contain %q, got %q instead", expected, out) 3808 } 3809 out, _, err = dockerCmdWithError("run", "--oom-score-adj", "-1001", "busybox", "true") 3810 c.Assert(err, check.NotNil) 3811 expected = "Invalid value -1001, range for oom score adj is [-1000, 1000]." 3812 if !strings.Contains(out, expected) { 3813 c.Fatalf("Expected output to contain %q, got %q instead", expected, out) 3814 } 3815 } 3816 3817 func (s *DockerSuite) TestRunVolumesMountedAsShared(c *check.C) { 3818 // Volume propagation is linux only. Also it creates directories for 3819 // bind mounting, so needs to be same host. 3820 testRequires(c, DaemonIsLinux, SameHostDaemon, NotUserNamespace) 3821 3822 // Prepare a source directory to bind mount 3823 tmpDir, err := ioutil.TempDir("", "volume-source") 3824 if err != nil { 3825 c.Fatal(err) 3826 } 3827 defer os.RemoveAll(tmpDir) 3828 3829 if err := os.Mkdir(path.Join(tmpDir, "mnt1"), 0755); err != nil { 3830 c.Fatal(err) 3831 } 3832 3833 // Convert this directory into a shared mount point so that we do 3834 // not rely on propagation properties of parent mount. 3835 cmd := exec.Command("mount", "--bind", tmpDir, tmpDir) 3836 if _, err = runCommand(cmd); err != nil { 3837 c.Fatal(err) 3838 } 3839 3840 cmd = exec.Command("mount", "--make-private", "--make-shared", tmpDir) 3841 if _, err = runCommand(cmd); err != nil { 3842 c.Fatal(err) 3843 } 3844 3845 dockerCmd(c, "run", "--privileged", "-v", fmt.Sprintf("%s:/volume-dest:shared", tmpDir), "busybox", "mount", "--bind", "/volume-dest/mnt1", "/volume-dest/mnt1") 3846 3847 // Make sure a bind mount under a shared volume propagated to host. 3848 if mounted, _ := mount.Mounted(path.Join(tmpDir, "mnt1")); !mounted { 3849 c.Fatalf("Bind mount under shared volume did not propagate to host") 3850 } 3851 3852 mount.Unmount(path.Join(tmpDir, "mnt1")) 3853 } 3854 3855 func (s *DockerSuite) TestRunVolumesMountedAsSlave(c *check.C) { 3856 // Volume propagation is linux only. Also it creates directories for 3857 // bind mounting, so needs to be same host. 3858 testRequires(c, DaemonIsLinux, SameHostDaemon, NotUserNamespace) 3859 3860 // Prepare a source directory to bind mount 3861 tmpDir, err := ioutil.TempDir("", "volume-source") 3862 if err != nil { 3863 c.Fatal(err) 3864 } 3865 defer os.RemoveAll(tmpDir) 3866 3867 if err := os.Mkdir(path.Join(tmpDir, "mnt1"), 0755); err != nil { 3868 c.Fatal(err) 3869 } 3870 3871 // Prepare a source directory with file in it. We will bind mount this 3872 // direcotry and see if file shows up. 3873 tmpDir2, err := ioutil.TempDir("", "volume-source2") 3874 if err != nil { 3875 c.Fatal(err) 3876 } 3877 defer os.RemoveAll(tmpDir2) 3878 3879 if err := ioutil.WriteFile(path.Join(tmpDir2, "slave-testfile"), []byte("Test"), 0644); err != nil { 3880 c.Fatal(err) 3881 } 3882 3883 // Convert this directory into a shared mount point so that we do 3884 // not rely on propagation properties of parent mount. 3885 cmd := exec.Command("mount", "--bind", tmpDir, tmpDir) 3886 if _, err = runCommand(cmd); err != nil { 3887 c.Fatal(err) 3888 } 3889 3890 cmd = exec.Command("mount", "--make-private", "--make-shared", tmpDir) 3891 if _, err = runCommand(cmd); err != nil { 3892 c.Fatal(err) 3893 } 3894 3895 dockerCmd(c, "run", "-i", "-d", "--name", "parent", "-v", fmt.Sprintf("%s:/volume-dest:slave", tmpDir), "busybox", "top") 3896 3897 // Bind mount tmpDir2/ onto tmpDir/mnt1. If mount propagates inside 3898 // container then contents of tmpDir2/slave-testfile should become 3899 // visible at "/volume-dest/mnt1/slave-testfile" 3900 cmd = exec.Command("mount", "--bind", tmpDir2, path.Join(tmpDir, "mnt1")) 3901 if _, err = runCommand(cmd); err != nil { 3902 c.Fatal(err) 3903 } 3904 3905 out, _ := dockerCmd(c, "exec", "parent", "cat", "/volume-dest/mnt1/slave-testfile") 3906 3907 mount.Unmount(path.Join(tmpDir, "mnt1")) 3908 3909 if out != "Test" { 3910 c.Fatalf("Bind mount under slave volume did not propagate to container") 3911 } 3912 } 3913 3914 func (s *DockerSuite) TestRunNamedVolumesMountedAsShared(c *check.C) { 3915 testRequires(c, DaemonIsLinux, NotUserNamespace) 3916 out, exitcode, _ := dockerCmdWithError("run", "-v", "foo:/test:shared", "busybox", "touch", "/test/somefile") 3917 3918 if exitcode == 0 { 3919 c.Fatalf("expected non-zero exit code; received %d", exitcode) 3920 } 3921 3922 if expected := "Invalid volume specification"; !strings.Contains(out, expected) { 3923 c.Fatalf(`Expected %q in output; got: %s`, expected, out) 3924 } 3925 3926 }