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