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