github.com/thieman/docker@v1.6.0/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 "testing" 20 "time" 21 22 "github.com/docker/docker/nat" 23 "github.com/docker/docker/pkg/networkfs/resolvconf" 24 ) 25 26 // "test123" should be printed by docker run 27 func TestRunEchoStdout(t *testing.T) { 28 defer deleteAllContainers() 29 runCmd := exec.Command(dockerBinary, "run", "busybox", "echo", "test123") 30 out, _, _, err := runCommandWithStdoutStderr(runCmd) 31 if err != nil { 32 t.Fatalf("failed to run container: %v, output: %q", err, out) 33 } 34 35 if out != "test123\n" { 36 t.Errorf("container should've printed 'test123'") 37 } 38 39 logDone("run - echo test123") 40 } 41 42 // "test" should be printed 43 func TestRunEchoStdoutWithMemoryLimit(t *testing.T) { 44 defer deleteAllContainers() 45 runCmd := exec.Command(dockerBinary, "run", "-m", "16m", "busybox", "echo", "test") 46 out, _, _, err := runCommandWithStdoutStderr(runCmd) 47 if err != nil { 48 t.Fatalf("failed to run container: %v, output: %q", err, out) 49 } 50 51 out = strings.Trim(out, "\r\n") 52 53 if expected := "test"; out != expected { 54 t.Errorf("container should've printed %q but printed %q", expected, out) 55 56 } 57 58 logDone("run - echo with memory limit") 59 } 60 61 // should run without memory swap 62 func TestRunWithoutMemoryswapLimit(t *testing.T) { 63 defer deleteAllContainers() 64 65 runCmd := exec.Command(dockerBinary, "run", "-m", "16m", "--memory-swap", "-1", "busybox", "true") 66 out, _, err := runCommandWithOutput(runCmd) 67 if err != nil { 68 t.Fatalf("failed to run container, output: %q", out) 69 } 70 71 logDone("run - without memory swap limit") 72 } 73 74 // "test" should be printed 75 func TestRunEchoStdoutWitCPULimit(t *testing.T) { 76 defer deleteAllContainers() 77 78 runCmd := exec.Command(dockerBinary, "run", "-c", "1000", "busybox", "echo", "test") 79 out, _, _, err := runCommandWithStdoutStderr(runCmd) 80 if err != nil { 81 t.Fatalf("failed to run container: %v, output: %q", err, out) 82 } 83 84 if out != "test\n" { 85 t.Errorf("container should've printed 'test'") 86 } 87 88 logDone("run - echo with CPU limit") 89 } 90 91 // "test" should be printed 92 func TestRunEchoStdoutWithCPUAndMemoryLimit(t *testing.T) { 93 defer deleteAllContainers() 94 95 runCmd := exec.Command(dockerBinary, "run", "-c", "1000", "-m", "16m", "busybox", "echo", "test") 96 out, _, _, err := runCommandWithStdoutStderr(runCmd) 97 if err != nil { 98 t.Fatalf("failed to run container: %v, output: %q", err, out) 99 } 100 101 if out != "test\n" { 102 t.Errorf("container should've printed 'test', got %q instead", out) 103 } 104 105 logDone("run - echo with CPU and memory limit") 106 } 107 108 // "test" should be printed 109 func TestRunEchoNamedContainer(t *testing.T) { 110 defer deleteAllContainers() 111 112 runCmd := exec.Command(dockerBinary, "run", "--name", "testfoonamedcontainer", "busybox", "echo", "test") 113 out, _, _, err := runCommandWithStdoutStderr(runCmd) 114 if err != nil { 115 t.Fatalf("failed to run container: %v, output: %q", err, out) 116 } 117 118 if out != "test\n" { 119 t.Errorf("container should've printed 'test'") 120 } 121 122 if err := deleteContainer("testfoonamedcontainer"); err != nil { 123 t.Errorf("failed to remove the named container: %v", err) 124 } 125 126 logDone("run - echo with named container") 127 } 128 129 // docker run should not leak file descriptors 130 func TestRunLeakyFileDescriptors(t *testing.T) { 131 defer deleteAllContainers() 132 133 runCmd := exec.Command(dockerBinary, "run", "busybox", "ls", "-C", "/proc/self/fd") 134 out, _, _, err := runCommandWithStdoutStderr(runCmd) 135 if err != nil { 136 t.Fatalf("failed to run container: %v, output: %q", err, out) 137 } 138 139 // normally, we should only get 0, 1, and 2, but 3 gets created by "ls" when it does "opendir" on the "fd" directory 140 if out != "0 1 2 3\n" { 141 t.Errorf("container should've printed '0 1 2 3', not: %s", out) 142 } 143 144 logDone("run - check file descriptor leakage") 145 } 146 147 // it should be possible to lookup Google DNS 148 // this will fail when Internet access is unavailable 149 func TestRunLookupGoogleDns(t *testing.T) { 150 defer deleteAllContainers() 151 152 out, _, _, err := runCommandWithStdoutStderr(exec.Command(dockerBinary, "run", "busybox", "nslookup", "google.com")) 153 if err != nil { 154 t.Fatalf("failed to run container: %v, output: %q", err, out) 155 } 156 157 logDone("run - nslookup google.com") 158 } 159 160 // the exit code should be 0 161 // some versions of lxc might make this test fail 162 func TestRunExitCodeZero(t *testing.T) { 163 defer deleteAllContainers() 164 165 runCmd := exec.Command(dockerBinary, "run", "busybox", "true") 166 if out, _, err := runCommandWithOutput(runCmd); err != nil { 167 t.Errorf("container should've exited with exit code 0: %s, %v", out, err) 168 } 169 170 logDone("run - exit with 0") 171 } 172 173 // the exit code should be 1 174 // some versions of lxc might make this test fail 175 func TestRunExitCodeOne(t *testing.T) { 176 defer deleteAllContainers() 177 178 runCmd := exec.Command(dockerBinary, "run", "busybox", "false") 179 exitCode, err := runCommand(runCmd) 180 if err != nil && !strings.Contains("exit status 1", fmt.Sprintf("%s", err)) { 181 t.Fatal(err) 182 } 183 if exitCode != 1 { 184 t.Errorf("container should've exited with exit code 1") 185 } 186 187 logDone("run - exit with 1") 188 } 189 190 // it should be possible to pipe in data via stdin to a process running in a container 191 // some versions of lxc might make this test fail 192 func TestRunStdinPipe(t *testing.T) { 193 defer deleteAllContainers() 194 195 runCmd := exec.Command("bash", "-c", `echo "blahblah" | docker run -i -a stdin busybox cat`) 196 out, _, _, err := runCommandWithStdoutStderr(runCmd) 197 if err != nil { 198 t.Fatalf("failed to run container: %v, output: %q", err, out) 199 } 200 201 out = stripTrailingCharacters(out) 202 203 inspectCmd := exec.Command(dockerBinary, "inspect", out) 204 if out, _, err := runCommandWithOutput(inspectCmd); err != nil { 205 t.Fatalf("out should've been a container id: %s %v", out, err) 206 } 207 208 waitCmd := exec.Command(dockerBinary, "wait", out) 209 if waitOut, _, err := runCommandWithOutput(waitCmd); err != nil { 210 t.Fatalf("error thrown while waiting for container: %s, %v", waitOut, err) 211 } 212 213 logsCmd := exec.Command(dockerBinary, "logs", out) 214 logsOut, _, err := runCommandWithOutput(logsCmd) 215 if err != nil { 216 t.Fatalf("error thrown while trying to get container logs: %s, %v", logsOut, err) 217 } 218 219 containerLogs := stripTrailingCharacters(logsOut) 220 221 if containerLogs != "blahblah" { 222 t.Errorf("logs didn't print the container's logs %s", containerLogs) 223 } 224 225 rmCmd := exec.Command(dockerBinary, "rm", out) 226 if out, _, err = runCommandWithOutput(rmCmd); err != nil { 227 t.Fatalf("rm failed to remove container: %s, %v", out, err) 228 } 229 230 logDone("run - pipe in with -i -a stdin") 231 } 232 233 // the container's ID should be printed when starting a container in detached mode 234 func TestRunDetachedContainerIDPrinting(t *testing.T) { 235 defer deleteAllContainers() 236 237 runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true") 238 out, _, _, err := runCommandWithStdoutStderr(runCmd) 239 if err != nil { 240 t.Fatalf("failed to run container: %v, output: %q", err, out) 241 } 242 243 out = stripTrailingCharacters(out) 244 245 inspectCmd := exec.Command(dockerBinary, "inspect", out) 246 if inspectOut, _, err := runCommandWithOutput(inspectCmd); err != nil { 247 t.Fatalf("out should've been a container id: %s %v", inspectOut, err) 248 } 249 250 waitCmd := exec.Command(dockerBinary, "wait", out) 251 if waitOut, _, err := runCommandWithOutput(waitCmd); err != nil { 252 t.Fatalf("error thrown while waiting for container: %s, %v", waitOut, err) 253 } 254 255 rmCmd := exec.Command(dockerBinary, "rm", out) 256 rmOut, _, err := runCommandWithOutput(rmCmd) 257 if err != nil { 258 t.Fatalf("rm failed to remove container: %s, %v", rmOut, err) 259 } 260 261 rmOut = stripTrailingCharacters(rmOut) 262 if rmOut != out { 263 t.Errorf("rm didn't print the container ID %s %s", out, rmOut) 264 } 265 266 logDone("run - print container ID in detached mode") 267 } 268 269 // the working directory should be set correctly 270 func TestRunWorkingDirectory(t *testing.T) { 271 defer deleteAllContainers() 272 273 runCmd := exec.Command(dockerBinary, "run", "-w", "/root", "busybox", "pwd") 274 out, _, _, err := runCommandWithStdoutStderr(runCmd) 275 if err != nil { 276 t.Fatalf("failed to run container: %v, output: %q", err, out) 277 } 278 279 out = stripTrailingCharacters(out) 280 281 if out != "/root" { 282 t.Errorf("-w failed to set working directory") 283 } 284 285 runCmd = exec.Command(dockerBinary, "run", "--workdir", "/root", "busybox", "pwd") 286 out, _, _, err = runCommandWithStdoutStderr(runCmd) 287 if err != nil { 288 t.Fatal(out, err) 289 } 290 291 out = stripTrailingCharacters(out) 292 293 if out != "/root" { 294 t.Errorf("--workdir failed to set working directory") 295 } 296 297 logDone("run - run with working directory set by -w") 298 logDone("run - run with working directory set by --workdir") 299 } 300 301 // pinging Google's DNS resolver should fail when we disable the networking 302 func TestRunWithoutNetworking(t *testing.T) { 303 defer deleteAllContainers() 304 305 runCmd := exec.Command(dockerBinary, "run", "--net=none", "busybox", "ping", "-c", "1", "8.8.8.8") 306 out, _, exitCode, err := runCommandWithStdoutStderr(runCmd) 307 if err != nil && exitCode != 1 { 308 t.Fatal(out, err) 309 } 310 if exitCode != 1 { 311 t.Errorf("--net=none should've disabled the network; the container shouldn't have been able to ping 8.8.8.8") 312 } 313 314 runCmd = exec.Command(dockerBinary, "run", "-n=false", "busybox", "ping", "-c", "1", "8.8.8.8") 315 out, _, exitCode, err = runCommandWithStdoutStderr(runCmd) 316 if err != nil && exitCode != 1 { 317 t.Fatal(out, err) 318 } 319 if exitCode != 1 { 320 t.Errorf("-n=false should've disabled the network; the container shouldn't have been able to ping 8.8.8.8") 321 } 322 323 logDone("run - disable networking with --net=none") 324 logDone("run - disable networking with -n=false") 325 } 326 327 //test --link use container name to link target 328 func TestRunLinksContainerWithContainerName(t *testing.T) { 329 defer deleteAllContainers() 330 331 cmd := exec.Command(dockerBinary, "run", "-i", "-t", "-d", "--name", "parent", "busybox") 332 out, _, _, err := runCommandWithStdoutStderr(cmd) 333 if err != nil { 334 t.Fatalf("failed to run container: %v, output: %q", err, out) 335 } 336 cmd = exec.Command(dockerBinary, "inspect", "-f", "{{.NetworkSettings.IPAddress}}", "parent") 337 ip, _, _, err := runCommandWithStdoutStderr(cmd) 338 if err != nil { 339 t.Fatalf("failed to inspect container: %v, output: %q", err, ip) 340 } 341 ip = strings.TrimSpace(ip) 342 cmd = exec.Command(dockerBinary, "run", "--link", "parent:test", "busybox", "/bin/cat", "/etc/hosts") 343 out, _, err = runCommandWithOutput(cmd) 344 if err != nil { 345 t.Fatalf("failed to run container: %v, output: %q", err, out) 346 } 347 if !strings.Contains(out, ip+" test") { 348 t.Fatalf("use a container name to link target failed") 349 } 350 351 logDone("run - use a container name to link target work") 352 } 353 354 //test --link use container id to link target 355 func TestRunLinksContainerWithContainerId(t *testing.T) { 356 defer deleteAllContainers() 357 358 cmd := exec.Command(dockerBinary, "run", "-i", "-t", "-d", "busybox") 359 cID, _, _, err := runCommandWithStdoutStderr(cmd) 360 if err != nil { 361 t.Fatalf("failed to run container: %v, output: %q", err, cID) 362 } 363 cID = strings.TrimSpace(cID) 364 cmd = exec.Command(dockerBinary, "inspect", "-f", "{{.NetworkSettings.IPAddress}}", cID) 365 ip, _, _, err := runCommandWithStdoutStderr(cmd) 366 if err != nil { 367 t.Fatalf("faild to inspect container: %v, output: %q", err, ip) 368 } 369 ip = strings.TrimSpace(ip) 370 cmd = exec.Command(dockerBinary, "run", "--link", cID+":test", "busybox", "/bin/cat", "/etc/hosts") 371 out, _, err := runCommandWithOutput(cmd) 372 if err != nil { 373 t.Fatalf("failed to run container: %v, output: %q", err, out) 374 } 375 if !strings.Contains(out, ip+" test") { 376 t.Fatalf("use a container id to link target failed") 377 } 378 379 logDone("run - use a container id to link target work") 380 } 381 382 func TestRunLinkToContainerNetMode(t *testing.T) { 383 defer deleteAllContainers() 384 385 cmd := exec.Command(dockerBinary, "run", "--name", "test", "-d", "busybox", "top") 386 out, _, err := runCommandWithOutput(cmd) 387 if err != nil { 388 t.Fatalf("failed to run container: %v, output: %q", err, out) 389 } 390 cmd = exec.Command(dockerBinary, "run", "--name", "parent", "-d", "--net=container:test", "busybox", "top") 391 out, _, err = runCommandWithOutput(cmd) 392 if err != nil { 393 t.Fatalf("failed to run container: %v, output: %q", err, out) 394 } 395 cmd = exec.Command(dockerBinary, "run", "-d", "--link=parent:parent", "busybox", "top") 396 out, _, err = runCommandWithOutput(cmd) 397 if err != nil { 398 t.Fatalf("failed to run container: %v, output: %q", err, out) 399 } 400 401 cmd = exec.Command(dockerBinary, "run", "--name", "child", "-d", "--net=container:parent", "busybox", "top") 402 out, _, err = runCommandWithOutput(cmd) 403 if err != nil { 404 t.Fatalf("failed to run container: %v, output: %q", err, out) 405 } 406 cmd = exec.Command(dockerBinary, "run", "-d", "--link=child:child", "busybox", "top") 407 out, _, err = runCommandWithOutput(cmd) 408 if err != nil { 409 t.Fatalf("failed to run container: %v, output: %q", err, out) 410 } 411 412 logDone("run - link to a container which net mode is container success") 413 } 414 415 func TestRunModeNetContainerHostname(t *testing.T) { 416 testRequires(t, ExecSupport) 417 defer deleteAllContainers() 418 cmd := exec.Command(dockerBinary, "run", "-i", "-d", "--name", "parent", "busybox", "top") 419 out, _, err := runCommandWithOutput(cmd) 420 if err != nil { 421 t.Fatalf("failed to run container: %v, output: %q", err, out) 422 } 423 cmd = exec.Command(dockerBinary, "exec", "parent", "cat", "/etc/hostname") 424 out, _, err = runCommandWithOutput(cmd) 425 if err != nil { 426 t.Fatalf("failed to exec command: %v, output: %q", err, out) 427 } 428 429 cmd = exec.Command(dockerBinary, "run", "--net=container:parent", "busybox", "cat", "/etc/hostname") 430 out1, _, err := runCommandWithOutput(cmd) 431 if err != nil { 432 t.Fatalf("failed to run container: %v, output: %q", err, out1) 433 } 434 if out1 != out { 435 t.Fatal("containers with shared net namespace should have same hostname") 436 } 437 438 logDone("run - containers with shared net namespace have same hostname") 439 } 440 441 // Regression test for #4741 442 func TestRunWithVolumesAsFiles(t *testing.T) { 443 defer deleteAllContainers() 444 445 runCmd := exec.Command(dockerBinary, "run", "--name", "test-data", "--volume", "/etc/hosts:/target-file", "busybox", "true") 446 out, stderr, exitCode, err := runCommandWithStdoutStderr(runCmd) 447 if err != nil && exitCode != 0 { 448 t.Fatal("1", out, stderr, err) 449 } 450 451 runCmd = exec.Command(dockerBinary, "run", "--volumes-from", "test-data", "busybox", "cat", "/target-file") 452 out, stderr, exitCode, err = runCommandWithStdoutStderr(runCmd) 453 if err != nil && exitCode != 0 { 454 t.Fatal("2", out, stderr, err) 455 } 456 457 logDone("run - regression test for #4741 - volumes from as files") 458 } 459 460 // Regression test for #4979 461 func TestRunWithVolumesFromExited(t *testing.T) { 462 defer deleteAllContainers() 463 464 runCmd := exec.Command(dockerBinary, "run", "--name", "test-data", "--volume", "/some/dir", "busybox", "touch", "/some/dir/file") 465 out, stderr, exitCode, err := runCommandWithStdoutStderr(runCmd) 466 if err != nil && exitCode != 0 { 467 t.Fatal("1", out, stderr, err) 468 } 469 470 runCmd = exec.Command(dockerBinary, "run", "--volumes-from", "test-data", "busybox", "cat", "/some/dir/file") 471 out, stderr, exitCode, err = runCommandWithStdoutStderr(runCmd) 472 if err != nil && exitCode != 0 { 473 t.Fatal("2", out, stderr, err) 474 } 475 476 logDone("run - regression test for #4979 - volumes-from on exited container") 477 } 478 479 // Volume path is a symlink which also exists on the host, and the host side is a file not a dir 480 // But the volume call is just a normal volume, not a bind mount 481 func TestRunCreateVolumesInSymlinkDir(t *testing.T) { 482 testRequires(t, SameHostDaemon) 483 testRequires(t, NativeExecDriver) 484 defer deleteAllContainers() 485 name := "test-volume-symlink" 486 487 dir, err := ioutil.TempDir("", name) 488 if err != nil { 489 t.Fatal(err) 490 } 491 defer os.RemoveAll(dir) 492 493 f, err := os.OpenFile(filepath.Join(dir, "test"), os.O_CREATE, 0700) 494 if err != nil { 495 t.Fatal(err) 496 } 497 f.Close() 498 499 dockerFile := fmt.Sprintf("FROM busybox\nRUN mkdir -p %s\nRUN ln -s %s /test", dir, dir) 500 if _, err := buildImage(name, dockerFile, false); err != nil { 501 t.Fatal(err) 502 } 503 defer deleteImages(name) 504 505 if out, _, err := dockerCmd(t, "run", "-v", "/test/test", name); err != nil { 506 t.Fatal(err, out) 507 } 508 509 logDone("run - create volume in symlink directory") 510 } 511 512 // Regression test for #4830 513 func TestRunWithRelativePath(t *testing.T) { 514 defer deleteAllContainers() 515 516 runCmd := exec.Command(dockerBinary, "run", "-v", "tmp:/other-tmp", "busybox", "true") 517 if _, _, _, err := runCommandWithStdoutStderr(runCmd); err == nil { 518 t.Fatalf("relative path should result in an error") 519 } 520 521 logDone("run - volume with relative path") 522 } 523 524 func TestRunVolumesMountedAsReadonly(t *testing.T) { 525 defer deleteAllContainers() 526 527 cmd := exec.Command(dockerBinary, "run", "-v", "/test:/test:ro", "busybox", "touch", "/test/somefile") 528 if code, err := runCommand(cmd); err == nil || code == 0 { 529 t.Fatalf("run should fail because volume is ro: exit code %d", code) 530 } 531 532 logDone("run - volumes as readonly mount") 533 } 534 535 func TestRunVolumesFromInReadonlyMode(t *testing.T) { 536 defer deleteAllContainers() 537 cmd := exec.Command(dockerBinary, "run", "--name", "parent", "-v", "/test", "busybox", "true") 538 if _, err := runCommand(cmd); err != nil { 539 t.Fatal(err) 540 } 541 542 cmd = exec.Command(dockerBinary, "run", "--volumes-from", "parent:ro", "busybox", "touch", "/test/file") 543 if code, err := runCommand(cmd); err == nil || code == 0 { 544 t.Fatalf("run should fail because volume is ro: exit code %d", code) 545 } 546 547 logDone("run - volumes from as readonly mount") 548 } 549 550 // Regression test for #1201 551 func TestRunVolumesFromInReadWriteMode(t *testing.T) { 552 defer deleteAllContainers() 553 cmd := exec.Command(dockerBinary, "run", "--name", "parent", "-v", "/test", "busybox", "true") 554 if _, err := runCommand(cmd); err != nil { 555 t.Fatal(err) 556 } 557 558 cmd = exec.Command(dockerBinary, "run", "--volumes-from", "parent:rw", "busybox", "touch", "/test/file") 559 if out, _, err := runCommandWithOutput(cmd); err != nil { 560 t.Fatalf("running --volumes-from parent:rw failed with output: %q\nerror: %v", out, err) 561 } 562 563 cmd = exec.Command(dockerBinary, "run", "--volumes-from", "parent:bar", "busybox", "touch", "/test/file") 564 if out, _, err := runCommandWithOutput(cmd); err == nil || !strings.Contains(out, "invalid mode for volumes-from: bar") { 565 t.Fatalf("running --volumes-from foo:bar should have failed with invalid mount mode: %q", out) 566 } 567 568 cmd = exec.Command(dockerBinary, "run", "--volumes-from", "parent", "busybox", "touch", "/test/file") 569 if out, _, err := runCommandWithOutput(cmd); err != nil { 570 t.Fatalf("running --volumes-from parent failed with output: %q\nerror: %v", out, err) 571 } 572 573 logDone("run - volumes from as read write mount") 574 } 575 576 func TestVolumesFromGetsProperMode(t *testing.T) { 577 defer deleteAllContainers() 578 cmd := exec.Command(dockerBinary, "run", "--name", "parent", "-v", "/test:/test:ro", "busybox", "true") 579 if _, err := runCommand(cmd); err != nil { 580 t.Fatal(err) 581 } 582 // Expect this "rw" mode to be be ignored since the inheritted volume is "ro" 583 cmd = exec.Command(dockerBinary, "run", "--volumes-from", "parent:rw", "busybox", "touch", "/test/file") 584 if _, err := runCommand(cmd); err == nil { 585 t.Fatal("Expected volumes-from to inherit read-only volume even when passing in `rw`") 586 } 587 588 cmd = exec.Command(dockerBinary, "run", "--name", "parent2", "-v", "/test:/test:ro", "busybox", "true") 589 if _, err := runCommand(cmd); err != nil { 590 t.Fatal(err) 591 } 592 // Expect this to be read-only since both are "ro" 593 cmd = exec.Command(dockerBinary, "run", "--volumes-from", "parent2:ro", "busybox", "touch", "/test/file") 594 if _, err := runCommand(cmd); err == nil { 595 t.Fatal("Expected volumes-from to inherit read-only volume even when passing in `ro`") 596 } 597 598 logDone("run - volumes from ignores `rw` if inherrited volume is `ro`") 599 } 600 601 // Test for GH#10618 602 func TestRunNoDupVolumes(t *testing.T) { 603 defer deleteAllContainers() 604 605 mountstr1 := randomUnixTmpDirPath("test1") + ":/someplace" 606 mountstr2 := randomUnixTmpDirPath("test2") + ":/someplace" 607 608 cmd := exec.Command(dockerBinary, "run", "-v", mountstr1, "-v", mountstr2, "busybox", "true") 609 if out, _, err := runCommandWithOutput(cmd); err == nil { 610 t.Fatal("Expected error about duplicate volume definitions") 611 } else { 612 if !strings.Contains(out, "Duplicate volume") { 613 t.Fatalf("Expected 'duplicate volume' error, got %v", err) 614 } 615 } 616 617 logDone("run - don't allow multiple (bind) volumes on the same container target") 618 } 619 620 // Test for #1351 621 func TestRunApplyVolumesFromBeforeVolumes(t *testing.T) { 622 defer deleteAllContainers() 623 624 cmd := exec.Command(dockerBinary, "run", "--name", "parent", "-v", "/test", "busybox", "touch", "/test/foo") 625 if _, err := runCommand(cmd); err != nil { 626 t.Fatal(err) 627 } 628 629 cmd = exec.Command(dockerBinary, "run", "--volumes-from", "parent", "-v", "/test", "busybox", "cat", "/test/foo") 630 if out, _, err := runCommandWithOutput(cmd); err != nil { 631 t.Fatal(out, err) 632 } 633 634 logDone("run - volumes from mounted first") 635 } 636 637 func TestRunMultipleVolumesFrom(t *testing.T) { 638 defer deleteAllContainers() 639 640 cmd := exec.Command(dockerBinary, "run", "--name", "parent1", "-v", "/test", "busybox", "touch", "/test/foo") 641 if _, err := runCommand(cmd); err != nil { 642 t.Fatal(err) 643 } 644 645 cmd = exec.Command(dockerBinary, "run", "--name", "parent2", "-v", "/other", "busybox", "touch", "/other/bar") 646 if _, err := runCommand(cmd); err != nil { 647 t.Fatal(err) 648 } 649 650 cmd = exec.Command(dockerBinary, "run", "--volumes-from", "parent1", "--volumes-from", "parent2", 651 "busybox", "sh", "-c", "cat /test/foo && cat /other/bar") 652 if _, err := runCommand(cmd); err != nil { 653 t.Fatal(err) 654 } 655 656 logDone("run - multiple volumes from") 657 } 658 659 // this tests verifies the ID format for the container 660 func TestRunVerifyContainerID(t *testing.T) { 661 defer deleteAllContainers() 662 663 cmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true") 664 out, exit, err := runCommandWithOutput(cmd) 665 if err != nil { 666 t.Fatal(err) 667 } 668 if exit != 0 { 669 t.Fatalf("expected exit code 0 received %d", exit) 670 } 671 match, err := regexp.MatchString("^[0-9a-f]{64}$", strings.TrimSuffix(out, "\n")) 672 if err != nil { 673 t.Fatal(err) 674 } 675 if !match { 676 t.Fatalf("Invalid container ID: %s", out) 677 } 678 679 logDone("run - verify container ID") 680 } 681 682 // Test that creating a container with a volume doesn't crash. Regression test for #995. 683 func TestRunCreateVolume(t *testing.T) { 684 defer deleteAllContainers() 685 686 cmd := exec.Command(dockerBinary, "run", "-v", "/var/lib/data", "busybox", "true") 687 if _, err := runCommand(cmd); err != nil { 688 t.Fatal(err) 689 } 690 691 logDone("run - create docker managed volume") 692 } 693 694 // Test that creating a volume with a symlink in its path works correctly. Test for #5152. 695 // Note that this bug happens only with symlinks with a target that starts with '/'. 696 func TestRunCreateVolumeWithSymlink(t *testing.T) { 697 defer deleteAllContainers() 698 699 image := "docker-test-createvolumewithsymlink" 700 defer deleteImages(image) 701 702 buildCmd := exec.Command(dockerBinary, "build", "-t", image, "-") 703 buildCmd.Stdin = strings.NewReader(`FROM busybox 704 RUN ln -s home /bar`) 705 buildCmd.Dir = workingDirectory 706 err := buildCmd.Run() 707 if err != nil { 708 t.Fatalf("could not build '%s': %v", image, err) 709 } 710 711 cmd := exec.Command(dockerBinary, "run", "-v", "/bar/foo", "--name", "test-createvolumewithsymlink", image, "sh", "-c", "mount | grep -q /home/foo") 712 exitCode, err := runCommand(cmd) 713 if err != nil || exitCode != 0 { 714 t.Fatalf("[run] err: %v, exitcode: %d", err, exitCode) 715 } 716 717 var volPath string 718 cmd = exec.Command(dockerBinary, "inspect", "-f", "{{range .Volumes}}{{.}}{{end}}", "test-createvolumewithsymlink") 719 volPath, exitCode, err = runCommandWithOutput(cmd) 720 if err != nil || exitCode != 0 { 721 t.Fatalf("[inspect] err: %v, exitcode: %d", err, exitCode) 722 } 723 724 cmd = exec.Command(dockerBinary, "rm", "-v", "test-createvolumewithsymlink") 725 exitCode, err = runCommand(cmd) 726 if err != nil || exitCode != 0 { 727 t.Fatalf("[rm] err: %v, exitcode: %d", err, exitCode) 728 } 729 730 f, err := os.Open(volPath) 731 defer f.Close() 732 if !os.IsNotExist(err) { 733 t.Fatalf("[open] (expecting 'file does not exist' error) err: %v, volPath: %s", err, volPath) 734 } 735 736 logDone("run - create volume with symlink") 737 } 738 739 // Tests that a volume path that has a symlink exists in a container mounting it with `--volumes-from`. 740 func TestRunVolumesFromSymlinkPath(t *testing.T) { 741 defer deleteAllContainers() 742 743 name := "docker-test-volumesfromsymlinkpath" 744 defer deleteImages(name) 745 746 buildCmd := exec.Command(dockerBinary, "build", "-t", name, "-") 747 buildCmd.Stdin = strings.NewReader(`FROM busybox 748 RUN ln -s home /foo 749 VOLUME ["/foo/bar"]`) 750 buildCmd.Dir = workingDirectory 751 err := buildCmd.Run() 752 if err != nil { 753 t.Fatalf("could not build 'docker-test-volumesfromsymlinkpath': %v", err) 754 } 755 756 cmd := exec.Command(dockerBinary, "run", "--name", "test-volumesfromsymlinkpath", name) 757 exitCode, err := runCommand(cmd) 758 if err != nil || exitCode != 0 { 759 t.Fatalf("[run] (volume) err: %v, exitcode: %d", err, exitCode) 760 } 761 762 cmd = exec.Command(dockerBinary, "run", "--volumes-from", "test-volumesfromsymlinkpath", "busybox", "sh", "-c", "ls /foo | grep -q bar") 763 exitCode, err = runCommand(cmd) 764 if err != nil || exitCode != 0 { 765 t.Fatalf("[run] err: %v, exitcode: %d", err, exitCode) 766 } 767 768 logDone("run - volumes-from symlink path") 769 } 770 771 func TestRunExitCode(t *testing.T) { 772 defer deleteAllContainers() 773 774 cmd := exec.Command(dockerBinary, "run", "busybox", "/bin/sh", "-c", "exit 72") 775 776 exit, err := runCommand(cmd) 777 if err == nil { 778 t.Fatal("should not have a non nil error") 779 } 780 if exit != 72 { 781 t.Fatalf("expected exit code 72 received %d", exit) 782 } 783 784 logDone("run - correct exit code") 785 } 786 787 func TestRunUserDefaultsToRoot(t *testing.T) { 788 defer deleteAllContainers() 789 790 cmd := exec.Command(dockerBinary, "run", "busybox", "id") 791 out, _, err := runCommandWithOutput(cmd) 792 if err != nil { 793 t.Fatal(err, out) 794 } 795 if !strings.Contains(out, "uid=0(root) gid=0(root)") { 796 t.Fatalf("expected root user got %s", out) 797 } 798 799 logDone("run - default user") 800 } 801 802 func TestRunUserByName(t *testing.T) { 803 defer deleteAllContainers() 804 805 cmd := exec.Command(dockerBinary, "run", "-u", "root", "busybox", "id") 806 out, _, err := runCommandWithOutput(cmd) 807 if err != nil { 808 t.Fatal(err, out) 809 } 810 if !strings.Contains(out, "uid=0(root) gid=0(root)") { 811 t.Fatalf("expected root user got %s", out) 812 } 813 814 logDone("run - user by name") 815 } 816 817 func TestRunUserByID(t *testing.T) { 818 defer deleteAllContainers() 819 820 cmd := exec.Command(dockerBinary, "run", "-u", "1", "busybox", "id") 821 out, _, err := runCommandWithOutput(cmd) 822 if err != nil { 823 t.Fatal(err, out) 824 } 825 if !strings.Contains(out, "uid=1(daemon) gid=1(daemon)") { 826 t.Fatalf("expected daemon user got %s", out) 827 } 828 829 logDone("run - user by id") 830 } 831 832 func TestRunUserByIDBig(t *testing.T) { 833 defer deleteAllContainers() 834 835 cmd := exec.Command(dockerBinary, "run", "-u", "2147483648", "busybox", "id") 836 out, _, err := runCommandWithOutput(cmd) 837 if err == nil { 838 t.Fatal("No error, but must be.", out) 839 } 840 if !strings.Contains(out, "Uids and gids must be in range") { 841 t.Fatalf("expected error about uids range, got %s", out) 842 } 843 844 logDone("run - user by id, id too big") 845 } 846 847 func TestRunUserByIDNegative(t *testing.T) { 848 defer deleteAllContainers() 849 850 cmd := exec.Command(dockerBinary, "run", "-u", "-1", "busybox", "id") 851 out, _, err := runCommandWithOutput(cmd) 852 if err == nil { 853 t.Fatal("No error, but must be.", out) 854 } 855 if !strings.Contains(out, "Uids and gids must be in range") { 856 t.Fatalf("expected error about uids range, got %s", out) 857 } 858 859 logDone("run - user by id, id negative") 860 } 861 862 func TestRunUserByIDZero(t *testing.T) { 863 defer deleteAllContainers() 864 865 cmd := exec.Command(dockerBinary, "run", "-u", "0", "busybox", "id") 866 out, _, err := runCommandWithOutput(cmd) 867 if err != nil { 868 t.Fatal(err, out) 869 } 870 if !strings.Contains(out, "uid=0(root) gid=0(root) groups=10(wheel)") { 871 t.Fatalf("expected daemon user got %s", out) 872 } 873 874 logDone("run - user by id, zero uid") 875 } 876 877 func TestRunUserNotFound(t *testing.T) { 878 defer deleteAllContainers() 879 880 cmd := exec.Command(dockerBinary, "run", "-u", "notme", "busybox", "id") 881 _, err := runCommand(cmd) 882 if err == nil { 883 t.Fatal("unknown user should cause container to fail") 884 } 885 886 logDone("run - user not found") 887 } 888 889 func TestRunTwoConcurrentContainers(t *testing.T) { 890 defer deleteAllContainers() 891 892 group := sync.WaitGroup{} 893 group.Add(2) 894 895 for i := 0; i < 2; i++ { 896 go func() { 897 defer group.Done() 898 cmd := exec.Command(dockerBinary, "run", "busybox", "sleep", "2") 899 if _, err := runCommand(cmd); err != nil { 900 t.Fatal(err) 901 } 902 }() 903 } 904 905 group.Wait() 906 907 logDone("run - two concurrent containers") 908 } 909 910 func TestRunEnvironment(t *testing.T) { 911 defer deleteAllContainers() 912 913 cmd := exec.Command(dockerBinary, "run", "-h", "testing", "-e=FALSE=true", "-e=TRUE", "-e=TRICKY", "-e=HOME=", "busybox", "env") 914 cmd.Env = append(os.Environ(), 915 "TRUE=false", 916 "TRICKY=tri\ncky\n", 917 ) 918 919 out, _, err := runCommandWithOutput(cmd) 920 if err != nil { 921 t.Fatal(err, out) 922 } 923 924 actualEnvLxc := strings.Split(strings.TrimSpace(out), "\n") 925 actualEnv := []string{} 926 for i := range actualEnvLxc { 927 if actualEnvLxc[i] != "container=lxc" { 928 actualEnv = append(actualEnv, actualEnvLxc[i]) 929 } 930 } 931 sort.Strings(actualEnv) 932 933 goodEnv := []string{ 934 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 935 "HOSTNAME=testing", 936 "FALSE=true", 937 "TRUE=false", 938 "TRICKY=tri", 939 "cky", 940 "", 941 "HOME=/root", 942 } 943 sort.Strings(goodEnv) 944 if len(goodEnv) != len(actualEnv) { 945 t.Fatalf("Wrong environment: should be %d variables, not: %q\n", len(goodEnv), strings.Join(actualEnv, ", ")) 946 } 947 for i := range goodEnv { 948 if actualEnv[i] != goodEnv[i] { 949 t.Fatalf("Wrong environment variable: should be %s, not %s", goodEnv[i], actualEnv[i]) 950 } 951 } 952 953 logDone("run - verify environment") 954 } 955 956 func TestRunEnvironmentErase(t *testing.T) { 957 // Test to make sure that when we use -e on env vars that are 958 // not set in our local env that they're removed (if present) in 959 // the container 960 defer deleteAllContainers() 961 962 cmd := exec.Command(dockerBinary, "run", "-e", "FOO", "-e", "HOSTNAME", "busybox", "env") 963 cmd.Env = appendBaseEnv([]string{}) 964 965 out, _, err := runCommandWithOutput(cmd) 966 if err != nil { 967 t.Fatal(err, out) 968 } 969 970 actualEnvLxc := strings.Split(strings.TrimSpace(out), "\n") 971 actualEnv := []string{} 972 for i := range actualEnvLxc { 973 if actualEnvLxc[i] != "container=lxc" { 974 actualEnv = append(actualEnv, actualEnvLxc[i]) 975 } 976 } 977 sort.Strings(actualEnv) 978 979 goodEnv := []string{ 980 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 981 "HOME=/root", 982 } 983 sort.Strings(goodEnv) 984 if len(goodEnv) != len(actualEnv) { 985 t.Fatalf("Wrong environment: should be %d variables, not: %q\n", len(goodEnv), strings.Join(actualEnv, ", ")) 986 } 987 for i := range goodEnv { 988 if actualEnv[i] != goodEnv[i] { 989 t.Fatalf("Wrong environment variable: should be %s, not %s", goodEnv[i], actualEnv[i]) 990 } 991 } 992 993 logDone("run - verify environment erase") 994 } 995 996 func TestRunEnvironmentOverride(t *testing.T) { 997 // Test to make sure that when we use -e on env vars that are 998 // already in the env that we're overriding them 999 defer deleteAllContainers() 1000 1001 cmd := exec.Command(dockerBinary, "run", "-e", "HOSTNAME", "-e", "HOME=/root2", "busybox", "env") 1002 cmd.Env = appendBaseEnv([]string{"HOSTNAME=bar"}) 1003 1004 out, _, err := runCommandWithOutput(cmd) 1005 if err != nil { 1006 t.Fatal(err, out) 1007 } 1008 1009 actualEnvLxc := strings.Split(strings.TrimSpace(out), "\n") 1010 actualEnv := []string{} 1011 for i := range actualEnvLxc { 1012 if actualEnvLxc[i] != "container=lxc" { 1013 actualEnv = append(actualEnv, actualEnvLxc[i]) 1014 } 1015 } 1016 sort.Strings(actualEnv) 1017 1018 goodEnv := []string{ 1019 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 1020 "HOME=/root2", 1021 "HOSTNAME=bar", 1022 } 1023 sort.Strings(goodEnv) 1024 if len(goodEnv) != len(actualEnv) { 1025 t.Fatalf("Wrong environment: should be %d variables, not: %q\n", len(goodEnv), strings.Join(actualEnv, ", ")) 1026 } 1027 for i := range goodEnv { 1028 if actualEnv[i] != goodEnv[i] { 1029 t.Fatalf("Wrong environment variable: should be %s, not %s", goodEnv[i], actualEnv[i]) 1030 } 1031 } 1032 1033 logDone("run - verify environment override") 1034 } 1035 1036 func TestRunContainerNetwork(t *testing.T) { 1037 defer deleteAllContainers() 1038 1039 cmd := exec.Command(dockerBinary, "run", "busybox", "ping", "-c", "1", "127.0.0.1") 1040 if _, err := runCommand(cmd); err != nil { 1041 t.Fatal(err) 1042 } 1043 1044 logDone("run - test container network via ping") 1045 } 1046 1047 // Issue #4681 1048 func TestRunLoopbackWhenNetworkDisabled(t *testing.T) { 1049 defer deleteAllContainers() 1050 1051 cmd := exec.Command(dockerBinary, "run", "--net=none", "busybox", "ping", "-c", "1", "127.0.0.1") 1052 if _, err := runCommand(cmd); err != nil { 1053 t.Fatal(err) 1054 } 1055 1056 logDone("run - test container loopback when networking disabled") 1057 } 1058 1059 func TestRunNetHostNotAllowedWithLinks(t *testing.T) { 1060 defer deleteAllContainers() 1061 1062 _, _, err := dockerCmd(t, "run", "--name", "linked", "busybox", "true") 1063 cmd := exec.Command(dockerBinary, "run", "--net=host", "--link", "linked:linked", "busybox", "true") 1064 _, _, err = runCommandWithOutput(cmd) 1065 if err == nil { 1066 t.Fatal("Expected error") 1067 } 1068 1069 logDone("run - don't allow --net=host to be used with links") 1070 } 1071 1072 func TestRunLoopbackOnlyExistsWhenNetworkingDisabled(t *testing.T) { 1073 defer deleteAllContainers() 1074 1075 cmd := exec.Command(dockerBinary, "run", "--net=none", "busybox", "ip", "-o", "-4", "a", "show", "up") 1076 out, _, err := runCommandWithOutput(cmd) 1077 if err != nil { 1078 t.Fatal(err, out) 1079 } 1080 1081 var ( 1082 count = 0 1083 parts = strings.Split(out, "\n") 1084 ) 1085 1086 for _, l := range parts { 1087 if l != "" { 1088 count++ 1089 } 1090 } 1091 1092 if count != 1 { 1093 t.Fatalf("Wrong interface count in container %d", count) 1094 } 1095 1096 if !strings.HasPrefix(out, "1: lo") { 1097 t.Fatalf("Wrong interface in test container: expected [1: lo], got %s", out) 1098 } 1099 1100 logDone("run - test loopback only exists when networking disabled") 1101 } 1102 1103 // #7851 hostname outside container shows FQDN, inside only shortname 1104 // For testing purposes it is not required to set host's hostname directly 1105 // and use "--net=host" (as the original issue submitter did), as the same 1106 // codepath is executed with "docker run -h <hostname>". Both were manually 1107 // tested, but this testcase takes the simpler path of using "run -h .." 1108 func TestRunFullHostnameSet(t *testing.T) { 1109 defer deleteAllContainers() 1110 1111 cmd := exec.Command(dockerBinary, "run", "-h", "foo.bar.baz", "busybox", "hostname") 1112 out, _, err := runCommandWithOutput(cmd) 1113 if err != nil { 1114 t.Fatal(err, out) 1115 } 1116 1117 if actual := strings.Trim(out, "\r\n"); actual != "foo.bar.baz" { 1118 t.Fatalf("expected hostname 'foo.bar.baz', received %s", actual) 1119 } 1120 1121 logDone("run - test fully qualified hostname set with -h") 1122 } 1123 1124 func TestRunPrivilegedCanMknod(t *testing.T) { 1125 defer deleteAllContainers() 1126 1127 cmd := exec.Command(dockerBinary, "run", "--privileged", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok") 1128 out, _, err := runCommandWithOutput(cmd) 1129 if err != nil { 1130 t.Fatal(err) 1131 } 1132 1133 if actual := strings.Trim(out, "\r\n"); actual != "ok" { 1134 t.Fatalf("expected output ok received %s", actual) 1135 } 1136 1137 logDone("run - test privileged can mknod") 1138 } 1139 1140 func TestRunUnPrivilegedCanMknod(t *testing.T) { 1141 defer deleteAllContainers() 1142 1143 cmd := exec.Command(dockerBinary, "run", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok") 1144 out, _, err := runCommandWithOutput(cmd) 1145 if err != nil { 1146 t.Fatal(err) 1147 } 1148 1149 if actual := strings.Trim(out, "\r\n"); actual != "ok" { 1150 t.Fatalf("expected output ok received %s", actual) 1151 } 1152 1153 logDone("run - test un-privileged can mknod") 1154 } 1155 1156 func TestRunCapDropInvalid(t *testing.T) { 1157 defer deleteAllContainers() 1158 cmd := exec.Command(dockerBinary, "run", "--cap-drop=CHPASS", "busybox", "ls") 1159 out, _, err := runCommandWithOutput(cmd) 1160 if err == nil { 1161 t.Fatal(err, out) 1162 } 1163 1164 logDone("run - test --cap-drop=CHPASS invalid") 1165 } 1166 1167 func TestRunCapDropCannotMknod(t *testing.T) { 1168 defer deleteAllContainers() 1169 1170 cmd := exec.Command(dockerBinary, "run", "--cap-drop=MKNOD", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok") 1171 out, _, err := runCommandWithOutput(cmd) 1172 if err == nil { 1173 t.Fatal(err, out) 1174 } 1175 1176 if actual := strings.Trim(out, "\r\n"); actual == "ok" { 1177 t.Fatalf("expected output not ok received %s", actual) 1178 } 1179 1180 logDone("run - test --cap-drop=MKNOD cannot mknod") 1181 } 1182 1183 func TestRunCapDropCannotMknodLowerCase(t *testing.T) { 1184 defer deleteAllContainers() 1185 1186 cmd := exec.Command(dockerBinary, "run", "--cap-drop=mknod", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok") 1187 out, _, err := runCommandWithOutput(cmd) 1188 if err == nil { 1189 t.Fatal(err, out) 1190 } 1191 1192 if actual := strings.Trim(out, "\r\n"); actual == "ok" { 1193 t.Fatalf("expected output not ok received %s", actual) 1194 } 1195 1196 logDone("run - test --cap-drop=mknod cannot mknod lowercase") 1197 } 1198 1199 func TestRunCapDropALLCannotMknod(t *testing.T) { 1200 defer deleteAllContainers() 1201 1202 cmd := exec.Command(dockerBinary, "run", "--cap-drop=ALL", "--cap-add=SETGID", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok") 1203 out, _, err := runCommandWithOutput(cmd) 1204 if err == nil { 1205 t.Fatal(err, out) 1206 } 1207 1208 if actual := strings.Trim(out, "\r\n"); actual == "ok" { 1209 t.Fatalf("expected output not ok received %s", actual) 1210 } 1211 1212 logDone("run - test --cap-drop=ALL cannot mknod") 1213 } 1214 1215 func TestRunCapDropALLAddMknodCanMknod(t *testing.T) { 1216 defer deleteAllContainers() 1217 1218 cmd := exec.Command(dockerBinary, "run", "--cap-drop=ALL", "--cap-add=MKNOD", "--cap-add=SETGID", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok") 1219 out, _, err := runCommandWithOutput(cmd) 1220 if err != nil { 1221 t.Fatal(err, out) 1222 } 1223 1224 if actual := strings.Trim(out, "\r\n"); actual != "ok" { 1225 t.Fatalf("expected output ok received %s", actual) 1226 } 1227 1228 logDone("run - test --cap-drop=ALL --cap-add=MKNOD can mknod") 1229 } 1230 1231 func TestRunCapAddInvalid(t *testing.T) { 1232 defer deleteAllContainers() 1233 1234 cmd := exec.Command(dockerBinary, "run", "--cap-add=CHPASS", "busybox", "ls") 1235 out, _, err := runCommandWithOutput(cmd) 1236 if err == nil { 1237 t.Fatal(err, out) 1238 } 1239 1240 logDone("run - test --cap-add=CHPASS invalid") 1241 } 1242 1243 func TestRunCapAddCanDownInterface(t *testing.T) { 1244 defer deleteAllContainers() 1245 1246 cmd := exec.Command(dockerBinary, "run", "--cap-add=NET_ADMIN", "busybox", "sh", "-c", "ip link set eth0 down && echo ok") 1247 out, _, err := runCommandWithOutput(cmd) 1248 if err != nil { 1249 t.Fatal(err, out) 1250 } 1251 1252 if actual := strings.Trim(out, "\r\n"); actual != "ok" { 1253 t.Fatalf("expected output ok received %s", actual) 1254 } 1255 1256 logDone("run - test --cap-add=NET_ADMIN can set eth0 down") 1257 } 1258 1259 func TestRunCapAddALLCanDownInterface(t *testing.T) { 1260 defer deleteAllContainers() 1261 1262 cmd := exec.Command(dockerBinary, "run", "--cap-add=ALL", "busybox", "sh", "-c", "ip link set eth0 down && echo ok") 1263 out, _, err := runCommandWithOutput(cmd) 1264 if err != nil { 1265 t.Fatal(err, out) 1266 } 1267 1268 if actual := strings.Trim(out, "\r\n"); actual != "ok" { 1269 t.Fatalf("expected output ok received %s", actual) 1270 } 1271 1272 logDone("run - test --cap-add=ALL can set eth0 down") 1273 } 1274 1275 func TestRunCapAddALLDropNetAdminCanDownInterface(t *testing.T) { 1276 defer deleteAllContainers() 1277 1278 cmd := exec.Command(dockerBinary, "run", "--cap-add=ALL", "--cap-drop=NET_ADMIN", "busybox", "sh", "-c", "ip link set eth0 down && echo ok") 1279 out, _, err := runCommandWithOutput(cmd) 1280 if err == nil { 1281 t.Fatal(err, out) 1282 } 1283 1284 if actual := strings.Trim(out, "\r\n"); actual == "ok" { 1285 t.Fatalf("expected output not ok received %s", actual) 1286 } 1287 1288 logDone("run - test --cap-add=ALL --cap-drop=NET_ADMIN cannot set eth0 down") 1289 } 1290 1291 func TestRunPrivilegedCanMount(t *testing.T) { 1292 defer deleteAllContainers() 1293 1294 cmd := exec.Command(dockerBinary, "run", "--privileged", "busybox", "sh", "-c", "mount -t tmpfs none /tmp && echo ok") 1295 out, _, err := runCommandWithOutput(cmd) 1296 if err != nil { 1297 t.Fatal(err) 1298 } 1299 1300 if actual := strings.Trim(out, "\r\n"); actual != "ok" { 1301 t.Fatalf("expected output ok received %s", actual) 1302 } 1303 1304 logDone("run - test privileged can mount") 1305 } 1306 1307 func TestRunUnPrivilegedCannotMount(t *testing.T) { 1308 defer deleteAllContainers() 1309 1310 cmd := exec.Command(dockerBinary, "run", "busybox", "sh", "-c", "mount -t tmpfs none /tmp && echo ok") 1311 out, _, err := runCommandWithOutput(cmd) 1312 if err == nil { 1313 t.Fatal(err, out) 1314 } 1315 1316 if actual := strings.Trim(out, "\r\n"); actual == "ok" { 1317 t.Fatalf("expected output not ok received %s", actual) 1318 } 1319 1320 logDone("run - test un-privileged cannot mount") 1321 } 1322 1323 func TestRunSysNotWritableInNonPrivilegedContainers(t *testing.T) { 1324 defer deleteAllContainers() 1325 1326 cmd := exec.Command(dockerBinary, "run", "busybox", "touch", "/sys/kernel/profiling") 1327 if code, err := runCommand(cmd); err == nil || code == 0 { 1328 t.Fatal("sys should not be writable in a non privileged container") 1329 } 1330 1331 logDone("run - sys not writable in non privileged container") 1332 } 1333 1334 func TestRunSysWritableInPrivilegedContainers(t *testing.T) { 1335 defer deleteAllContainers() 1336 1337 cmd := exec.Command(dockerBinary, "run", "--privileged", "busybox", "touch", "/sys/kernel/profiling") 1338 if code, err := runCommand(cmd); err != nil || code != 0 { 1339 t.Fatalf("sys should be writable in privileged container") 1340 } 1341 1342 logDone("run - sys writable in privileged container") 1343 } 1344 1345 func TestRunProcNotWritableInNonPrivilegedContainers(t *testing.T) { 1346 defer deleteAllContainers() 1347 1348 cmd := exec.Command(dockerBinary, "run", "busybox", "touch", "/proc/sysrq-trigger") 1349 if code, err := runCommand(cmd); err == nil || code == 0 { 1350 t.Fatal("proc should not be writable in a non privileged container") 1351 } 1352 1353 logDone("run - proc not writable in non privileged container") 1354 } 1355 1356 func TestRunProcWritableInPrivilegedContainers(t *testing.T) { 1357 defer deleteAllContainers() 1358 1359 cmd := exec.Command(dockerBinary, "run", "--privileged", "busybox", "touch", "/proc/sysrq-trigger") 1360 if code, err := runCommand(cmd); err != nil || code != 0 { 1361 t.Fatalf("proc should be writable in privileged container") 1362 } 1363 logDone("run - proc writable in privileged container") 1364 } 1365 1366 func TestRunWithCpuset(t *testing.T) { 1367 defer deleteAllContainers() 1368 1369 cmd := exec.Command(dockerBinary, "run", "--cpuset", "0", "busybox", "true") 1370 if code, err := runCommand(cmd); err != nil || code != 0 { 1371 t.Fatalf("container should run successfuly with cpuset of 0: %s", err) 1372 } 1373 1374 logDone("run - cpuset 0") 1375 } 1376 1377 func TestRunWithCpusetCpus(t *testing.T) { 1378 defer deleteAllContainers() 1379 1380 cmd := exec.Command(dockerBinary, "run", "--cpuset-cpus", "0", "busybox", "true") 1381 if code, err := runCommand(cmd); err != nil || code != 0 { 1382 t.Fatalf("container should run successfuly with cpuset-cpus of 0: %s", err) 1383 } 1384 1385 logDone("run - cpuset-cpus 0") 1386 } 1387 1388 func TestRunDeviceNumbers(t *testing.T) { 1389 defer deleteAllContainers() 1390 1391 cmd := exec.Command(dockerBinary, "run", "busybox", "sh", "-c", "ls -l /dev/null") 1392 out, _, err := runCommandWithOutput(cmd) 1393 if err != nil { 1394 t.Fatal(err, out) 1395 } 1396 deviceLineFields := strings.Fields(out) 1397 deviceLineFields[6] = "" 1398 deviceLineFields[7] = "" 1399 deviceLineFields[8] = "" 1400 expected := []string{"crw-rw-rw-", "1", "root", "root", "1,", "3", "", "", "", "/dev/null"} 1401 1402 if !(reflect.DeepEqual(deviceLineFields, expected)) { 1403 t.Fatalf("expected output\ncrw-rw-rw- 1 root root 1, 3 May 24 13:29 /dev/null\n received\n %s\n", out) 1404 } 1405 1406 logDone("run - test device numbers") 1407 } 1408 1409 func TestRunThatCharacterDevicesActLikeCharacterDevices(t *testing.T) { 1410 defer deleteAllContainers() 1411 1412 cmd := exec.Command(dockerBinary, "run", "busybox", "sh", "-c", "dd if=/dev/zero of=/zero bs=1k count=5 2> /dev/null ; du -h /zero") 1413 out, _, err := runCommandWithOutput(cmd) 1414 if err != nil { 1415 t.Fatal(err, out) 1416 } 1417 1418 if actual := strings.Trim(out, "\r\n"); actual[0] == '0' { 1419 t.Fatalf("expected a new file called /zero to be create that is greater than 0 bytes long, but du says: %s", actual) 1420 } 1421 1422 logDone("run - test that character devices work.") 1423 } 1424 1425 func TestRunUnprivilegedWithChroot(t *testing.T) { 1426 defer deleteAllContainers() 1427 1428 cmd := exec.Command(dockerBinary, "run", "busybox", "chroot", "/", "true") 1429 if _, err := runCommand(cmd); err != nil { 1430 t.Fatal(err) 1431 } 1432 1433 logDone("run - unprivileged with chroot") 1434 } 1435 1436 func TestRunAddingOptionalDevices(t *testing.T) { 1437 defer deleteAllContainers() 1438 1439 cmd := exec.Command(dockerBinary, "run", "--device", "/dev/zero:/dev/nulo", "busybox", "sh", "-c", "ls /dev/nulo") 1440 out, _, err := runCommandWithOutput(cmd) 1441 if err != nil { 1442 t.Fatal(err, out) 1443 } 1444 1445 if actual := strings.Trim(out, "\r\n"); actual != "/dev/nulo" { 1446 t.Fatalf("expected output /dev/nulo, received %s", actual) 1447 } 1448 1449 logDone("run - test --device argument") 1450 } 1451 1452 func TestRunModeHostname(t *testing.T) { 1453 testRequires(t, SameHostDaemon) 1454 defer deleteAllContainers() 1455 1456 cmd := exec.Command(dockerBinary, "run", "-h=testhostname", "busybox", "cat", "/etc/hostname") 1457 out, _, err := runCommandWithOutput(cmd) 1458 if err != nil { 1459 t.Fatal(err, out) 1460 } 1461 1462 if actual := strings.Trim(out, "\r\n"); actual != "testhostname" { 1463 t.Fatalf("expected 'testhostname', but says: %q", actual) 1464 } 1465 1466 cmd = exec.Command(dockerBinary, "run", "--net=host", "busybox", "cat", "/etc/hostname") 1467 1468 out, _, err = runCommandWithOutput(cmd) 1469 if err != nil { 1470 t.Fatal(err, out) 1471 } 1472 hostname, err := os.Hostname() 1473 if err != nil { 1474 t.Fatal(err) 1475 } 1476 if actual := strings.Trim(out, "\r\n"); actual != hostname { 1477 t.Fatalf("expected %q, but says: %q", hostname, actual) 1478 } 1479 1480 logDone("run - hostname and several network modes") 1481 } 1482 1483 func TestRunRootWorkdir(t *testing.T) { 1484 defer deleteAllContainers() 1485 1486 s, _, err := dockerCmd(t, "run", "--workdir", "/", "busybox", "pwd") 1487 if err != nil { 1488 t.Fatal(s, err) 1489 } 1490 if s != "/\n" { 1491 t.Fatalf("pwd returned %q (expected /\\n)", s) 1492 } 1493 1494 logDone("run - workdir /") 1495 } 1496 1497 func TestRunAllowBindMountingRoot(t *testing.T) { 1498 defer deleteAllContainers() 1499 1500 s, _, err := dockerCmd(t, "run", "-v", "/:/host", "busybox", "ls", "/host") 1501 if err != nil { 1502 t.Fatal(s, err) 1503 } 1504 1505 logDone("run - bind mount / as volume") 1506 } 1507 1508 func TestRunDisallowBindMountingRootToRoot(t *testing.T) { 1509 defer deleteAllContainers() 1510 1511 cmd := exec.Command(dockerBinary, "run", "-v", "/:/", "busybox", "ls", "/host") 1512 out, _, err := runCommandWithOutput(cmd) 1513 if err == nil { 1514 t.Fatal(out, err) 1515 } 1516 1517 logDone("run - bind mount /:/ as volume should not work") 1518 } 1519 1520 // Verify that a container gets default DNS when only localhost resolvers exist 1521 func TestRunDnsDefaultOptions(t *testing.T) { 1522 defer deleteAllContainers() 1523 testRequires(t, SameHostDaemon) 1524 1525 // preserve original resolv.conf for restoring after test 1526 origResolvConf, err := ioutil.ReadFile("/etc/resolv.conf") 1527 if os.IsNotExist(err) { 1528 t.Fatalf("/etc/resolv.conf does not exist") 1529 } 1530 // defer restored original conf 1531 defer func() { 1532 if err := ioutil.WriteFile("/etc/resolv.conf", origResolvConf, 0644); err != nil { 1533 t.Fatal(err) 1534 } 1535 }() 1536 1537 // test 3 cases: standard IPv4 localhost, commented out localhost, and IPv6 localhost 1538 // 2 are removed from the file at container start, and the 3rd (commented out) one is ignored by 1539 // GetNameservers(), leading to a replacement of nameservers with the default set 1540 tmpResolvConf := []byte("nameserver 127.0.0.1\n#nameserver 127.0.2.1\nnameserver ::1") 1541 if err := ioutil.WriteFile("/etc/resolv.conf", tmpResolvConf, 0644); err != nil { 1542 t.Fatal(err) 1543 } 1544 1545 cmd := exec.Command(dockerBinary, "run", "busybox", "cat", "/etc/resolv.conf") 1546 1547 actual, _, err := runCommandWithOutput(cmd) 1548 if err != nil { 1549 t.Fatal(err, actual) 1550 } 1551 1552 // check that the actual defaults are appended to the commented out 1553 // localhost resolver (which should be preserved) 1554 // NOTE: if we ever change the defaults from google dns, this will break 1555 expected := "#nameserver 127.0.2.1\n\nnameserver 8.8.8.8\nnameserver 8.8.4.4" 1556 if actual != expected { 1557 t.Fatalf("expected resolv.conf be: %q, but was: %q", expected, actual) 1558 } 1559 1560 logDone("run - dns default options") 1561 } 1562 1563 func TestRunDnsOptions(t *testing.T) { 1564 defer deleteAllContainers() 1565 1566 cmd := exec.Command(dockerBinary, "run", "--dns=127.0.0.1", "--dns-search=mydomain", "busybox", "cat", "/etc/resolv.conf") 1567 1568 out, stderr, _, err := runCommandWithStdoutStderr(cmd) 1569 if err != nil { 1570 t.Fatal(err, out) 1571 } 1572 1573 // The client will get a warning on stderr when setting DNS to a localhost address; verify this: 1574 if !strings.Contains(stderr, "Localhost DNS setting") { 1575 t.Fatalf("Expected warning on stderr about localhost resolver, but got %q", stderr) 1576 } 1577 1578 actual := strings.Replace(strings.Trim(out, "\r\n"), "\n", " ", -1) 1579 if actual != "nameserver 127.0.0.1 search mydomain" { 1580 t.Fatalf("expected 'nameserver 127.0.0.1 search mydomain', but says: %q", actual) 1581 } 1582 1583 cmd = exec.Command(dockerBinary, "run", "--dns=127.0.0.1", "--dns-search=.", "busybox", "cat", "/etc/resolv.conf") 1584 1585 out, _, _, err = runCommandWithStdoutStderr(cmd) 1586 if err != nil { 1587 t.Fatal(err, out) 1588 } 1589 1590 actual = strings.Replace(strings.Trim(strings.Trim(out, "\r\n"), " "), "\n", " ", -1) 1591 if actual != "nameserver 127.0.0.1" { 1592 t.Fatalf("expected 'nameserver 127.0.0.1', but says: %q", actual) 1593 } 1594 1595 logDone("run - dns options") 1596 } 1597 1598 func TestRunDnsOptionsBasedOnHostResolvConf(t *testing.T) { 1599 defer deleteAllContainers() 1600 testRequires(t, SameHostDaemon) 1601 1602 origResolvConf, err := ioutil.ReadFile("/etc/resolv.conf") 1603 if os.IsNotExist(err) { 1604 t.Fatalf("/etc/resolv.conf does not exist") 1605 } 1606 1607 hostNamservers := resolvconf.GetNameservers(origResolvConf) 1608 hostSearch := resolvconf.GetSearchDomains(origResolvConf) 1609 1610 var out string 1611 cmd := exec.Command(dockerBinary, "run", "--dns=127.0.0.1", "busybox", "cat", "/etc/resolv.conf") 1612 if out, _, _, err = runCommandWithStdoutStderr(cmd); err != nil { 1613 t.Fatal(err, out) 1614 } 1615 1616 if actualNameservers := resolvconf.GetNameservers([]byte(out)); string(actualNameservers[0]) != "127.0.0.1" { 1617 t.Fatalf("expected '127.0.0.1', but says: %q", string(actualNameservers[0])) 1618 } 1619 1620 actualSearch := resolvconf.GetSearchDomains([]byte(out)) 1621 if len(actualSearch) != len(hostSearch) { 1622 t.Fatalf("expected %q search domain(s), but it has: %q", len(hostSearch), len(actualSearch)) 1623 } 1624 for i := range actualSearch { 1625 if actualSearch[i] != hostSearch[i] { 1626 t.Fatalf("expected %q domain, but says: %q", actualSearch[i], hostSearch[i]) 1627 } 1628 } 1629 1630 cmd = exec.Command(dockerBinary, "run", "--dns-search=mydomain", "busybox", "cat", "/etc/resolv.conf") 1631 1632 if out, _, err = runCommandWithOutput(cmd); err != nil { 1633 t.Fatal(err, out) 1634 } 1635 1636 actualNameservers := resolvconf.GetNameservers([]byte(out)) 1637 if len(actualNameservers) != len(hostNamservers) { 1638 t.Fatalf("expected %q nameserver(s), but it has: %q", len(hostNamservers), len(actualNameservers)) 1639 } 1640 for i := range actualNameservers { 1641 if actualNameservers[i] != hostNamservers[i] { 1642 t.Fatalf("expected %q nameserver, but says: %q", actualNameservers[i], hostNamservers[i]) 1643 } 1644 } 1645 1646 if actualSearch = resolvconf.GetSearchDomains([]byte(out)); string(actualSearch[0]) != "mydomain" { 1647 t.Fatalf("expected 'mydomain', but says: %q", string(actualSearch[0])) 1648 } 1649 1650 // test with file 1651 tmpResolvConf := []byte("search example.com\nnameserver 12.34.56.78\nnameserver 127.0.0.1") 1652 if err := ioutil.WriteFile("/etc/resolv.conf", tmpResolvConf, 0644); err != nil { 1653 t.Fatal(err) 1654 } 1655 // put the old resolvconf back 1656 defer func() { 1657 if err := ioutil.WriteFile("/etc/resolv.conf", origResolvConf, 0644); err != nil { 1658 t.Fatal(err) 1659 } 1660 }() 1661 1662 resolvConf, err := ioutil.ReadFile("/etc/resolv.conf") 1663 if os.IsNotExist(err) { 1664 t.Fatalf("/etc/resolv.conf does not exist") 1665 } 1666 1667 hostNamservers = resolvconf.GetNameservers(resolvConf) 1668 hostSearch = resolvconf.GetSearchDomains(resolvConf) 1669 1670 cmd = exec.Command(dockerBinary, "run", "busybox", "cat", "/etc/resolv.conf") 1671 1672 if out, _, err = runCommandWithOutput(cmd); err != nil { 1673 t.Fatal(err, out) 1674 } 1675 1676 if actualNameservers = resolvconf.GetNameservers([]byte(out)); string(actualNameservers[0]) != "12.34.56.78" || len(actualNameservers) != 1 { 1677 t.Fatalf("expected '12.34.56.78', but has: %v", actualNameservers) 1678 } 1679 1680 actualSearch = resolvconf.GetSearchDomains([]byte(out)) 1681 if len(actualSearch) != len(hostSearch) { 1682 t.Fatalf("expected %q search domain(s), but it has: %q", len(hostSearch), len(actualSearch)) 1683 } 1684 for i := range actualSearch { 1685 if actualSearch[i] != hostSearch[i] { 1686 t.Fatalf("expected %q domain, but says: %q", actualSearch[i], hostSearch[i]) 1687 } 1688 } 1689 defer deleteAllContainers() 1690 1691 logDone("run - dns options based on host resolv.conf") 1692 } 1693 1694 // Test the file watch notifier on docker host's /etc/resolv.conf 1695 // A go-routine is responsible for auto-updating containers which are 1696 // stopped and have an unmodified copy of resolv.conf, as well as 1697 // marking running containers as requiring an update on next restart 1698 func TestRunResolvconfUpdater(t *testing.T) { 1699 // Because overlay doesn't support inotify properly, we need to skip 1700 // this test if the docker daemon has Storage Driver == overlay 1701 testRequires(t, SameHostDaemon, NotOverlay) 1702 1703 tmpResolvConf := []byte("search pommesfrites.fr\nnameserver 12.34.56.78") 1704 tmpLocalhostResolvConf := []byte("nameserver 127.0.0.1") 1705 1706 //take a copy of resolv.conf for restoring after test completes 1707 resolvConfSystem, err := ioutil.ReadFile("/etc/resolv.conf") 1708 if err != nil { 1709 t.Fatal(err) 1710 } 1711 1712 // This test case is meant to test monitoring resolv.conf when it is 1713 // a regular file not a bind mount. So we unmount resolv.conf and replace 1714 // it with a file containing the original settings. 1715 cmd := exec.Command("umount", "/etc/resolv.conf") 1716 if _, err = runCommand(cmd); err != nil { 1717 t.Fatal(err) 1718 } 1719 1720 //cleanup 1721 defer func() { 1722 deleteAllContainers() 1723 if err := ioutil.WriteFile("/etc/resolv.conf", resolvConfSystem, 0644); err != nil { 1724 t.Fatal(err) 1725 } 1726 }() 1727 1728 //1. test that a non-running container gets an updated resolv.conf 1729 cmd = exec.Command(dockerBinary, "run", "--name='first'", "busybox", "true") 1730 if _, err := runCommand(cmd); err != nil { 1731 t.Fatal(err) 1732 } 1733 containerID1, err := getIDByName("first") 1734 if err != nil { 1735 t.Fatal(err) 1736 } 1737 1738 // replace resolv.conf with our temporary copy 1739 bytesResolvConf := []byte(tmpResolvConf) 1740 if err := ioutil.WriteFile("/etc/resolv.conf", bytesResolvConf, 0644); err != nil { 1741 t.Fatal(err) 1742 } 1743 1744 time.Sleep(time.Second / 2) 1745 // check for update in container 1746 containerResolv, err := readContainerFile(containerID1, "resolv.conf") 1747 if err != nil { 1748 t.Fatal(err) 1749 } 1750 if !bytes.Equal(containerResolv, bytesResolvConf) { 1751 t.Fatalf("Stopped container does not have updated resolv.conf; expected %q, got %q", tmpResolvConf, string(containerResolv)) 1752 } 1753 1754 //2. test that a non-running container does not receive resolv.conf updates 1755 // if it modified the container copy of the starting point resolv.conf 1756 cmd = exec.Command(dockerBinary, "run", "--name='second'", "busybox", "sh", "-c", "echo 'search mylittlepony.com' >>/etc/resolv.conf") 1757 if _, err = runCommand(cmd); err != nil { 1758 t.Fatal(err) 1759 } 1760 containerID2, err := getIDByName("second") 1761 if err != nil { 1762 t.Fatal(err) 1763 } 1764 containerResolvHashBefore, err := readContainerFile(containerID2, "resolv.conf.hash") 1765 if err != nil { 1766 t.Fatal(err) 1767 } 1768 1769 //make a change to resolv.conf (in this case replacing our tmp copy with orig copy) 1770 if err := ioutil.WriteFile("/etc/resolv.conf", resolvConfSystem, 0644); err != nil { 1771 t.Fatal(err) 1772 } 1773 1774 time.Sleep(time.Second / 2) 1775 containerResolvHashAfter, err := readContainerFile(containerID2, "resolv.conf.hash") 1776 if err != nil { 1777 t.Fatal(err) 1778 } 1779 1780 if !bytes.Equal(containerResolvHashBefore, containerResolvHashAfter) { 1781 t.Fatalf("Stopped container with modified resolv.conf should not have been updated; expected hash: %v, new hash: %v", containerResolvHashBefore, containerResolvHashAfter) 1782 } 1783 1784 //3. test that a running container's resolv.conf is not modified while running 1785 cmd = exec.Command(dockerBinary, "run", "-d", "busybox", "top") 1786 out, _, err := runCommandWithOutput(cmd) 1787 if err != nil { 1788 t.Fatal(err) 1789 } 1790 runningContainerID := strings.TrimSpace(out) 1791 1792 containerResolvHashBefore, err = readContainerFile(runningContainerID, "resolv.conf.hash") 1793 if err != nil { 1794 t.Fatal(err) 1795 } 1796 1797 // replace resolv.conf 1798 if err := ioutil.WriteFile("/etc/resolv.conf", bytesResolvConf, 0644); err != nil { 1799 t.Fatal(err) 1800 } 1801 1802 // make sure the updater has time to run to validate we really aren't 1803 // getting updated 1804 time.Sleep(time.Second / 2) 1805 containerResolvHashAfter, err = readContainerFile(runningContainerID, "resolv.conf.hash") 1806 if err != nil { 1807 t.Fatal(err) 1808 } 1809 1810 if !bytes.Equal(containerResolvHashBefore, containerResolvHashAfter) { 1811 t.Fatalf("Running container's resolv.conf should not be updated; expected hash: %v, new hash: %v", containerResolvHashBefore, containerResolvHashAfter) 1812 } 1813 1814 //4. test that a running container's resolv.conf is updated upon restart 1815 // (the above container is still running..) 1816 cmd = exec.Command(dockerBinary, "restart", runningContainerID) 1817 if _, err = runCommand(cmd); err != nil { 1818 t.Fatal(err) 1819 } 1820 1821 // check for update in container 1822 containerResolv, err = readContainerFile(runningContainerID, "resolv.conf") 1823 if err != nil { 1824 t.Fatal(err) 1825 } 1826 if !bytes.Equal(containerResolv, bytesResolvConf) { 1827 t.Fatalf("Restarted container should have updated resolv.conf; expected %q, got %q", tmpResolvConf, string(containerResolv)) 1828 } 1829 1830 //5. test that additions of a localhost resolver are cleaned from 1831 // host resolv.conf before updating container's resolv.conf copies 1832 1833 // replace resolv.conf with a localhost-only nameserver copy 1834 bytesResolvConf = []byte(tmpLocalhostResolvConf) 1835 if err = ioutil.WriteFile("/etc/resolv.conf", bytesResolvConf, 0644); err != nil { 1836 t.Fatal(err) 1837 } 1838 1839 time.Sleep(time.Second / 2) 1840 // our first exited container ID should have been updated, but with default DNS 1841 // after the cleanup of resolv.conf found only a localhost nameserver: 1842 containerResolv, err = readContainerFile(containerID1, "resolv.conf") 1843 if err != nil { 1844 t.Fatal(err) 1845 } 1846 1847 expected := "\nnameserver 8.8.8.8\nnameserver 8.8.4.4" 1848 if !bytes.Equal(containerResolv, []byte(expected)) { 1849 t.Fatalf("Container does not have cleaned/replaced DNS in resolv.conf; expected %q, got %q", expected, string(containerResolv)) 1850 } 1851 1852 //6. Test that replacing (as opposed to modifying) resolv.conf triggers an update 1853 // of containers' resolv.conf. 1854 1855 // Restore the original resolv.conf 1856 if err := ioutil.WriteFile("/etc/resolv.conf", resolvConfSystem, 0644); err != nil { 1857 t.Fatal(err) 1858 } 1859 1860 // Run the container so it picks up the old settings 1861 cmd = exec.Command(dockerBinary, "run", "--name='third'", "busybox", "true") 1862 if _, err := runCommand(cmd); err != nil { 1863 t.Fatal(err) 1864 } 1865 containerID3, err := getIDByName("third") 1866 if err != nil { 1867 t.Fatal(err) 1868 } 1869 1870 // Create a modified resolv.conf.aside and override resolv.conf with it 1871 bytesResolvConf = []byte(tmpResolvConf) 1872 if err := ioutil.WriteFile("/etc/resolv.conf.aside", bytesResolvConf, 0644); err != nil { 1873 t.Fatal(err) 1874 } 1875 1876 err = os.Rename("/etc/resolv.conf.aside", "/etc/resolv.conf") 1877 if err != nil { 1878 t.Fatal(err) 1879 } 1880 1881 time.Sleep(time.Second / 2) 1882 // check for update in container 1883 containerResolv, err = readContainerFile(containerID3, "resolv.conf") 1884 if err != nil { 1885 t.Fatal(err) 1886 } 1887 if !bytes.Equal(containerResolv, bytesResolvConf) { 1888 t.Fatalf("Stopped container does not have updated resolv.conf; expected\n%q\n got\n%q", tmpResolvConf, string(containerResolv)) 1889 } 1890 1891 //cleanup, restore original resolv.conf happens in defer func() 1892 logDone("run - resolv.conf updater") 1893 } 1894 1895 func TestRunAddHost(t *testing.T) { 1896 defer deleteAllContainers() 1897 cmd := exec.Command(dockerBinary, "run", "--add-host=extra:86.75.30.9", "busybox", "grep", "extra", "/etc/hosts") 1898 1899 out, _, err := runCommandWithOutput(cmd) 1900 if err != nil { 1901 t.Fatal(err, out) 1902 } 1903 1904 actual := strings.Trim(out, "\r\n") 1905 if actual != "86.75.30.9\textra" { 1906 t.Fatalf("expected '86.75.30.9\textra', but says: %q", actual) 1907 } 1908 1909 logDone("run - add-host option") 1910 } 1911 1912 // Regression test for #6983 1913 func TestRunAttachStdErrOnlyTTYMode(t *testing.T) { 1914 defer deleteAllContainers() 1915 1916 cmd := exec.Command(dockerBinary, "run", "-t", "-a", "stderr", "busybox", "true") 1917 exitCode, err := runCommand(cmd) 1918 if err != nil { 1919 t.Fatal(err) 1920 } else if exitCode != 0 { 1921 t.Fatalf("Container should have exited with error code 0") 1922 } 1923 1924 logDone("run - Attach stderr only with -t") 1925 } 1926 1927 // Regression test for #6983 1928 func TestRunAttachStdOutOnlyTTYMode(t *testing.T) { 1929 defer deleteAllContainers() 1930 1931 cmd := exec.Command(dockerBinary, "run", "-t", "-a", "stdout", "busybox", "true") 1932 1933 exitCode, err := runCommand(cmd) 1934 if err != nil { 1935 t.Fatal(err) 1936 } else if exitCode != 0 { 1937 t.Fatalf("Container should have exited with error code 0") 1938 } 1939 1940 logDone("run - Attach stdout only with -t") 1941 } 1942 1943 // Regression test for #6983 1944 func TestRunAttachStdOutAndErrTTYMode(t *testing.T) { 1945 defer deleteAllContainers() 1946 1947 cmd := exec.Command(dockerBinary, "run", "-t", "-a", "stdout", "-a", "stderr", "busybox", "true") 1948 exitCode, err := runCommand(cmd) 1949 if err != nil { 1950 t.Fatal(err) 1951 } else if exitCode != 0 { 1952 t.Fatalf("Container should have exited with error code 0") 1953 } 1954 1955 logDone("run - Attach stderr and stdout with -t") 1956 } 1957 1958 // Test for #10388 - this will run the same test as TestRunAttachStdOutAndErrTTYMode 1959 // but using --attach instead of -a to make sure we read the flag correctly 1960 func TestRunAttachWithDettach(t *testing.T) { 1961 defer deleteAllContainers() 1962 1963 cmd := exec.Command(dockerBinary, "run", "-d", "--attach", "stdout", "busybox", "true") 1964 _, stderr, _, err := runCommandWithStdoutStderr(cmd) 1965 if err == nil { 1966 t.Fatalf("Container should have exited with error code different than 0", err) 1967 } else if !strings.Contains(stderr, "Conflicting options: -a and -d") { 1968 t.Fatalf("Should have been returned an error with conflicting options -a and -d") 1969 } 1970 1971 logDone("run - Attach stdout with -d") 1972 } 1973 1974 func TestRunState(t *testing.T) { 1975 defer deleteAllContainers() 1976 cmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top") 1977 1978 out, _, err := runCommandWithOutput(cmd) 1979 if err != nil { 1980 t.Fatal(err, out) 1981 } 1982 id := strings.TrimSpace(out) 1983 state, err := inspectField(id, "State.Running") 1984 if err != nil { 1985 t.Fatal(err) 1986 } 1987 if state != "true" { 1988 t.Fatal("Container state is 'not running'") 1989 } 1990 pid1, err := inspectField(id, "State.Pid") 1991 if err != nil { 1992 t.Fatal(err) 1993 } 1994 if pid1 == "0" { 1995 t.Fatal("Container state Pid 0") 1996 } 1997 1998 cmd = exec.Command(dockerBinary, "stop", id) 1999 out, _, err = runCommandWithOutput(cmd) 2000 if err != nil { 2001 t.Fatal(err, out) 2002 } 2003 state, err = inspectField(id, "State.Running") 2004 if err != nil { 2005 t.Fatal(err) 2006 } 2007 if state != "false" { 2008 t.Fatal("Container state is 'running'") 2009 } 2010 pid2, err := inspectField(id, "State.Pid") 2011 if err != nil { 2012 t.Fatal(err) 2013 } 2014 if pid2 == pid1 { 2015 t.Fatalf("Container state Pid %s, but expected %s", pid2, pid1) 2016 } 2017 2018 cmd = exec.Command(dockerBinary, "start", id) 2019 out, _, err = runCommandWithOutput(cmd) 2020 if err != nil { 2021 t.Fatal(err, out) 2022 } 2023 state, err = inspectField(id, "State.Running") 2024 if err != nil { 2025 t.Fatal(err) 2026 } 2027 if state != "true" { 2028 t.Fatal("Container state is 'not running'") 2029 } 2030 pid3, err := inspectField(id, "State.Pid") 2031 if err != nil { 2032 t.Fatal(err) 2033 } 2034 if pid3 == pid1 { 2035 t.Fatalf("Container state Pid %s, but expected %s", pid2, pid1) 2036 } 2037 logDone("run - test container state.") 2038 } 2039 2040 // Test for #1737 2041 func TestRunCopyVolumeUidGid(t *testing.T) { 2042 name := "testrunvolumesuidgid" 2043 defer deleteImages(name) 2044 defer deleteAllContainers() 2045 _, err := buildImage(name, 2046 `FROM busybox 2047 RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd 2048 RUN echo 'dockerio:x:1001:' >> /etc/group 2049 RUN mkdir -p /hello && touch /hello/test && chown dockerio.dockerio /hello`, 2050 true) 2051 if err != nil { 2052 t.Fatal(err) 2053 } 2054 2055 // Test that the uid and gid is copied from the image to the volume 2056 cmd := exec.Command(dockerBinary, "run", "--rm", "-v", "/hello", name, "sh", "-c", "ls -l / | grep hello | awk '{print $3\":\"$4}'") 2057 out, _, err := runCommandWithOutput(cmd) 2058 if err != nil { 2059 t.Fatal(err, out) 2060 } 2061 out = strings.TrimSpace(out) 2062 if out != "dockerio:dockerio" { 2063 t.Fatalf("Wrong /hello ownership: %s, expected dockerio:dockerio", out) 2064 } 2065 2066 logDone("run - copy uid/gid for volume") 2067 } 2068 2069 // Test for #1582 2070 func TestRunCopyVolumeContent(t *testing.T) { 2071 name := "testruncopyvolumecontent" 2072 defer deleteImages(name) 2073 defer deleteAllContainers() 2074 _, err := buildImage(name, 2075 `FROM busybox 2076 RUN mkdir -p /hello/local && echo hello > /hello/local/world`, 2077 true) 2078 if err != nil { 2079 t.Fatal(err) 2080 } 2081 2082 // Test that the content is copied from the image to the volume 2083 cmd := exec.Command(dockerBinary, "run", "--rm", "-v", "/hello", name, "find", "/hello") 2084 out, _, err := runCommandWithOutput(cmd) 2085 if err != nil { 2086 t.Fatal(err, out) 2087 } 2088 if !(strings.Contains(out, "/hello/local/world") && strings.Contains(out, "/hello/local")) { 2089 t.Fatal("Container failed to transfer content to volume") 2090 } 2091 logDone("run - copy volume content") 2092 } 2093 2094 func TestRunCleanupCmdOnEntrypoint(t *testing.T) { 2095 name := "testrunmdcleanuponentrypoint" 2096 defer deleteImages(name) 2097 defer deleteAllContainers() 2098 if _, err := buildImage(name, 2099 `FROM busybox 2100 ENTRYPOINT ["echo"] 2101 CMD ["testingpoint"]`, 2102 true); err != nil { 2103 t.Fatal(err) 2104 } 2105 runCmd := exec.Command(dockerBinary, "run", "--entrypoint", "whoami", name) 2106 out, exit, err := runCommandWithOutput(runCmd) 2107 if err != nil { 2108 t.Fatalf("Error: %v, out: %q", err, out) 2109 } 2110 if exit != 0 { 2111 t.Fatalf("expected exit code 0 received %d, out: %q", exit, out) 2112 } 2113 out = strings.TrimSpace(out) 2114 if out != "root" { 2115 t.Fatalf("Expected output root, got %q", out) 2116 } 2117 logDone("run - cleanup cmd on --entrypoint") 2118 } 2119 2120 // TestRunWorkdirExistsAndIsFile checks that if 'docker run -w' with existing file can be detected 2121 func TestRunWorkdirExistsAndIsFile(t *testing.T) { 2122 defer deleteAllContainers() 2123 runCmd := exec.Command(dockerBinary, "run", "-w", "/bin/cat", "busybox") 2124 out, exit, err := runCommandWithOutput(runCmd) 2125 if !(err != nil && exit == 1 && strings.Contains(out, "Cannot mkdir: /bin/cat is not a directory")) { 2126 t.Fatalf("Docker must complains about making dir, but we got out: %s, exit: %d, err: %s", out, exit, err) 2127 } 2128 logDone("run - error on existing file for workdir") 2129 } 2130 2131 func TestRunExitOnStdinClose(t *testing.T) { 2132 name := "testrunexitonstdinclose" 2133 defer deleteAllContainers() 2134 runCmd := exec.Command(dockerBinary, "run", "--name", name, "-i", "busybox", "/bin/cat") 2135 2136 stdin, err := runCmd.StdinPipe() 2137 if err != nil { 2138 t.Fatal(err) 2139 } 2140 stdout, err := runCmd.StdoutPipe() 2141 if err != nil { 2142 t.Fatal(err) 2143 } 2144 2145 if err := runCmd.Start(); err != nil { 2146 t.Fatal(err) 2147 } 2148 if _, err := stdin.Write([]byte("hello\n")); err != nil { 2149 t.Fatal(err) 2150 } 2151 2152 r := bufio.NewReader(stdout) 2153 line, err := r.ReadString('\n') 2154 if err != nil { 2155 t.Fatal(err) 2156 } 2157 line = strings.TrimSpace(line) 2158 if line != "hello" { 2159 t.Fatalf("Output should be 'hello', got '%q'", line) 2160 } 2161 if err := stdin.Close(); err != nil { 2162 t.Fatal(err) 2163 } 2164 finish := make(chan struct{}) 2165 go func() { 2166 if err := runCmd.Wait(); err != nil { 2167 t.Fatal(err) 2168 } 2169 close(finish) 2170 }() 2171 select { 2172 case <-finish: 2173 case <-time.After(1 * time.Second): 2174 t.Fatal("docker run failed to exit on stdin close") 2175 } 2176 state, err := inspectField(name, "State.Running") 2177 if err != nil { 2178 t.Fatal(err) 2179 } 2180 if state != "false" { 2181 t.Fatal("Container must be stopped after stdin closing") 2182 } 2183 logDone("run - exit on stdin closing") 2184 } 2185 2186 // Test for #2267 2187 func TestRunWriteHostsFileAndNotCommit(t *testing.T) { 2188 defer deleteAllContainers() 2189 2190 name := "writehosts" 2191 cmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "sh", "-c", "echo test2267 >> /etc/hosts && cat /etc/hosts") 2192 out, _, err := runCommandWithOutput(cmd) 2193 if err != nil { 2194 t.Fatal(err, out) 2195 } 2196 if !strings.Contains(out, "test2267") { 2197 t.Fatal("/etc/hosts should contain 'test2267'") 2198 } 2199 2200 cmd = exec.Command(dockerBinary, "diff", name) 2201 if err != nil { 2202 t.Fatal(err, out) 2203 } 2204 out, _, err = runCommandWithOutput(cmd) 2205 if err != nil { 2206 t.Fatal(err, out) 2207 } 2208 2209 if len(strings.Trim(out, "\r\n")) != 0 && !eqToBaseDiff(out, t) { 2210 t.Fatal("diff should be empty") 2211 } 2212 2213 logDone("run - write to /etc/hosts and not commited") 2214 } 2215 2216 func eqToBaseDiff(out string, t *testing.T) bool { 2217 cmd := exec.Command(dockerBinary, "run", "-d", "busybox", "echo", "hello") 2218 out1, _, err := runCommandWithOutput(cmd) 2219 cID := stripTrailingCharacters(out1) 2220 cmd = exec.Command(dockerBinary, "diff", cID) 2221 base_diff, _, err := runCommandWithOutput(cmd) 2222 if err != nil { 2223 t.Fatal(err, base_diff) 2224 } 2225 base_arr := strings.Split(base_diff, "\n") 2226 sort.Strings(base_arr) 2227 out_arr := strings.Split(out, "\n") 2228 sort.Strings(out_arr) 2229 return sliceEq(base_arr, out_arr) 2230 } 2231 2232 func sliceEq(a, b []string) bool { 2233 if len(a) != len(b) { 2234 return false 2235 } 2236 2237 for i := range a { 2238 if a[i] != b[i] { 2239 return false 2240 } 2241 } 2242 2243 return true 2244 } 2245 2246 // Test for #2267 2247 func TestRunWriteHostnameFileAndNotCommit(t *testing.T) { 2248 defer deleteAllContainers() 2249 2250 name := "writehostname" 2251 cmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "sh", "-c", "echo test2267 >> /etc/hostname && cat /etc/hostname") 2252 out, _, err := runCommandWithOutput(cmd) 2253 if err != nil { 2254 t.Fatal(err, out) 2255 } 2256 if !strings.Contains(out, "test2267") { 2257 t.Fatal("/etc/hostname should contain 'test2267'") 2258 } 2259 2260 cmd = exec.Command(dockerBinary, "diff", name) 2261 if err != nil { 2262 t.Fatal(err, out) 2263 } 2264 out, _, err = runCommandWithOutput(cmd) 2265 if err != nil { 2266 t.Fatal(err, out) 2267 } 2268 if len(strings.Trim(out, "\r\n")) != 0 && !eqToBaseDiff(out, t) { 2269 t.Fatal("diff should be empty") 2270 } 2271 2272 logDone("run - write to /etc/hostname and not commited") 2273 } 2274 2275 // Test for #2267 2276 func TestRunWriteResolvFileAndNotCommit(t *testing.T) { 2277 defer deleteAllContainers() 2278 2279 name := "writeresolv" 2280 cmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "sh", "-c", "echo test2267 >> /etc/resolv.conf && cat /etc/resolv.conf") 2281 out, _, err := runCommandWithOutput(cmd) 2282 if err != nil { 2283 t.Fatal(err, out) 2284 } 2285 if !strings.Contains(out, "test2267") { 2286 t.Fatal("/etc/resolv.conf should contain 'test2267'") 2287 } 2288 2289 cmd = exec.Command(dockerBinary, "diff", name) 2290 if err != nil { 2291 t.Fatal(err, out) 2292 } 2293 out, _, err = runCommandWithOutput(cmd) 2294 if err != nil { 2295 t.Fatal(err, out) 2296 } 2297 if len(strings.Trim(out, "\r\n")) != 0 && !eqToBaseDiff(out, t) { 2298 t.Fatal("diff should be empty") 2299 } 2300 2301 logDone("run - write to /etc/resolv.conf and not commited") 2302 } 2303 2304 func TestRunWithBadDevice(t *testing.T) { 2305 defer deleteAllContainers() 2306 2307 name := "baddevice" 2308 cmd := exec.Command(dockerBinary, "run", "--name", name, "--device", "/etc", "busybox", "true") 2309 out, _, err := runCommandWithOutput(cmd) 2310 if err == nil { 2311 t.Fatal("Run should fail with bad device") 2312 } 2313 expected := `\"/etc\": not a device node` 2314 if !strings.Contains(out, expected) { 2315 t.Fatalf("Output should contain %q, actual out: %q", expected, out) 2316 } 2317 logDone("run - error with bad device") 2318 } 2319 2320 func TestRunEntrypoint(t *testing.T) { 2321 defer deleteAllContainers() 2322 2323 name := "entrypoint" 2324 cmd := exec.Command(dockerBinary, "run", "--name", name, "--entrypoint", "/bin/echo", "busybox", "-n", "foobar") 2325 out, _, err := runCommandWithOutput(cmd) 2326 if err != nil { 2327 t.Fatal(err, out) 2328 } 2329 expected := "foobar" 2330 if out != expected { 2331 t.Fatalf("Output should be %q, actual out: %q", expected, out) 2332 } 2333 logDone("run - entrypoint") 2334 } 2335 2336 func TestRunBindMounts(t *testing.T) { 2337 testRequires(t, SameHostDaemon) 2338 defer deleteAllContainers() 2339 2340 tmpDir, err := ioutil.TempDir("", "docker-test-container") 2341 if err != nil { 2342 t.Fatal(err) 2343 } 2344 2345 defer os.RemoveAll(tmpDir) 2346 writeFile(path.Join(tmpDir, "touch-me"), "", t) 2347 2348 // Test reading from a read-only bind mount 2349 cmd := exec.Command(dockerBinary, "run", "-v", fmt.Sprintf("%s:/tmp:ro", tmpDir), "busybox", "ls", "/tmp") 2350 out, _, err := runCommandWithOutput(cmd) 2351 if err != nil { 2352 t.Fatal(err, out) 2353 } 2354 if !strings.Contains(out, "touch-me") { 2355 t.Fatal("Container failed to read from bind mount") 2356 } 2357 2358 // test writing to bind mount 2359 cmd = exec.Command(dockerBinary, "run", "-v", fmt.Sprintf("%s:/tmp:rw", tmpDir), "busybox", "touch", "/tmp/holla") 2360 out, _, err = runCommandWithOutput(cmd) 2361 if err != nil { 2362 t.Fatal(err, out) 2363 } 2364 readFile(path.Join(tmpDir, "holla"), t) // Will fail if the file doesn't exist 2365 2366 // test mounting to an illegal destination directory 2367 cmd = exec.Command(dockerBinary, "run", "-v", fmt.Sprintf("%s:.", tmpDir), "busybox", "ls", ".") 2368 _, err = runCommand(cmd) 2369 if err == nil { 2370 t.Fatal("Container bind mounted illegal directory") 2371 } 2372 2373 // test mount a file 2374 cmd = exec.Command(dockerBinary, "run", "-v", fmt.Sprintf("%s/holla:/tmp/holla:rw", tmpDir), "busybox", "sh", "-c", "echo -n 'yotta' > /tmp/holla") 2375 _, err = runCommand(cmd) 2376 if err != nil { 2377 t.Fatal(err, out) 2378 } 2379 content := readFile(path.Join(tmpDir, "holla"), t) // Will fail if the file doesn't exist 2380 expected := "yotta" 2381 if content != expected { 2382 t.Fatalf("Output should be %q, actual out: %q", expected, content) 2383 } 2384 2385 logDone("run - bind mounts") 2386 } 2387 2388 // Ensure that CIDFile gets deleted if it's empty 2389 // Perform this test by making `docker run` fail 2390 func TestRunCidFileCleanupIfEmpty(t *testing.T) { 2391 defer deleteAllContainers() 2392 2393 tmpDir, err := ioutil.TempDir("", "TestRunCidFile") 2394 if err != nil { 2395 t.Fatal(err) 2396 } 2397 defer os.RemoveAll(tmpDir) 2398 tmpCidFile := path.Join(tmpDir, "cid") 2399 cmd := exec.Command(dockerBinary, "run", "--cidfile", tmpCidFile, "emptyfs") 2400 out, _, err := runCommandWithOutput(cmd) 2401 if err == nil { 2402 t.Fatalf("Run without command must fail. out=%s", out) 2403 } else if !strings.Contains(out, "No command specified") { 2404 t.Fatalf("Run without command failed with wrong output. out=%s\nerr=%v", out, err) 2405 } 2406 2407 if _, err := os.Stat(tmpCidFile); err == nil { 2408 t.Fatalf("empty CIDFile %q should've been deleted", tmpCidFile) 2409 } 2410 logDone("run - cleanup empty cidfile on error") 2411 } 2412 2413 // #2098 - Docker cidFiles only contain short version of the containerId 2414 //sudo docker run --cidfile /tmp/docker_test.cid ubuntu echo "test" 2415 // TestRunCidFile tests that run --cidfile returns the longid 2416 func TestRunCidFileCheckIDLength(t *testing.T) { 2417 defer deleteAllContainers() 2418 2419 tmpDir, err := ioutil.TempDir("", "TestRunCidFile") 2420 if err != nil { 2421 t.Fatal(err) 2422 } 2423 tmpCidFile := path.Join(tmpDir, "cid") 2424 defer os.RemoveAll(tmpDir) 2425 cmd := exec.Command(dockerBinary, "run", "-d", "--cidfile", tmpCidFile, "busybox", "true") 2426 out, _, err := runCommandWithOutput(cmd) 2427 if err != nil { 2428 t.Fatal(err) 2429 } 2430 id := strings.TrimSpace(out) 2431 buffer, err := ioutil.ReadFile(tmpCidFile) 2432 if err != nil { 2433 t.Fatal(err) 2434 } 2435 cid := string(buffer) 2436 if len(cid) != 64 { 2437 t.Fatalf("--cidfile should be a long id, not %q", id) 2438 } 2439 if cid != id { 2440 t.Fatalf("cid must be equal to %s, got %s", id, cid) 2441 } 2442 2443 logDone("run - cidfile contains long id") 2444 } 2445 2446 func TestRunNetworkNotInitializedNoneMode(t *testing.T) { 2447 defer deleteAllContainers() 2448 2449 cmd := exec.Command(dockerBinary, "run", "-d", "--net=none", "busybox", "top") 2450 out, _, err := runCommandWithOutput(cmd) 2451 if err != nil { 2452 t.Fatal(err) 2453 } 2454 id := strings.TrimSpace(out) 2455 res, err := inspectField(id, "NetworkSettings.IPAddress") 2456 if err != nil { 2457 t.Fatal(err) 2458 } 2459 if res != "" { 2460 t.Fatalf("For 'none' mode network must not be initialized, but container got IP: %s", res) 2461 } 2462 2463 logDone("run - network must not be initialized in 'none' mode") 2464 } 2465 2466 func TestRunSetMacAddress(t *testing.T) { 2467 mac := "12:34:56:78:9a:bc" 2468 2469 defer deleteAllContainers() 2470 cmd := exec.Command(dockerBinary, "run", "-i", "--rm", fmt.Sprintf("--mac-address=%s", mac), "busybox", "/bin/sh", "-c", "ip link show eth0 | tail -1 | awk '{print $2}'") 2471 out, ec, err := runCommandWithOutput(cmd) 2472 if err != nil { 2473 t.Fatalf("exec failed:\nexit code=%v\noutput=%s", ec, out) 2474 } 2475 actualMac := strings.TrimSpace(out) 2476 if actualMac != mac { 2477 t.Fatalf("Set MAC address with --mac-address failed. The container has an incorrect MAC address: %q, expected: %q", actualMac, mac) 2478 } 2479 2480 logDone("run - setting MAC address with --mac-address") 2481 } 2482 2483 func TestRunInspectMacAddress(t *testing.T) { 2484 defer deleteAllContainers() 2485 2486 mac := "12:34:56:78:9a:bc" 2487 cmd := exec.Command(dockerBinary, "run", "-d", "--mac-address="+mac, "busybox", "top") 2488 out, _, err := runCommandWithOutput(cmd) 2489 if err != nil { 2490 t.Fatal(err) 2491 } 2492 id := strings.TrimSpace(out) 2493 inspectedMac, err := inspectField(id, "NetworkSettings.MacAddress") 2494 if err != nil { 2495 t.Fatal(err) 2496 } 2497 if inspectedMac != mac { 2498 t.Fatalf("docker inspect outputs wrong MAC address: %q, should be: %q", inspectedMac, mac) 2499 } 2500 2501 logDone("run - inspecting MAC address") 2502 } 2503 2504 // test docker run use a invalid mac address 2505 func TestRunWithInvalidMacAddress(t *testing.T) { 2506 defer deleteAllContainers() 2507 2508 runCmd := exec.Command(dockerBinary, "run", "--mac-address", "92:d0:c6:0a:29", "busybox") 2509 out, _, err := runCommandWithOutput(runCmd) 2510 //use a invalid mac address should with a error out 2511 if err == nil || !strings.Contains(out, "is not a valid mac address") { 2512 t.Fatalf("run with an invalid --mac-address should with error out") 2513 } 2514 2515 logDone("run - can't use an invalid mac address") 2516 } 2517 2518 func TestRunDeallocatePortOnMissingIptablesRule(t *testing.T) { 2519 defer deleteAllContainers() 2520 testRequires(t, SameHostDaemon) 2521 2522 cmd := exec.Command(dockerBinary, "run", "-d", "-p", "23:23", "busybox", "top") 2523 out, _, err := runCommandWithOutput(cmd) 2524 if err != nil { 2525 t.Fatal(err) 2526 } 2527 id := strings.TrimSpace(out) 2528 ip, err := inspectField(id, "NetworkSettings.IPAddress") 2529 if err != nil { 2530 t.Fatal(err) 2531 } 2532 iptCmd := exec.Command("iptables", "-D", "DOCKER", "-d", fmt.Sprintf("%s/32", ip), 2533 "!", "-i", "docker0", "-o", "docker0", "-p", "tcp", "-m", "tcp", "--dport", "23", "-j", "ACCEPT") 2534 out, _, err = runCommandWithOutput(iptCmd) 2535 if err != nil { 2536 t.Fatal(err, out) 2537 } 2538 if err := deleteContainer(id); err != nil { 2539 t.Fatal(err) 2540 } 2541 cmd = exec.Command(dockerBinary, "run", "-d", "-p", "23:23", "busybox", "top") 2542 out, _, err = runCommandWithOutput(cmd) 2543 if err != nil { 2544 t.Fatal(err, out) 2545 } 2546 2547 logDone("run - port should be deallocated even on iptables error") 2548 } 2549 2550 func TestRunPortInUse(t *testing.T) { 2551 defer deleteAllContainers() 2552 testRequires(t, SameHostDaemon) 2553 2554 port := "1234" 2555 l, err := net.Listen("tcp", ":"+port) 2556 if err != nil { 2557 t.Fatal(err) 2558 } 2559 defer l.Close() 2560 cmd := exec.Command(dockerBinary, "run", "-d", "-p", port+":80", "busybox", "top") 2561 out, _, err := runCommandWithOutput(cmd) 2562 if err == nil { 2563 t.Fatalf("Binding on used port must fail") 2564 } 2565 if !strings.Contains(out, "address already in use") { 2566 t.Fatalf("Out must be about \"address already in use\", got %s", out) 2567 } 2568 2569 logDone("run - error out if port already in use") 2570 } 2571 2572 // https://github.com/docker/docker/issues/8428 2573 func TestRunPortProxy(t *testing.T) { 2574 testRequires(t, SameHostDaemon) 2575 2576 defer deleteAllContainers() 2577 2578 port := "12345" 2579 cmd := exec.Command(dockerBinary, "run", "-d", "-p", port+":80", "busybox", "top") 2580 2581 out, _, err := runCommandWithOutput(cmd) 2582 if err != nil { 2583 t.Fatalf("Failed to run and bind port %s, output: %s, error: %s", port, out, err) 2584 } 2585 2586 // connect for 10 times here. This will trigger 10 EPIPES in the child 2587 // process and kill it when it writes to a closed stdout/stderr 2588 for i := 0; i < 10; i++ { 2589 net.Dial("tcp", fmt.Sprintf("0.0.0.0:%s", port)) 2590 } 2591 2592 listPs := exec.Command("sh", "-c", "ps ax | grep docker") 2593 out, _, err = runCommandWithOutput(listPs) 2594 if err != nil { 2595 t.Errorf("list docker process failed with output %s, error %s", out, err) 2596 } 2597 if strings.Contains(out, "docker <defunct>") { 2598 t.Errorf("Unexpected defunct docker process") 2599 } 2600 if !strings.Contains(out, "docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 12345") { 2601 t.Errorf("Failed to find docker-proxy process, got %s", out) 2602 } 2603 2604 logDone("run - proxy should work with unavailable port") 2605 } 2606 2607 // Regression test for #7792 2608 func TestRunMountOrdering(t *testing.T) { 2609 defer deleteAllContainers() 2610 testRequires(t, SameHostDaemon) 2611 2612 tmpDir, err := ioutil.TempDir("", "docker_nested_mount_test") 2613 if err != nil { 2614 t.Fatal(err) 2615 } 2616 defer os.RemoveAll(tmpDir) 2617 2618 tmpDir2, err := ioutil.TempDir("", "docker_nested_mount_test2") 2619 if err != nil { 2620 t.Fatal(err) 2621 } 2622 defer os.RemoveAll(tmpDir2) 2623 2624 // Create a temporary tmpfs mount. 2625 fooDir := filepath.Join(tmpDir, "foo") 2626 if err := os.MkdirAll(filepath.Join(tmpDir, "foo"), 0755); err != nil { 2627 t.Fatalf("failed to mkdir at %s - %s", fooDir, err) 2628 } 2629 2630 if err := ioutil.WriteFile(fmt.Sprintf("%s/touch-me", fooDir), []byte{}, 0644); err != nil { 2631 t.Fatal(err) 2632 } 2633 2634 if err := ioutil.WriteFile(fmt.Sprintf("%s/touch-me", tmpDir), []byte{}, 0644); err != nil { 2635 t.Fatal(err) 2636 } 2637 2638 if err := ioutil.WriteFile(fmt.Sprintf("%s/touch-me", tmpDir2), []byte{}, 0644); err != nil { 2639 t.Fatal(err) 2640 } 2641 2642 cmd := exec.Command(dockerBinary, "run", "-v", fmt.Sprintf("%s:/tmp", tmpDir), "-v", fmt.Sprintf("%s:/tmp/foo", fooDir), "-v", fmt.Sprintf("%s:/tmp/tmp2", tmpDir2), "-v", fmt.Sprintf("%s:/tmp/tmp2/foo", fooDir), "busybox:latest", "sh", "-c", "ls /tmp/touch-me && ls /tmp/foo/touch-me && ls /tmp/tmp2/touch-me && ls /tmp/tmp2/foo/touch-me") 2643 out, _, err := runCommandWithOutput(cmd) 2644 if err != nil { 2645 t.Fatal(out, err) 2646 } 2647 2648 logDone("run - volumes are mounted in the correct order") 2649 } 2650 2651 // Regression test for https://github.com/docker/docker/issues/8259 2652 func TestRunReuseBindVolumeThatIsSymlink(t *testing.T) { 2653 defer deleteAllContainers() 2654 testRequires(t, SameHostDaemon) 2655 2656 tmpDir, err := ioutil.TempDir(os.TempDir(), "testlink") 2657 if err != nil { 2658 t.Fatal(err) 2659 } 2660 defer os.RemoveAll(tmpDir) 2661 2662 linkPath := os.TempDir() + "/testlink2" 2663 if err := os.Symlink(tmpDir, linkPath); err != nil { 2664 t.Fatal(err) 2665 } 2666 defer os.RemoveAll(linkPath) 2667 2668 // Create first container 2669 cmd := exec.Command(dockerBinary, "run", "-v", fmt.Sprintf("%s:/tmp/test", linkPath), "busybox", "ls", "-lh", "/tmp/test") 2670 if _, err := runCommand(cmd); err != nil { 2671 t.Fatal(err) 2672 } 2673 2674 // Create second container with same symlinked path 2675 // This will fail if the referenced issue is hit with a "Volume exists" error 2676 cmd = exec.Command(dockerBinary, "run", "-v", fmt.Sprintf("%s:/tmp/test", linkPath), "busybox", "ls", "-lh", "/tmp/test") 2677 if out, _, err := runCommandWithOutput(cmd); err != nil { 2678 t.Fatal(err, out) 2679 } 2680 2681 logDone("run - can remount old bindmount volume") 2682 } 2683 2684 //GH#10604: Test an "/etc" volume doesn't overlay special bind mounts in container 2685 func TestRunCreateVolumeEtc(t *testing.T) { 2686 defer deleteAllContainers() 2687 2688 cmd := exec.Command(dockerBinary, "run", "--dns=127.0.0.1", "-v", "/etc", "busybox", "cat", "/etc/resolv.conf") 2689 out, _, err := runCommandWithOutput(cmd) 2690 if err != nil { 2691 t.Fatal("failed to run container: %v, output: %q", err, out) 2692 } 2693 if !strings.Contains(out, "nameserver 127.0.0.1") { 2694 t.Fatal("/etc volume mount hides /etc/resolv.conf") 2695 } 2696 2697 cmd = exec.Command(dockerBinary, "run", "-h=test123", "-v", "/etc", "busybox", "cat", "/etc/hostname") 2698 out, _, err = runCommandWithOutput(cmd) 2699 if err != nil { 2700 t.Fatal("failed to run container: %v, output: %q", err, out) 2701 } 2702 if !strings.Contains(out, "test123") { 2703 t.Fatal("/etc volume mount hides /etc/hostname") 2704 } 2705 2706 cmd = exec.Command(dockerBinary, "run", "--add-host=test:192.168.0.1", "-v", "/etc", "busybox", "cat", "/etc/hosts") 2707 out, _, err = runCommandWithOutput(cmd) 2708 if err != nil { 2709 t.Fatal("failed to run container: %v, output: %q", err, out) 2710 } 2711 out = strings.Replace(out, "\n", " ", -1) 2712 if !strings.Contains(out, "192.168.0.1\ttest") || !strings.Contains(out, "127.0.0.1\tlocalhost") { 2713 t.Fatal("/etc volume mount hides /etc/hosts") 2714 } 2715 2716 logDone("run - verify /etc volume doesn't hide special bind mounts") 2717 } 2718 2719 func TestVolumesNoCopyData(t *testing.T) { 2720 defer deleteImages("dataimage") 2721 defer deleteAllContainers() 2722 if _, err := buildImage("dataimage", 2723 `FROM busybox 2724 RUN mkdir -p /foo 2725 RUN touch /foo/bar`, 2726 true); err != nil { 2727 t.Fatal(err) 2728 } 2729 2730 cmd := exec.Command(dockerBinary, "run", "--name", "test", "-v", "/foo", "busybox") 2731 if _, err := runCommand(cmd); err != nil { 2732 t.Fatal(err) 2733 } 2734 2735 cmd = exec.Command(dockerBinary, "run", "--volumes-from", "test", "dataimage", "ls", "-lh", "/foo/bar") 2736 if out, _, err := runCommandWithOutput(cmd); err == nil || !strings.Contains(out, "No such file or directory") { 2737 t.Fatalf("Data was copied on volumes-from but shouldn't be:\n%q", out) 2738 } 2739 2740 tmpDir := randomUnixTmpDirPath("docker_test_bind_mount_copy_data") 2741 cmd = exec.Command(dockerBinary, "run", "-v", tmpDir+":/foo", "dataimage", "ls", "-lh", "/foo/bar") 2742 if out, _, err := runCommandWithOutput(cmd); err == nil || !strings.Contains(out, "No such file or directory") { 2743 t.Fatalf("Data was copied on bind-mount but shouldn't be:\n%q", out) 2744 } 2745 2746 logDone("run - volumes do not copy data for volumes-from and bindmounts") 2747 } 2748 2749 func TestRunVolumesNotRecreatedOnStart(t *testing.T) { 2750 testRequires(t, SameHostDaemon) 2751 2752 // Clear out any remnants from other tests 2753 deleteAllContainers() 2754 info, err := ioutil.ReadDir(volumesConfigPath) 2755 if err != nil { 2756 t.Fatal(err) 2757 } 2758 if len(info) > 0 { 2759 for _, f := range info { 2760 if err := os.RemoveAll(volumesConfigPath + "/" + f.Name()); err != nil { 2761 t.Fatal(err) 2762 } 2763 } 2764 } 2765 2766 defer deleteAllContainers() 2767 cmd := exec.Command(dockerBinary, "run", "-v", "/foo", "--name", "lone_starr", "busybox") 2768 if _, err := runCommand(cmd); err != nil { 2769 t.Fatal(err) 2770 } 2771 2772 cmd = exec.Command(dockerBinary, "start", "lone_starr") 2773 if _, err := runCommand(cmd); err != nil { 2774 t.Fatal(err) 2775 } 2776 2777 info, err = ioutil.ReadDir(volumesConfigPath) 2778 if err != nil { 2779 t.Fatal(err) 2780 } 2781 if len(info) != 1 { 2782 t.Fatalf("Expected only 1 volume have %v", len(info)) 2783 } 2784 2785 logDone("run - volumes not recreated on start") 2786 } 2787 2788 func TestRunNoOutputFromPullInStdout(t *testing.T) { 2789 defer deleteAllContainers() 2790 // just run with unknown image 2791 cmd := exec.Command(dockerBinary, "run", "asdfsg") 2792 stdout := bytes.NewBuffer(nil) 2793 cmd.Stdout = stdout 2794 if err := cmd.Run(); err == nil { 2795 t.Fatal("Run with unknown image should fail") 2796 } 2797 if stdout.Len() != 0 { 2798 t.Fatalf("Stdout contains output from pull: %s", stdout) 2799 } 2800 logDone("run - no output from pull in stdout") 2801 } 2802 2803 func TestRunVolumesCleanPaths(t *testing.T) { 2804 if _, err := buildImage("run_volumes_clean_paths", 2805 `FROM busybox 2806 VOLUME /foo/`, 2807 true); err != nil { 2808 t.Fatal(err) 2809 } 2810 defer deleteImages("run_volumes_clean_paths") 2811 defer deleteAllContainers() 2812 2813 cmd := exec.Command(dockerBinary, "run", "-v", "/foo", "-v", "/bar/", "--name", "dark_helmet", "run_volumes_clean_paths") 2814 if out, _, err := runCommandWithOutput(cmd); err != nil { 2815 t.Fatal(err, out) 2816 } 2817 2818 out, err := inspectFieldMap("dark_helmet", "Volumes", "/foo/") 2819 if err != nil { 2820 t.Fatal(err) 2821 } 2822 if out != "<no value>" { 2823 t.Fatalf("Found unexpected volume entry for '/foo/' in volumes\n%q", out) 2824 } 2825 2826 out, err = inspectFieldMap("dark_helmet", "Volumes", "/foo") 2827 if err != nil { 2828 t.Fatal(err) 2829 } 2830 if !strings.Contains(out, volumesStoragePath) { 2831 t.Fatalf("Volume was not defined for /foo\n%q", out) 2832 } 2833 2834 out, err = inspectFieldMap("dark_helmet", "Volumes", "/bar/") 2835 if err != nil { 2836 t.Fatal(err) 2837 } 2838 if out != "<no value>" { 2839 t.Fatalf("Found unexpected volume entry for '/bar/' in volumes\n%q", out) 2840 } 2841 out, err = inspectFieldMap("dark_helmet", "Volumes", "/bar") 2842 if err != nil { 2843 t.Fatal(err) 2844 } 2845 if !strings.Contains(out, volumesStoragePath) { 2846 t.Fatalf("Volume was not defined for /bar\n%q", out) 2847 } 2848 2849 logDone("run - volume paths are cleaned") 2850 } 2851 2852 // Regression test for #3631 2853 func TestRunSlowStdoutConsumer(t *testing.T) { 2854 defer deleteAllContainers() 2855 2856 c := exec.Command(dockerBinary, "run", "--rm", "busybox", "/bin/sh", "-c", "dd if=/dev/zero of=/dev/stdout bs=1024 count=2000 | catv") 2857 2858 stdout, err := c.StdoutPipe() 2859 if err != nil { 2860 t.Fatal(err) 2861 } 2862 2863 if err := c.Start(); err != nil { 2864 t.Fatal(err) 2865 } 2866 n, err := consumeWithSpeed(stdout, 10000, 5*time.Millisecond, nil) 2867 if err != nil { 2868 t.Fatal(err) 2869 } 2870 2871 expected := 2 * 1024 * 2000 2872 if n != expected { 2873 t.Fatalf("Expected %d, got %d", expected, n) 2874 } 2875 2876 logDone("run - slow consumer") 2877 } 2878 2879 func TestRunAllowPortRangeThroughExpose(t *testing.T) { 2880 defer deleteAllContainers() 2881 2882 cmd := exec.Command(dockerBinary, "run", "-d", "--expose", "3000-3003", "-P", "busybox", "top") 2883 out, _, err := runCommandWithOutput(cmd) 2884 if err != nil { 2885 t.Fatal(err) 2886 } 2887 id := strings.TrimSpace(out) 2888 portstr, err := inspectFieldJSON(id, "NetworkSettings.Ports") 2889 if err != nil { 2890 t.Fatal(err) 2891 } 2892 var ports nat.PortMap 2893 err = unmarshalJSON([]byte(portstr), &ports) 2894 for port, binding := range ports { 2895 portnum, _ := strconv.Atoi(strings.Split(string(port), "/")[0]) 2896 if portnum < 3000 || portnum > 3003 { 2897 t.Fatalf("Port is out of range ", portnum, binding, out) 2898 } 2899 if binding == nil || len(binding) != 1 || len(binding[0].HostPort) == 0 { 2900 t.Fatal("Port is not mapped for the port "+port, out) 2901 } 2902 } 2903 if err := deleteContainer(id); err != nil { 2904 t.Fatal(err) 2905 } 2906 logDone("run - allow port range through --expose flag") 2907 } 2908 2909 // test docker run expose a invalid port 2910 func TestRunExposePort(t *testing.T) { 2911 defer deleteAllContainers() 2912 2913 runCmd := exec.Command(dockerBinary, "run", "--expose", "80000", "busybox") 2914 out, _, err := runCommandWithOutput(runCmd) 2915 //expose a invalid port should with a error out 2916 if err == nil || !strings.Contains(out, "Invalid range format for --expose") { 2917 t.Fatalf("run --expose a invalid port should with error out") 2918 } 2919 2920 logDone("run - can't expose a invalid port") 2921 } 2922 2923 func TestRunUnknownCommand(t *testing.T) { 2924 testRequires(t, NativeExecDriver) 2925 defer deleteAllContainers() 2926 runCmd := exec.Command(dockerBinary, "create", "busybox", "/bin/nada") 2927 cID, _, _, err := runCommandWithStdoutStderr(runCmd) 2928 if err != nil { 2929 t.Fatalf("Failed to create container: %v, output: %q", err, cID) 2930 } 2931 cID = strings.TrimSpace(cID) 2932 2933 runCmd = exec.Command(dockerBinary, "start", cID) 2934 _, _, _, _ = runCommandWithStdoutStderr(runCmd) 2935 2936 runCmd = exec.Command(dockerBinary, "inspect", "--format={{.State.ExitCode}}", cID) 2937 rc, _, _, err2 := runCommandWithStdoutStderr(runCmd) 2938 rc = strings.TrimSpace(rc) 2939 2940 if err2 != nil { 2941 t.Fatalf("Error getting status of container: %v", err2) 2942 } 2943 2944 if rc == "0" { 2945 t.Fatalf("ExitCode(%v) cannot be 0", rc) 2946 } 2947 2948 logDone("run - Unknown Command") 2949 } 2950 2951 func TestRunModeIpcHost(t *testing.T) { 2952 testRequires(t, SameHostDaemon) 2953 defer deleteAllContainers() 2954 2955 hostIpc, err := os.Readlink("/proc/1/ns/ipc") 2956 if err != nil { 2957 t.Fatal(err) 2958 } 2959 2960 cmd := exec.Command(dockerBinary, "run", "--ipc=host", "busybox", "readlink", "/proc/self/ns/ipc") 2961 out2, _, err := runCommandWithOutput(cmd) 2962 if err != nil { 2963 t.Fatal(err, out2) 2964 } 2965 2966 out2 = strings.Trim(out2, "\n") 2967 if hostIpc != out2 { 2968 t.Fatalf("IPC different with --ipc=host %s != %s\n", hostIpc, out2) 2969 } 2970 2971 cmd = exec.Command(dockerBinary, "run", "busybox", "readlink", "/proc/self/ns/ipc") 2972 out2, _, err = runCommandWithOutput(cmd) 2973 if err != nil { 2974 t.Fatal(err, out2) 2975 } 2976 2977 out2 = strings.Trim(out2, "\n") 2978 if hostIpc == out2 { 2979 t.Fatalf("IPC should be different without --ipc=host %s == %s\n", hostIpc, out2) 2980 } 2981 2982 logDone("run - ipc host mode") 2983 } 2984 2985 func TestRunModeIpcContainer(t *testing.T) { 2986 defer deleteAllContainers() 2987 testRequires(t, SameHostDaemon) 2988 2989 cmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top") 2990 out, _, err := runCommandWithOutput(cmd) 2991 if err != nil { 2992 t.Fatal(err, out) 2993 } 2994 id := strings.TrimSpace(out) 2995 state, err := inspectField(id, "State.Running") 2996 if err != nil { 2997 t.Fatal(err) 2998 } 2999 if state != "true" { 3000 t.Fatal("Container state is 'not running'") 3001 } 3002 pid1, err := inspectField(id, "State.Pid") 3003 if err != nil { 3004 t.Fatal(err) 3005 } 3006 3007 parentContainerIpc, err := os.Readlink(fmt.Sprintf("/proc/%s/ns/ipc", pid1)) 3008 if err != nil { 3009 t.Fatal(err) 3010 } 3011 cmd = exec.Command(dockerBinary, "run", fmt.Sprintf("--ipc=container:%s", id), "busybox", "readlink", "/proc/self/ns/ipc") 3012 out2, _, err := runCommandWithOutput(cmd) 3013 if err != nil { 3014 t.Fatal(err, out2) 3015 } 3016 3017 out2 = strings.Trim(out2, "\n") 3018 if parentContainerIpc != out2 { 3019 t.Fatalf("IPC different with --ipc=container:%s %s != %s\n", id, parentContainerIpc, out2) 3020 } 3021 3022 logDone("run - ipc container mode") 3023 } 3024 3025 func TestContainerNetworkMode(t *testing.T) { 3026 defer deleteAllContainers() 3027 testRequires(t, SameHostDaemon) 3028 3029 cmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top") 3030 out, _, err := runCommandWithOutput(cmd) 3031 if err != nil { 3032 t.Fatal(err, out) 3033 } 3034 id := strings.TrimSpace(out) 3035 if err := waitRun(id); err != nil { 3036 t.Fatal(err) 3037 } 3038 pid1, err := inspectField(id, "State.Pid") 3039 if err != nil { 3040 t.Fatal(err) 3041 } 3042 3043 parentContainerNet, err := os.Readlink(fmt.Sprintf("/proc/%s/ns/net", pid1)) 3044 if err != nil { 3045 t.Fatal(err) 3046 } 3047 cmd = exec.Command(dockerBinary, "run", fmt.Sprintf("--net=container:%s", id), "busybox", "readlink", "/proc/self/ns/net") 3048 out2, _, err := runCommandWithOutput(cmd) 3049 if err != nil { 3050 t.Fatal(err, out2) 3051 } 3052 3053 out2 = strings.Trim(out2, "\n") 3054 if parentContainerNet != out2 { 3055 t.Fatalf("NET different with --net=container:%s %s != %s\n", id, parentContainerNet, out2) 3056 } 3057 3058 logDone("run - container shared network namespace") 3059 } 3060 3061 func TestRunModePidHost(t *testing.T) { 3062 testRequires(t, NativeExecDriver, SameHostDaemon) 3063 defer deleteAllContainers() 3064 3065 hostPid, err := os.Readlink("/proc/1/ns/pid") 3066 if err != nil { 3067 t.Fatal(err) 3068 } 3069 3070 cmd := exec.Command(dockerBinary, "run", "--pid=host", "busybox", "readlink", "/proc/self/ns/pid") 3071 out2, _, err := runCommandWithOutput(cmd) 3072 if err != nil { 3073 t.Fatal(err, out2) 3074 } 3075 3076 out2 = strings.Trim(out2, "\n") 3077 if hostPid != out2 { 3078 t.Fatalf("PID different with --pid=host %s != %s\n", hostPid, out2) 3079 } 3080 3081 cmd = exec.Command(dockerBinary, "run", "busybox", "readlink", "/proc/self/ns/pid") 3082 out2, _, err = runCommandWithOutput(cmd) 3083 if err != nil { 3084 t.Fatal(err, out2) 3085 } 3086 3087 out2 = strings.Trim(out2, "\n") 3088 if hostPid == out2 { 3089 t.Fatalf("PID should be different without --pid=host %s == %s\n", hostPid, out2) 3090 } 3091 3092 logDone("run - pid host mode") 3093 } 3094 3095 func TestRunTLSverify(t *testing.T) { 3096 cmd := exec.Command(dockerBinary, "ps") 3097 out, ec, err := runCommandWithOutput(cmd) 3098 if err != nil || ec != 0 { 3099 t.Fatalf("Should have worked: %v:\n%v", err, out) 3100 } 3101 3102 // Regardless of whether we specify true or false we need to 3103 // test to make sure tls is turned on if --tlsverify is specified at all 3104 3105 cmd = exec.Command(dockerBinary, "--tlsverify=false", "ps") 3106 out, ec, err = runCommandWithOutput(cmd) 3107 if err == nil || ec == 0 || !strings.Contains(out, "trying to connect") { 3108 t.Fatalf("Should have failed: \nec:%v\nout:%v\nerr:%v", ec, out, err) 3109 } 3110 3111 cmd = exec.Command(dockerBinary, "--tlsverify=true", "ps") 3112 out, ec, err = runCommandWithOutput(cmd) 3113 if err == nil || ec == 0 || !strings.Contains(out, "cert") { 3114 t.Fatalf("Should have failed: \nec:%v\nout:%v\nerr:%v", ec, out, err) 3115 } 3116 3117 logDone("run - verify tls is set for --tlsverify") 3118 } 3119 3120 func TestRunPortFromDockerRangeInUse(t *testing.T) { 3121 defer deleteAllContainers() 3122 // first find allocator current position 3123 cmd := exec.Command(dockerBinary, "run", "-d", "-p", ":80", "busybox", "top") 3124 out, _, err := runCommandWithOutput(cmd) 3125 if err != nil { 3126 t.Fatal(out, err) 3127 } 3128 id := strings.TrimSpace(out) 3129 cmd = exec.Command(dockerBinary, "port", id) 3130 out, _, err = runCommandWithOutput(cmd) 3131 if err != nil { 3132 t.Fatal(out, err) 3133 } 3134 out = strings.TrimSpace(out) 3135 3136 if out == "" { 3137 t.Fatal("docker port command output is empty") 3138 } 3139 out = strings.Split(out, ":")[1] 3140 lastPort, err := strconv.Atoi(out) 3141 if err != nil { 3142 t.Fatal(err) 3143 } 3144 port := lastPort + 1 3145 l, err := net.Listen("tcp", ":"+strconv.Itoa(port)) 3146 if err != nil { 3147 t.Fatal(err) 3148 } 3149 defer l.Close() 3150 cmd = exec.Command(dockerBinary, "run", "-d", "-p", ":80", "busybox", "top") 3151 out, _, err = runCommandWithOutput(cmd) 3152 if err != nil { 3153 t.Fatalf(out, err) 3154 } 3155 id = strings.TrimSpace(out) 3156 cmd = exec.Command(dockerBinary, "port", id) 3157 out, _, err = runCommandWithOutput(cmd) 3158 if err != nil { 3159 t.Fatal(out, err) 3160 } 3161 3162 logDone("run - find another port if port from autorange already bound") 3163 } 3164 3165 func TestRunTtyWithPipe(t *testing.T) { 3166 defer deleteAllContainers() 3167 3168 done := make(chan struct{}) 3169 go func() { 3170 defer close(done) 3171 3172 cmd := exec.Command(dockerBinary, "run", "-ti", "busybox", "true") 3173 if _, err := cmd.StdinPipe(); err != nil { 3174 t.Fatal(err) 3175 } 3176 3177 expected := "cannot enable tty mode" 3178 if out, _, err := runCommandWithOutput(cmd); err == nil { 3179 t.Fatal("run should have failed") 3180 } else if !strings.Contains(out, expected) { 3181 t.Fatalf("run failed with error %q: expected %q", out, expected) 3182 } 3183 }() 3184 3185 select { 3186 case <-done: 3187 case <-time.After(3 * time.Second): 3188 t.Fatal("container is running but should have failed") 3189 } 3190 3191 logDone("run - forbid piped stdin with tty") 3192 } 3193 3194 func TestRunNonLocalMacAddress(t *testing.T) { 3195 defer deleteAllContainers() 3196 addr := "00:16:3E:08:00:50" 3197 3198 cmd := exec.Command(dockerBinary, "run", "--mac-address", addr, "busybox", "ifconfig") 3199 if out, _, err := runCommandWithOutput(cmd); err != nil || !strings.Contains(out, addr) { 3200 t.Fatalf("Output should have contained %q: %s, %v", addr, out, err) 3201 } 3202 3203 logDone("run - use non-local mac-address") 3204 } 3205 3206 func TestRunNetHost(t *testing.T) { 3207 testRequires(t, SameHostDaemon) 3208 defer deleteAllContainers() 3209 3210 hostNet, err := os.Readlink("/proc/1/ns/net") 3211 if err != nil { 3212 t.Fatal(err) 3213 } 3214 3215 cmd := exec.Command(dockerBinary, "run", "--net=host", "busybox", "readlink", "/proc/self/ns/net") 3216 out2, _, err := runCommandWithOutput(cmd) 3217 if err != nil { 3218 t.Fatal(err, out2) 3219 } 3220 3221 out2 = strings.Trim(out2, "\n") 3222 if hostNet != out2 { 3223 t.Fatalf("Net namespace different with --net=host %s != %s\n", hostNet, out2) 3224 } 3225 3226 cmd = exec.Command(dockerBinary, "run", "busybox", "readlink", "/proc/self/ns/net") 3227 out2, _, err = runCommandWithOutput(cmd) 3228 if err != nil { 3229 t.Fatal(err, out2) 3230 } 3231 3232 out2 = strings.Trim(out2, "\n") 3233 if hostNet == out2 { 3234 t.Fatalf("Net namespace should be different without --net=host %s == %s\n", hostNet, out2) 3235 } 3236 3237 logDone("run - net host mode") 3238 } 3239 3240 func TestRunNetContainerWhichHost(t *testing.T) { 3241 testRequires(t, SameHostDaemon) 3242 defer deleteAllContainers() 3243 3244 hostNet, err := os.Readlink("/proc/1/ns/net") 3245 if err != nil { 3246 t.Fatal(err) 3247 } 3248 3249 cmd := exec.Command(dockerBinary, "run", "-d", "--net=host", "--name=test", "busybox", "top") 3250 out, _, err := runCommandWithOutput(cmd) 3251 if err != nil { 3252 t.Fatal(err, out) 3253 } 3254 3255 cmd = exec.Command(dockerBinary, "run", "--net=container:test", "busybox", "readlink", "/proc/self/ns/net") 3256 out, _, err = runCommandWithOutput(cmd) 3257 if err != nil { 3258 t.Fatal(err, out) 3259 } 3260 3261 out = strings.Trim(out, "\n") 3262 if hostNet != out { 3263 t.Fatalf("Container should have host network namespace") 3264 } 3265 3266 logDone("run - net container mode, where container in host mode") 3267 } 3268 3269 func TestRunAllowPortRangeThroughPublish(t *testing.T) { 3270 defer deleteAllContainers() 3271 3272 cmd := exec.Command(dockerBinary, "run", "-d", "--expose", "3000-3003", "-p", "3000-3003", "busybox", "top") 3273 out, _, err := runCommandWithOutput(cmd) 3274 3275 id := strings.TrimSpace(out) 3276 portstr, err := inspectFieldJSON(id, "NetworkSettings.Ports") 3277 if err != nil { 3278 t.Fatal(err) 3279 } 3280 var ports nat.PortMap 3281 err = unmarshalJSON([]byte(portstr), &ports) 3282 for port, binding := range ports { 3283 portnum, _ := strconv.Atoi(strings.Split(string(port), "/")[0]) 3284 if portnum < 3000 || portnum > 3003 { 3285 t.Fatalf("Port is out of range ", portnum, binding, out) 3286 } 3287 if binding == nil || len(binding) != 1 || len(binding[0].HostPort) == 0 { 3288 t.Fatal("Port is not mapped for the port "+port, out) 3289 } 3290 } 3291 logDone("run - allow port range through --expose flag") 3292 } 3293 3294 func TestRunOOMExitCode(t *testing.T) { 3295 defer deleteAllContainers() 3296 3297 done := make(chan struct{}) 3298 go func() { 3299 defer close(done) 3300 3301 runCmd := exec.Command(dockerBinary, "run", "-m", "4MB", "busybox", "sh", "-c", "x=a; while true; do x=$x$x; done") 3302 out, exitCode, _ := runCommandWithOutput(runCmd) 3303 if expected := 137; exitCode != expected { 3304 t.Fatalf("wrong exit code for OOM container: expected %d, got %d (output: %q)", expected, exitCode, out) 3305 } 3306 }() 3307 3308 select { 3309 case <-done: 3310 case <-time.After(3 * time.Second): 3311 t.Fatal("Timeout waiting for container to die on OOM") 3312 } 3313 3314 logDone("run - exit code on oom") 3315 } 3316 3317 func TestRunSetDefaultRestartPolicy(t *testing.T) { 3318 defer deleteAllContainers() 3319 runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "test", "busybox", "top") 3320 if out, _, err := runCommandWithOutput(runCmd); err != nil { 3321 t.Fatalf("failed to run container: %v, output: %q", err, out) 3322 } 3323 cmd := exec.Command(dockerBinary, "inspect", "-f", "{{.HostConfig.RestartPolicy.Name}}", "test") 3324 out, _, err := runCommandWithOutput(cmd) 3325 if err != nil { 3326 t.Fatalf("failed to inspect container: %v, output: %q", err, out) 3327 } 3328 out = strings.Trim(out, "\r\n") 3329 if out != "no" { 3330 t.Fatalf("Set default restart policy failed") 3331 } 3332 3333 logDone("run - set default restart policy success") 3334 } 3335 3336 func TestRunRestartMaxRetries(t *testing.T) { 3337 defer deleteAllContainers() 3338 out, err := exec.Command(dockerBinary, "run", "-d", "--restart=on-failure:3", "busybox", "false").CombinedOutput() 3339 if err != nil { 3340 t.Fatal(string(out), err) 3341 } 3342 id := strings.TrimSpace(string(out)) 3343 if err := waitInspect(id, "{{ .State.Restarting }} {{ .State.Running }}", "false false", 5); err != nil { 3344 t.Fatal(err) 3345 } 3346 count, err := inspectField(id, "RestartCount") 3347 if err != nil { 3348 t.Fatal(err) 3349 } 3350 if count != "3" { 3351 t.Fatalf("Container was restarted %s times, expected %d", count, 3) 3352 } 3353 MaximumRetryCount, err := inspectField(id, "HostConfig.RestartPolicy.MaximumRetryCount") 3354 if err != nil { 3355 t.Fatal(err) 3356 } 3357 if MaximumRetryCount != "3" { 3358 t.Fatalf("Container Maximum Retry Count is %s, expected %s", MaximumRetryCount, "3") 3359 } 3360 logDone("run - test max-retries for --restart") 3361 } 3362 3363 func TestRunContainerWithWritableRootfs(t *testing.T) { 3364 defer deleteAllContainers() 3365 out, err := exec.Command(dockerBinary, "run", "--rm", "busybox", "touch", "/file").CombinedOutput() 3366 if err != nil { 3367 t.Fatal(string(out), err) 3368 } 3369 logDone("run - writable rootfs") 3370 } 3371 3372 func TestRunContainerWithReadonlyRootfs(t *testing.T) { 3373 testRequires(t, NativeExecDriver) 3374 defer deleteAllContainers() 3375 3376 out, err := exec.Command(dockerBinary, "run", "--read-only", "--rm", "busybox", "touch", "/file").CombinedOutput() 3377 if err == nil { 3378 t.Fatal("expected container to error on run with read only error") 3379 } 3380 expected := "Read-only file system" 3381 if !strings.Contains(string(out), expected) { 3382 t.Fatalf("expected output from failure to contain %s but contains %s", expected, out) 3383 } 3384 logDone("run - read only rootfs") 3385 } 3386 3387 func TestRunVolumesFromRestartAfterRemoved(t *testing.T) { 3388 defer deleteAllContainers() 3389 3390 out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "--name", "voltest", "-v", "/foo", "busybox")) 3391 if err != nil { 3392 t.Fatal(out, err) 3393 } 3394 3395 out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "--name", "restarter", "--volumes-from", "voltest", "busybox", "top")) 3396 if err != nil { 3397 t.Fatal(out, err) 3398 } 3399 3400 // Remove the main volume container and restart the consuming container 3401 out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "rm", "-f", "voltest")) 3402 if err != nil { 3403 t.Fatal(out, err) 3404 } 3405 3406 // This should not fail since the volumes-from were already applied 3407 out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "restart", "restarter")) 3408 if err != nil { 3409 t.Fatalf("expected container to restart successfully: %v\n%s", err, out) 3410 } 3411 3412 logDone("run - can restart a volumes-from container after producer is removed") 3413 } 3414 3415 func TestRunPidHostWithChildIsKillable(t *testing.T) { 3416 defer deleteAllContainers() 3417 name := "ibuildthecloud" 3418 if out, err := exec.Command(dockerBinary, "run", "-d", "--pid=host", "--name", name, "busybox", "sh", "-c", "sleep 30; echo hi").CombinedOutput(); err != nil { 3419 t.Fatal(err, out) 3420 } 3421 time.Sleep(1 * time.Second) 3422 errchan := make(chan error) 3423 go func() { 3424 if out, err := exec.Command(dockerBinary, "kill", name).CombinedOutput(); err != nil { 3425 errchan <- fmt.Errorf("%v:\n%s", err, out) 3426 } 3427 close(errchan) 3428 }() 3429 select { 3430 case err := <-errchan: 3431 if err != nil { 3432 t.Fatal(err) 3433 } 3434 case <-time.After(5 * time.Second): 3435 t.Fatal("Kill container timed out") 3436 } 3437 logDone("run - can kill container with pid-host and some childs of pid 1") 3438 }