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