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