github.com/brahmaroutu/docker@v1.2.1-0.20160809185609-eb28dde01f16/integration-cli/docker_cli_daemon_test.go (about) 1 // +build linux 2 3 package main 4 5 import ( 6 "bytes" 7 "encoding/json" 8 "fmt" 9 "io" 10 "io/ioutil" 11 "net" 12 "os" 13 "os/exec" 14 "path" 15 "path/filepath" 16 "regexp" 17 "strconv" 18 "strings" 19 "sync" 20 "syscall" 21 "time" 22 23 "github.com/docker/docker/pkg/integration/checker" 24 "github.com/docker/docker/pkg/mount" 25 "github.com/docker/go-units" 26 "github.com/docker/libnetwork/iptables" 27 "github.com/docker/libtrust" 28 "github.com/go-check/check" 29 "github.com/kr/pty" 30 ) 31 32 // TestLegacyDaemonCommand test starting docker daemon using "deprecated" docker daemon 33 // command. Remove this test when we remove this. 34 func (s *DockerDaemonSuite) TestLegacyDaemonCommand(c *check.C) { 35 cmd := exec.Command(dockerBinary, "daemon", "--storage-driver=vfs", "--debug") 36 err := cmd.Start() 37 c.Assert(err, checker.IsNil, check.Commentf("could not start daemon using 'docker daemon'")) 38 39 c.Assert(cmd.Process.Kill(), checker.IsNil) 40 } 41 42 func (s *DockerDaemonSuite) TestDaemonRestartWithRunningContainersPorts(c *check.C) { 43 if err := s.d.StartWithBusybox(); err != nil { 44 c.Fatalf("Could not start daemon with busybox: %v", err) 45 } 46 47 if out, err := s.d.Cmd("run", "-d", "--name", "top1", "-p", "1234:80", "--restart", "always", "busybox:latest", "top"); err != nil { 48 c.Fatalf("Could not run top1: err=%v\n%s", err, out) 49 } 50 // --restart=no by default 51 if out, err := s.d.Cmd("run", "-d", "--name", "top2", "-p", "80", "busybox:latest", "top"); err != nil { 52 c.Fatalf("Could not run top2: err=%v\n%s", err, out) 53 } 54 55 testRun := func(m map[string]bool, prefix string) { 56 var format string 57 for cont, shouldRun := range m { 58 out, err := s.d.Cmd("ps") 59 if err != nil { 60 c.Fatalf("Could not run ps: err=%v\n%q", err, out) 61 } 62 if shouldRun { 63 format = "%scontainer %q is not running" 64 } else { 65 format = "%scontainer %q is running" 66 } 67 if shouldRun != strings.Contains(out, cont) { 68 c.Fatalf(format, prefix, cont) 69 } 70 } 71 } 72 73 testRun(map[string]bool{"top1": true, "top2": true}, "") 74 75 if err := s.d.Restart(); err != nil { 76 c.Fatalf("Could not restart daemon: %v", err) 77 } 78 testRun(map[string]bool{"top1": true, "top2": false}, "After daemon restart: ") 79 } 80 81 func (s *DockerDaemonSuite) TestDaemonRestartWithVolumesRefs(c *check.C) { 82 if err := s.d.StartWithBusybox(); err != nil { 83 c.Fatal(err) 84 } 85 86 if out, err := s.d.Cmd("run", "--name", "volrestarttest1", "-v", "/foo", "busybox"); err != nil { 87 c.Fatal(err, out) 88 } 89 90 if err := s.d.Restart(); err != nil { 91 c.Fatal(err) 92 } 93 94 if _, err := s.d.Cmd("run", "-d", "--volumes-from", "volrestarttest1", "--name", "volrestarttest2", "busybox", "top"); err != nil { 95 c.Fatal(err) 96 } 97 98 if out, err := s.d.Cmd("rm", "-fv", "volrestarttest2"); err != nil { 99 c.Fatal(err, out) 100 } 101 102 out, err := s.d.Cmd("inspect", "-f", "{{json .Mounts}}", "volrestarttest1") 103 c.Assert(err, check.IsNil) 104 105 if _, err := inspectMountPointJSON(out, "/foo"); err != nil { 106 c.Fatalf("Expected volume to exist: /foo, error: %v\n", err) 107 } 108 } 109 110 // #11008 111 func (s *DockerDaemonSuite) TestDaemonRestartUnlessStopped(c *check.C) { 112 err := s.d.StartWithBusybox() 113 c.Assert(err, check.IsNil) 114 115 out, err := s.d.Cmd("run", "-d", "--name", "top1", "--restart", "always", "busybox:latest", "top") 116 c.Assert(err, check.IsNil, check.Commentf("run top1: %v", out)) 117 118 out, err = s.d.Cmd("run", "-d", "--name", "top2", "--restart", "unless-stopped", "busybox:latest", "top") 119 c.Assert(err, check.IsNil, check.Commentf("run top2: %v", out)) 120 121 testRun := func(m map[string]bool, prefix string) { 122 var format string 123 for name, shouldRun := range m { 124 out, err := s.d.Cmd("ps") 125 c.Assert(err, check.IsNil, check.Commentf("run ps: %v", out)) 126 if shouldRun { 127 format = "%scontainer %q is not running" 128 } else { 129 format = "%scontainer %q is running" 130 } 131 c.Assert(strings.Contains(out, name), check.Equals, shouldRun, check.Commentf(format, prefix, name)) 132 } 133 } 134 135 // both running 136 testRun(map[string]bool{"top1": true, "top2": true}, "") 137 138 out, err = s.d.Cmd("stop", "top1") 139 c.Assert(err, check.IsNil, check.Commentf(out)) 140 141 out, err = s.d.Cmd("stop", "top2") 142 c.Assert(err, check.IsNil, check.Commentf(out)) 143 144 // both stopped 145 testRun(map[string]bool{"top1": false, "top2": false}, "") 146 147 err = s.d.Restart() 148 c.Assert(err, check.IsNil) 149 150 // restart=always running 151 testRun(map[string]bool{"top1": true, "top2": false}, "After daemon restart: ") 152 153 out, err = s.d.Cmd("start", "top2") 154 c.Assert(err, check.IsNil, check.Commentf("start top2: %v", out)) 155 156 err = s.d.Restart() 157 c.Assert(err, check.IsNil) 158 159 // both running 160 testRun(map[string]bool{"top1": true, "top2": true}, "After second daemon restart: ") 161 162 } 163 164 func (s *DockerDaemonSuite) TestDaemonRestartOnFailure(c *check.C) { 165 err := s.d.StartWithBusybox() 166 c.Assert(err, check.IsNil) 167 168 out, err := s.d.Cmd("run", "-d", "--name", "test1", "--restart", "on-failure:3", "busybox:latest", "false") 169 c.Assert(err, check.IsNil, check.Commentf("run top1: %v", out)) 170 171 // wait test1 to stop 172 hostArgs := []string{"--host", s.d.sock()} 173 err = waitInspectWithArgs("test1", "{{.State.Running}} {{.State.Restarting}}", "false false", 10*time.Second, hostArgs...) 174 c.Assert(err, checker.IsNil, check.Commentf("test1 should exit but not")) 175 176 // record last start time 177 out, err = s.d.Cmd("inspect", "-f={{.State.StartedAt}}", "test1") 178 c.Assert(err, checker.IsNil, check.Commentf("out: %v", out)) 179 lastStartTime := out 180 181 err = s.d.Restart() 182 c.Assert(err, check.IsNil) 183 184 // test1 shouldn't restart at all 185 err = waitInspectWithArgs("test1", "{{.State.Running}} {{.State.Restarting}}", "false false", 0, hostArgs...) 186 c.Assert(err, checker.IsNil, check.Commentf("test1 should exit but not")) 187 188 // make sure test1 isn't restarted when daemon restart 189 // if "StartAt" time updates, means test1 was once restarted. 190 out, err = s.d.Cmd("inspect", "-f={{.State.StartedAt}}", "test1") 191 c.Assert(err, checker.IsNil, check.Commentf("out: %v", out)) 192 c.Assert(out, checker.Equals, lastStartTime, check.Commentf("test1 shouldn't start after daemon restarts")) 193 } 194 195 func (s *DockerDaemonSuite) TestDaemonStartIptablesFalse(c *check.C) { 196 if err := s.d.Start("--iptables=false"); err != nil { 197 c.Fatalf("we should have been able to start the daemon with passing iptables=false: %v", err) 198 } 199 } 200 201 // Make sure we cannot shrink base device at daemon restart. 202 func (s *DockerDaemonSuite) TestDaemonRestartWithInvalidBasesize(c *check.C) { 203 testRequires(c, Devicemapper) 204 c.Assert(s.d.Start(), check.IsNil) 205 206 oldBasesizeBytes := s.d.getBaseDeviceSize(c) 207 var newBasesizeBytes int64 = 1073741824 //1GB in bytes 208 209 if newBasesizeBytes < oldBasesizeBytes { 210 err := s.d.Restart("--storage-opt", fmt.Sprintf("dm.basesize=%d", newBasesizeBytes)) 211 c.Assert(err, check.IsNil, check.Commentf("daemon should not have started as new base device size is less than existing base device size: %v", err)) 212 } 213 c.Assert(s.d.Stop(), check.IsNil) 214 } 215 216 // Make sure we can grow base device at daemon restart. 217 func (s *DockerDaemonSuite) TestDaemonRestartWithIncreasedBasesize(c *check.C) { 218 testRequires(c, Devicemapper) 219 c.Assert(s.d.Start(), check.IsNil) 220 221 oldBasesizeBytes := s.d.getBaseDeviceSize(c) 222 223 var newBasesizeBytes int64 = 53687091200 //50GB in bytes 224 225 if newBasesizeBytes < oldBasesizeBytes { 226 c.Skip(fmt.Sprintf("New base device size (%v) must be greater than (%s)", units.HumanSize(float64(newBasesizeBytes)), units.HumanSize(float64(oldBasesizeBytes)))) 227 } 228 229 err := s.d.Restart("--storage-opt", fmt.Sprintf("dm.basesize=%d", newBasesizeBytes)) 230 c.Assert(err, check.IsNil, check.Commentf("we should have been able to start the daemon with increased base device size: %v", err)) 231 232 basesizeAfterRestart := s.d.getBaseDeviceSize(c) 233 newBasesize, err := convertBasesize(newBasesizeBytes) 234 c.Assert(err, check.IsNil, check.Commentf("Error in converting base device size: %v", err)) 235 c.Assert(newBasesize, check.Equals, basesizeAfterRestart, check.Commentf("Basesize passed is not equal to Basesize set")) 236 c.Assert(s.d.Stop(), check.IsNil) 237 } 238 239 // Issue #8444: If docker0 bridge is modified (intentionally or unintentionally) and 240 // no longer has an IP associated, we should gracefully handle that case and associate 241 // an IP with it rather than fail daemon start 242 func (s *DockerDaemonSuite) TestDaemonStartBridgeWithoutIPAssociation(c *check.C) { 243 // rather than depending on brctl commands to verify docker0 is created and up 244 // let's start the daemon and stop it, and then make a modification to run the 245 // actual test 246 if err := s.d.Start(); err != nil { 247 c.Fatalf("Could not start daemon: %v", err) 248 } 249 if err := s.d.Stop(); err != nil { 250 c.Fatalf("Could not stop daemon: %v", err) 251 } 252 253 // now we will remove the ip from docker0 and then try starting the daemon 254 ipCmd := exec.Command("ip", "addr", "flush", "dev", "docker0") 255 stdout, stderr, _, err := runCommandWithStdoutStderr(ipCmd) 256 if err != nil { 257 c.Fatalf("failed to remove docker0 IP association: %v, stdout: %q, stderr: %q", err, stdout, stderr) 258 } 259 260 if err := s.d.Start(); err != nil { 261 warning := "**WARNING: Docker bridge network in bad state--delete docker0 bridge interface to fix" 262 c.Fatalf("Could not start daemon when docker0 has no IP address: %v\n%s", err, warning) 263 } 264 } 265 266 func (s *DockerDaemonSuite) TestDaemonIptablesClean(c *check.C) { 267 if err := s.d.StartWithBusybox(); err != nil { 268 c.Fatalf("Could not start daemon with busybox: %v", err) 269 } 270 271 if out, err := s.d.Cmd("run", "-d", "--name", "top", "-p", "80", "busybox:latest", "top"); err != nil { 272 c.Fatalf("Could not run top: %s, %v", out, err) 273 } 274 275 // get output from iptables with container running 276 ipTablesSearchString := "tcp dpt:80" 277 ipTablesCmd := exec.Command("iptables", "-nvL") 278 out, _, err := runCommandWithOutput(ipTablesCmd) 279 if err != nil { 280 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 281 } 282 283 if !strings.Contains(out, ipTablesSearchString) { 284 c.Fatalf("iptables output should have contained %q, but was %q", ipTablesSearchString, out) 285 } 286 287 if err := s.d.Stop(); err != nil { 288 c.Fatalf("Could not stop daemon: %v", err) 289 } 290 291 // get output from iptables after restart 292 ipTablesCmd = exec.Command("iptables", "-nvL") 293 out, _, err = runCommandWithOutput(ipTablesCmd) 294 if err != nil { 295 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 296 } 297 298 if strings.Contains(out, ipTablesSearchString) { 299 c.Fatalf("iptables output should not have contained %q, but was %q", ipTablesSearchString, out) 300 } 301 } 302 303 func (s *DockerDaemonSuite) TestDaemonIptablesCreate(c *check.C) { 304 if err := s.d.StartWithBusybox(); err != nil { 305 c.Fatalf("Could not start daemon with busybox: %v", err) 306 } 307 308 if out, err := s.d.Cmd("run", "-d", "--name", "top", "--restart=always", "-p", "80", "busybox:latest", "top"); err != nil { 309 c.Fatalf("Could not run top: %s, %v", out, err) 310 } 311 312 // get output from iptables with container running 313 ipTablesSearchString := "tcp dpt:80" 314 ipTablesCmd := exec.Command("iptables", "-nvL") 315 out, _, err := runCommandWithOutput(ipTablesCmd) 316 if err != nil { 317 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 318 } 319 320 if !strings.Contains(out, ipTablesSearchString) { 321 c.Fatalf("iptables output should have contained %q, but was %q", ipTablesSearchString, out) 322 } 323 324 if err := s.d.Restart(); err != nil { 325 c.Fatalf("Could not restart daemon: %v", err) 326 } 327 328 // make sure the container is not running 329 runningOut, err := s.d.Cmd("inspect", "--format={{.State.Running}}", "top") 330 if err != nil { 331 c.Fatalf("Could not inspect on container: %s, %v", out, err) 332 } 333 if strings.TrimSpace(runningOut) != "true" { 334 c.Fatalf("Container should have been restarted after daemon restart. Status running should have been true but was: %q", strings.TrimSpace(runningOut)) 335 } 336 337 // get output from iptables after restart 338 ipTablesCmd = exec.Command("iptables", "-nvL") 339 out, _, err = runCommandWithOutput(ipTablesCmd) 340 if err != nil { 341 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 342 } 343 344 if !strings.Contains(out, ipTablesSearchString) { 345 c.Fatalf("iptables output after restart should have contained %q, but was %q", ipTablesSearchString, out) 346 } 347 } 348 349 // TestDaemonIPv6Enabled checks that when the daemon is started with --ipv6=true that the docker0 bridge 350 // has the fe80::1 address and that a container is assigned a link-local address 351 func (s *DockerSuite) TestDaemonIPv6Enabled(c *check.C) { 352 testRequires(c, IPv6) 353 354 if err := setupV6(); err != nil { 355 c.Fatal("Could not set up host for IPv6 tests") 356 } 357 358 d := NewDaemon(c) 359 360 if err := d.StartWithBusybox("--ipv6"); err != nil { 361 c.Fatal(err) 362 } 363 defer d.Stop() 364 365 iface, err := net.InterfaceByName("docker0") 366 if err != nil { 367 c.Fatalf("Error getting docker0 interface: %v", err) 368 } 369 370 addrs, err := iface.Addrs() 371 if err != nil { 372 c.Fatalf("Error getting addresses for docker0 interface: %v", err) 373 } 374 375 var found bool 376 expected := "fe80::1/64" 377 378 for i := range addrs { 379 if addrs[i].String() == expected { 380 found = true 381 break 382 } 383 } 384 385 if !found { 386 c.Fatalf("Bridge does not have an IPv6 Address") 387 } 388 389 if out, err := d.Cmd("run", "-itd", "--name=ipv6test", "busybox:latest"); err != nil { 390 c.Fatalf("Could not run container: %s, %v", out, err) 391 } 392 393 out, err := d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.LinkLocalIPv6Address}}'", "ipv6test") 394 out = strings.Trim(out, " \r\n'") 395 396 if err != nil { 397 c.Fatalf("Error inspecting container: %s, %v", out, err) 398 } 399 400 if ip := net.ParseIP(out); ip == nil { 401 c.Fatalf("Container should have a link-local IPv6 address") 402 } 403 404 out, err = d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.GlobalIPv6Address}}'", "ipv6test") 405 out = strings.Trim(out, " \r\n'") 406 407 if err != nil { 408 c.Fatalf("Error inspecting container: %s, %v", out, err) 409 } 410 411 if ip := net.ParseIP(out); ip != nil { 412 c.Fatalf("Container should not have a global IPv6 address: %v", out) 413 } 414 415 if err := teardownV6(); err != nil { 416 c.Fatal("Could not perform teardown for IPv6 tests") 417 } 418 419 } 420 421 // TestDaemonIPv6FixedCIDR checks that when the daemon is started with --ipv6=true and a fixed CIDR 422 // that running containers are given a link-local and global IPv6 address 423 func (s *DockerDaemonSuite) TestDaemonIPv6FixedCIDR(c *check.C) { 424 // IPv6 setup is messing with local bridge address. 425 testRequires(c, SameHostDaemon) 426 err := setupV6() 427 c.Assert(err, checker.IsNil, check.Commentf("Could not set up host for IPv6 tests")) 428 429 err = s.d.StartWithBusybox("--ipv6", "--fixed-cidr-v6='2001:db8:2::/64'", "--default-gateway-v6='2001:db8:2::100'") 430 c.Assert(err, checker.IsNil, check.Commentf("Could not start daemon with busybox: %v", err)) 431 432 out, err := s.d.Cmd("run", "-itd", "--name=ipv6test", "busybox:latest") 433 c.Assert(err, checker.IsNil, check.Commentf("Could not run container: %s, %v", out, err)) 434 435 out, err = s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.GlobalIPv6Address}}'", "ipv6test") 436 out = strings.Trim(out, " \r\n'") 437 438 c.Assert(err, checker.IsNil, check.Commentf(out)) 439 440 ip := net.ParseIP(out) 441 c.Assert(ip, checker.NotNil, check.Commentf("Container should have a global IPv6 address")) 442 443 out, err = s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.IPv6Gateway}}'", "ipv6test") 444 c.Assert(err, checker.IsNil, check.Commentf(out)) 445 446 c.Assert(strings.Trim(out, " \r\n'"), checker.Equals, "2001:db8:2::100", check.Commentf("Container should have a global IPv6 gateway")) 447 448 err = teardownV6() 449 c.Assert(err, checker.IsNil, check.Commentf("Could not perform teardown for IPv6 tests")) 450 } 451 452 // TestDaemonIPv6FixedCIDRAndMac checks that when the daemon is started with ipv6 fixed CIDR 453 // the running containers are given an IPv6 address derived from the MAC address and the ipv6 fixed CIDR 454 func (s *DockerDaemonSuite) TestDaemonIPv6FixedCIDRAndMac(c *check.C) { 455 // IPv6 setup is messing with local bridge address. 456 testRequires(c, SameHostDaemon) 457 err := setupV6() 458 c.Assert(err, checker.IsNil) 459 460 err = s.d.StartWithBusybox("--ipv6", "--fixed-cidr-v6='2001:db8:1::/64'") 461 c.Assert(err, checker.IsNil) 462 463 out, err := s.d.Cmd("run", "-itd", "--name=ipv6test", "--mac-address", "AA:BB:CC:DD:EE:FF", "busybox") 464 c.Assert(err, checker.IsNil) 465 466 out, err = s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.GlobalIPv6Address}}'", "ipv6test") 467 c.Assert(err, checker.IsNil) 468 c.Assert(strings.Trim(out, " \r\n'"), checker.Equals, "2001:db8:1::aabb:ccdd:eeff") 469 470 err = teardownV6() 471 c.Assert(err, checker.IsNil) 472 } 473 474 func (s *DockerDaemonSuite) TestDaemonLogLevelWrong(c *check.C) { 475 c.Assert(s.d.Start("--log-level=bogus"), check.NotNil, check.Commentf("Daemon shouldn't start with wrong log level")) 476 } 477 478 func (s *DockerDaemonSuite) TestDaemonLogLevelDebug(c *check.C) { 479 if err := s.d.Start("--log-level=debug"); err != nil { 480 c.Fatal(err) 481 } 482 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 483 if !strings.Contains(string(content), `level=debug`) { 484 c.Fatalf(`Missing level="debug" in log file:\n%s`, string(content)) 485 } 486 } 487 488 func (s *DockerDaemonSuite) TestDaemonLogLevelFatal(c *check.C) { 489 // we creating new daemons to create new logFile 490 if err := s.d.Start("--log-level=fatal"); err != nil { 491 c.Fatal(err) 492 } 493 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 494 if strings.Contains(string(content), `level=debug`) { 495 c.Fatalf(`Should not have level="debug" in log file:\n%s`, string(content)) 496 } 497 } 498 499 func (s *DockerDaemonSuite) TestDaemonFlagD(c *check.C) { 500 if err := s.d.Start("-D"); err != nil { 501 c.Fatal(err) 502 } 503 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 504 if !strings.Contains(string(content), `level=debug`) { 505 c.Fatalf(`Should have level="debug" in log file using -D:\n%s`, string(content)) 506 } 507 } 508 509 func (s *DockerDaemonSuite) TestDaemonFlagDebug(c *check.C) { 510 if err := s.d.Start("--debug"); err != nil { 511 c.Fatal(err) 512 } 513 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 514 if !strings.Contains(string(content), `level=debug`) { 515 c.Fatalf(`Should have level="debug" in log file using --debug:\n%s`, string(content)) 516 } 517 } 518 519 func (s *DockerDaemonSuite) TestDaemonFlagDebugLogLevelFatal(c *check.C) { 520 if err := s.d.Start("--debug", "--log-level=fatal"); err != nil { 521 c.Fatal(err) 522 } 523 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 524 if !strings.Contains(string(content), `level=debug`) { 525 c.Fatalf(`Should have level="debug" in log file when using both --debug and --log-level=fatal:\n%s`, string(content)) 526 } 527 } 528 529 func (s *DockerDaemonSuite) TestDaemonAllocatesListeningPort(c *check.C) { 530 listeningPorts := [][]string{ 531 {"0.0.0.0", "0.0.0.0", "5678"}, 532 {"127.0.0.1", "127.0.0.1", "1234"}, 533 {"localhost", "127.0.0.1", "1235"}, 534 } 535 536 cmdArgs := make([]string, 0, len(listeningPorts)*2) 537 for _, hostDirective := range listeningPorts { 538 cmdArgs = append(cmdArgs, "--host", fmt.Sprintf("tcp://%s:%s", hostDirective[0], hostDirective[2])) 539 } 540 541 if err := s.d.StartWithBusybox(cmdArgs...); err != nil { 542 c.Fatalf("Could not start daemon with busybox: %v", err) 543 } 544 545 for _, hostDirective := range listeningPorts { 546 output, err := s.d.Cmd("run", "-p", fmt.Sprintf("%s:%s:80", hostDirective[1], hostDirective[2]), "busybox", "true") 547 if err == nil { 548 c.Fatalf("Container should not start, expected port already allocated error: %q", output) 549 } else if !strings.Contains(output, "port is already allocated") { 550 c.Fatalf("Expected port is already allocated error: %q", output) 551 } 552 } 553 } 554 555 func (s *DockerDaemonSuite) TestDaemonKeyGeneration(c *check.C) { 556 // TODO: skip or update for Windows daemon 557 os.Remove("/etc/docker/key.json") 558 if err := s.d.Start(); err != nil { 559 c.Fatalf("Could not start daemon: %v", err) 560 } 561 s.d.Stop() 562 563 k, err := libtrust.LoadKeyFile("/etc/docker/key.json") 564 if err != nil { 565 c.Fatalf("Error opening key file") 566 } 567 kid := k.KeyID() 568 // Test Key ID is a valid fingerprint (e.g. QQXN:JY5W:TBXI:MK3X:GX6P:PD5D:F56N:NHCS:LVRZ:JA46:R24J:XEFF) 569 if len(kid) != 59 { 570 c.Fatalf("Bad key ID: %s", kid) 571 } 572 } 573 574 func (s *DockerDaemonSuite) TestDaemonKeyMigration(c *check.C) { 575 // TODO: skip or update for Windows daemon 576 os.Remove("/etc/docker/key.json") 577 k1, err := libtrust.GenerateECP256PrivateKey() 578 if err != nil { 579 c.Fatalf("Error generating private key: %s", err) 580 } 581 if err := os.MkdirAll(filepath.Join(os.Getenv("HOME"), ".docker"), 0755); err != nil { 582 c.Fatalf("Error creating .docker directory: %s", err) 583 } 584 if err := libtrust.SaveKey(filepath.Join(os.Getenv("HOME"), ".docker", "key.json"), k1); err != nil { 585 c.Fatalf("Error saving private key: %s", err) 586 } 587 588 if err := s.d.Start(); err != nil { 589 c.Fatalf("Could not start daemon: %v", err) 590 } 591 s.d.Stop() 592 593 k2, err := libtrust.LoadKeyFile("/etc/docker/key.json") 594 if err != nil { 595 c.Fatalf("Error opening key file") 596 } 597 if k1.KeyID() != k2.KeyID() { 598 c.Fatalf("Key not migrated") 599 } 600 } 601 602 // GH#11320 - verify that the daemon exits on failure properly 603 // Note that this explicitly tests the conflict of {-b,--bridge} and {--bip} options as the means 604 // to get a daemon init failure; no other tests for -b/--bip conflict are therefore required 605 func (s *DockerDaemonSuite) TestDaemonExitOnFailure(c *check.C) { 606 //attempt to start daemon with incorrect flags (we know -b and --bip conflict) 607 if err := s.d.Start("--bridge", "nosuchbridge", "--bip", "1.1.1.1"); err != nil { 608 //verify we got the right error 609 if !strings.Contains(err.Error(), "Daemon exited") { 610 c.Fatalf("Expected daemon not to start, got %v", err) 611 } 612 // look in the log and make sure we got the message that daemon is shutting down 613 runCmd := exec.Command("grep", "Error starting daemon", s.d.LogFileName()) 614 if out, _, err := runCommandWithOutput(runCmd); err != nil { 615 c.Fatalf("Expected 'Error starting daemon' message; but doesn't exist in log: %q, err: %v", out, err) 616 } 617 } else { 618 //if we didn't get an error and the daemon is running, this is a failure 619 c.Fatal("Conflicting options should cause the daemon to error out with a failure") 620 } 621 } 622 623 func (s *DockerDaemonSuite) TestDaemonBridgeExternal(c *check.C) { 624 d := s.d 625 err := d.Start("--bridge", "nosuchbridge") 626 c.Assert(err, check.NotNil, check.Commentf("--bridge option with an invalid bridge should cause the daemon to fail")) 627 defer d.Restart() 628 629 bridgeName := "external-bridge" 630 bridgeIP := "192.169.1.1/24" 631 _, bridgeIPNet, _ := net.ParseCIDR(bridgeIP) 632 633 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 634 c.Assert(err, check.IsNil, check.Commentf(out)) 635 defer deleteInterface(c, bridgeName) 636 637 err = d.StartWithBusybox("--bridge", bridgeName) 638 c.Assert(err, check.IsNil) 639 640 ipTablesSearchString := bridgeIPNet.String() 641 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 642 out, _, err = runCommandWithOutput(ipTablesCmd) 643 c.Assert(err, check.IsNil) 644 645 c.Assert(strings.Contains(out, ipTablesSearchString), check.Equals, true, 646 check.Commentf("iptables output should have contained %q, but was %q", 647 ipTablesSearchString, out)) 648 649 _, err = d.Cmd("run", "-d", "--name", "ExtContainer", "busybox", "top") 650 c.Assert(err, check.IsNil) 651 652 containerIP := d.findContainerIP("ExtContainer") 653 ip := net.ParseIP(containerIP) 654 c.Assert(bridgeIPNet.Contains(ip), check.Equals, true, 655 check.Commentf("Container IP-Address must be in the same subnet range : %s", 656 containerIP)) 657 } 658 659 func createInterface(c *check.C, ifType string, ifName string, ipNet string) (string, error) { 660 args := []string{"link", "add", "name", ifName, "type", ifType} 661 ipLinkCmd := exec.Command("ip", args...) 662 out, _, err := runCommandWithOutput(ipLinkCmd) 663 if err != nil { 664 return out, err 665 } 666 667 ifCfgCmd := exec.Command("ifconfig", ifName, ipNet, "up") 668 out, _, err = runCommandWithOutput(ifCfgCmd) 669 return out, err 670 } 671 672 func deleteInterface(c *check.C, ifName string) { 673 ifCmd := exec.Command("ip", "link", "delete", ifName) 674 out, _, err := runCommandWithOutput(ifCmd) 675 c.Assert(err, check.IsNil, check.Commentf(out)) 676 677 flushCmd := exec.Command("iptables", "-t", "nat", "--flush") 678 out, _, err = runCommandWithOutput(flushCmd) 679 c.Assert(err, check.IsNil, check.Commentf(out)) 680 681 flushCmd = exec.Command("iptables", "--flush") 682 out, _, err = runCommandWithOutput(flushCmd) 683 c.Assert(err, check.IsNil, check.Commentf(out)) 684 } 685 686 func (s *DockerDaemonSuite) TestDaemonBridgeIP(c *check.C) { 687 // TestDaemonBridgeIP Steps 688 // 1. Delete the existing docker0 Bridge 689 // 2. Set --bip daemon configuration and start the new Docker Daemon 690 // 3. Check if the bip config has taken effect using ifconfig and iptables commands 691 // 4. Launch a Container and make sure the IP-Address is in the expected subnet 692 // 5. Delete the docker0 Bridge 693 // 6. Restart the Docker Daemon (via deferred action) 694 // This Restart takes care of bringing docker0 interface back to auto-assigned IP 695 696 defaultNetworkBridge := "docker0" 697 deleteInterface(c, defaultNetworkBridge) 698 699 d := s.d 700 701 bridgeIP := "192.169.1.1/24" 702 ip, bridgeIPNet, _ := net.ParseCIDR(bridgeIP) 703 704 err := d.StartWithBusybox("--bip", bridgeIP) 705 c.Assert(err, check.IsNil) 706 defer d.Restart() 707 708 ifconfigSearchString := ip.String() 709 ifconfigCmd := exec.Command("ifconfig", defaultNetworkBridge) 710 out, _, _, err := runCommandWithStdoutStderr(ifconfigCmd) 711 c.Assert(err, check.IsNil) 712 713 c.Assert(strings.Contains(out, ifconfigSearchString), check.Equals, true, 714 check.Commentf("ifconfig output should have contained %q, but was %q", 715 ifconfigSearchString, out)) 716 717 ipTablesSearchString := bridgeIPNet.String() 718 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 719 out, _, err = runCommandWithOutput(ipTablesCmd) 720 c.Assert(err, check.IsNil) 721 722 c.Assert(strings.Contains(out, ipTablesSearchString), check.Equals, true, 723 check.Commentf("iptables output should have contained %q, but was %q", 724 ipTablesSearchString, out)) 725 726 out, err = d.Cmd("run", "-d", "--name", "test", "busybox", "top") 727 c.Assert(err, check.IsNil) 728 729 containerIP := d.findContainerIP("test") 730 ip = net.ParseIP(containerIP) 731 c.Assert(bridgeIPNet.Contains(ip), check.Equals, true, 732 check.Commentf("Container IP-Address must be in the same subnet range : %s", 733 containerIP)) 734 deleteInterface(c, defaultNetworkBridge) 735 } 736 737 func (s *DockerDaemonSuite) TestDaemonRestartWithBridgeIPChange(c *check.C) { 738 if err := s.d.Start(); err != nil { 739 c.Fatalf("Could not start daemon: %v", err) 740 } 741 defer s.d.Restart() 742 if err := s.d.Stop(); err != nil { 743 c.Fatalf("Could not stop daemon: %v", err) 744 } 745 746 // now we will change the docker0's IP and then try starting the daemon 747 bridgeIP := "192.169.100.1/24" 748 _, bridgeIPNet, _ := net.ParseCIDR(bridgeIP) 749 750 ipCmd := exec.Command("ifconfig", "docker0", bridgeIP) 751 stdout, stderr, _, err := runCommandWithStdoutStderr(ipCmd) 752 if err != nil { 753 c.Fatalf("failed to change docker0's IP association: %v, stdout: %q, stderr: %q", err, stdout, stderr) 754 } 755 756 if err := s.d.Start("--bip", bridgeIP); err != nil { 757 c.Fatalf("Could not start daemon: %v", err) 758 } 759 760 //check if the iptables contains new bridgeIP MASQUERADE rule 761 ipTablesSearchString := bridgeIPNet.String() 762 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 763 out, _, err := runCommandWithOutput(ipTablesCmd) 764 if err != nil { 765 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 766 } 767 if !strings.Contains(out, ipTablesSearchString) { 768 c.Fatalf("iptables output should have contained new MASQUERADE rule with IP %q, but was %q", ipTablesSearchString, out) 769 } 770 } 771 772 func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr(c *check.C) { 773 d := s.d 774 775 bridgeName := "external-bridge" 776 bridgeIP := "192.169.1.1/24" 777 778 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 779 c.Assert(err, check.IsNil, check.Commentf(out)) 780 defer deleteInterface(c, bridgeName) 781 782 args := []string{"--bridge", bridgeName, "--fixed-cidr", "192.169.1.0/30"} 783 err = d.StartWithBusybox(args...) 784 c.Assert(err, check.IsNil) 785 defer d.Restart() 786 787 for i := 0; i < 4; i++ { 788 cName := "Container" + strconv.Itoa(i) 789 out, err := d.Cmd("run", "-d", "--name", cName, "busybox", "top") 790 if err != nil { 791 c.Assert(strings.Contains(out, "no available IPv4 addresses"), check.Equals, true, 792 check.Commentf("Could not run a Container : %s %s", err.Error(), out)) 793 } 794 } 795 } 796 797 func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr2(c *check.C) { 798 d := s.d 799 800 bridgeName := "external-bridge" 801 bridgeIP := "10.2.2.1/16" 802 803 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 804 c.Assert(err, check.IsNil, check.Commentf(out)) 805 defer deleteInterface(c, bridgeName) 806 807 err = d.StartWithBusybox("--bip", bridgeIP, "--fixed-cidr", "10.2.2.0/24") 808 c.Assert(err, check.IsNil) 809 defer s.d.Restart() 810 811 out, err = d.Cmd("run", "-d", "--name", "bb", "busybox", "top") 812 c.Assert(err, checker.IsNil, check.Commentf(out)) 813 defer d.Cmd("stop", "bb") 814 815 out, err = d.Cmd("exec", "bb", "/bin/sh", "-c", "ifconfig eth0 | awk '/inet addr/{print substr($2,6)}'") 816 c.Assert(out, checker.Equals, "10.2.2.0\n") 817 818 out, err = d.Cmd("run", "--rm", "busybox", "/bin/sh", "-c", "ifconfig eth0 | awk '/inet addr/{print substr($2,6)}'") 819 c.Assert(err, checker.IsNil, check.Commentf(out)) 820 c.Assert(out, checker.Equals, "10.2.2.2\n") 821 } 822 823 func (s *DockerDaemonSuite) TestDaemonBridgeFixedCIDREqualBridgeNetwork(c *check.C) { 824 d := s.d 825 826 bridgeName := "external-bridge" 827 bridgeIP := "172.27.42.1/16" 828 829 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 830 c.Assert(err, check.IsNil, check.Commentf(out)) 831 defer deleteInterface(c, bridgeName) 832 833 err = d.StartWithBusybox("--bridge", bridgeName, "--fixed-cidr", bridgeIP) 834 c.Assert(err, check.IsNil) 835 defer s.d.Restart() 836 837 out, err = d.Cmd("run", "-d", "busybox", "top") 838 c.Assert(err, check.IsNil, check.Commentf(out)) 839 cid1 := strings.TrimSpace(out) 840 defer d.Cmd("stop", cid1) 841 } 842 843 func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4Implicit(c *check.C) { 844 defaultNetworkBridge := "docker0" 845 deleteInterface(c, defaultNetworkBridge) 846 847 d := s.d 848 849 bridgeIP := "192.169.1.1" 850 bridgeIPNet := fmt.Sprintf("%s/24", bridgeIP) 851 852 err := d.StartWithBusybox("--bip", bridgeIPNet) 853 c.Assert(err, check.IsNil) 854 defer d.Restart() 855 856 expectedMessage := fmt.Sprintf("default via %s dev", bridgeIP) 857 out, err := d.Cmd("run", "busybox", "ip", "-4", "route", "list", "0/0") 858 c.Assert(strings.Contains(out, expectedMessage), check.Equals, true, 859 check.Commentf("Implicit default gateway should be bridge IP %s, but default route was '%s'", 860 bridgeIP, strings.TrimSpace(out))) 861 deleteInterface(c, defaultNetworkBridge) 862 } 863 864 func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4Explicit(c *check.C) { 865 defaultNetworkBridge := "docker0" 866 deleteInterface(c, defaultNetworkBridge) 867 868 d := s.d 869 870 bridgeIP := "192.169.1.1" 871 bridgeIPNet := fmt.Sprintf("%s/24", bridgeIP) 872 gatewayIP := "192.169.1.254" 873 874 err := d.StartWithBusybox("--bip", bridgeIPNet, "--default-gateway", gatewayIP) 875 c.Assert(err, check.IsNil) 876 defer d.Restart() 877 878 expectedMessage := fmt.Sprintf("default via %s dev", gatewayIP) 879 out, err := d.Cmd("run", "busybox", "ip", "-4", "route", "list", "0/0") 880 c.Assert(strings.Contains(out, expectedMessage), check.Equals, true, 881 check.Commentf("Explicit default gateway should be %s, but default route was '%s'", 882 gatewayIP, strings.TrimSpace(out))) 883 deleteInterface(c, defaultNetworkBridge) 884 } 885 886 func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4ExplicitOutsideContainerSubnet(c *check.C) { 887 defaultNetworkBridge := "docker0" 888 deleteInterface(c, defaultNetworkBridge) 889 890 // Program a custom default gateway outside of the container subnet, daemon should accept it and start 891 err := s.d.StartWithBusybox("--bip", "172.16.0.10/16", "--fixed-cidr", "172.16.1.0/24", "--default-gateway", "172.16.0.254") 892 c.Assert(err, check.IsNil) 893 894 deleteInterface(c, defaultNetworkBridge) 895 s.d.Restart() 896 } 897 898 func (s *DockerDaemonSuite) TestDaemonDefaultNetworkInvalidClusterConfig(c *check.C) { 899 testRequires(c, DaemonIsLinux, SameHostDaemon) 900 901 // Start daemon without docker0 bridge 902 defaultNetworkBridge := "docker0" 903 deleteInterface(c, defaultNetworkBridge) 904 905 d := NewDaemon(c) 906 discoveryBackend := "consul://consuladdr:consulport/some/path" 907 err := d.Start(fmt.Sprintf("--cluster-store=%s", discoveryBackend)) 908 c.Assert(err, checker.IsNil) 909 910 // Start daemon with docker0 bridge 911 ifconfigCmd := exec.Command("ifconfig", defaultNetworkBridge) 912 _, err = runCommand(ifconfigCmd) 913 c.Assert(err, check.IsNil) 914 915 err = d.Restart(fmt.Sprintf("--cluster-store=%s", discoveryBackend)) 916 c.Assert(err, checker.IsNil) 917 918 d.Stop() 919 } 920 921 func (s *DockerDaemonSuite) TestDaemonIP(c *check.C) { 922 d := s.d 923 924 ipStr := "192.170.1.1/24" 925 ip, _, _ := net.ParseCIDR(ipStr) 926 args := []string{"--ip", ip.String()} 927 err := d.StartWithBusybox(args...) 928 c.Assert(err, check.IsNil) 929 defer d.Restart() 930 931 out, err := d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top") 932 c.Assert(err, check.NotNil, 933 check.Commentf("Running a container must fail with an invalid --ip option")) 934 c.Assert(strings.Contains(out, "Error starting userland proxy"), check.Equals, true) 935 936 ifName := "dummy" 937 out, err = createInterface(c, "dummy", ifName, ipStr) 938 c.Assert(err, check.IsNil, check.Commentf(out)) 939 defer deleteInterface(c, ifName) 940 941 _, err = d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top") 942 c.Assert(err, check.IsNil) 943 944 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 945 out, _, err = runCommandWithOutput(ipTablesCmd) 946 c.Assert(err, check.IsNil) 947 948 regex := fmt.Sprintf("DNAT.*%s.*dpt:8000", ip.String()) 949 matched, _ := regexp.MatchString(regex, out) 950 c.Assert(matched, check.Equals, true, 951 check.Commentf("iptables output should have contained %q, but was %q", regex, out)) 952 } 953 954 func (s *DockerDaemonSuite) TestDaemonICCPing(c *check.C) { 955 testRequires(c, bridgeNfIptables) 956 d := s.d 957 958 bridgeName := "external-bridge" 959 bridgeIP := "192.169.1.1/24" 960 961 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 962 c.Assert(err, check.IsNil, check.Commentf(out)) 963 defer deleteInterface(c, bridgeName) 964 965 args := []string{"--bridge", bridgeName, "--icc=false"} 966 err = d.StartWithBusybox(args...) 967 c.Assert(err, check.IsNil) 968 defer d.Restart() 969 970 ipTablesCmd := exec.Command("iptables", "-nvL", "FORWARD") 971 out, _, err = runCommandWithOutput(ipTablesCmd) 972 c.Assert(err, check.IsNil) 973 974 regex := fmt.Sprintf("DROP.*all.*%s.*%s", bridgeName, bridgeName) 975 matched, _ := regexp.MatchString(regex, out) 976 c.Assert(matched, check.Equals, true, 977 check.Commentf("iptables output should have contained %q, but was %q", regex, out)) 978 979 // Pinging another container must fail with --icc=false 980 pingContainers(c, d, true) 981 982 ipStr := "192.171.1.1/24" 983 ip, _, _ := net.ParseCIDR(ipStr) 984 ifName := "icc-dummy" 985 986 createInterface(c, "dummy", ifName, ipStr) 987 988 // But, Pinging external or a Host interface must succeed 989 pingCmd := fmt.Sprintf("ping -c 1 %s -W 1", ip.String()) 990 runArgs := []string{"run", "--rm", "busybox", "sh", "-c", pingCmd} 991 _, err = d.Cmd(runArgs...) 992 c.Assert(err, check.IsNil) 993 } 994 995 func (s *DockerDaemonSuite) TestDaemonICCLinkExpose(c *check.C) { 996 d := s.d 997 998 bridgeName := "external-bridge" 999 bridgeIP := "192.169.1.1/24" 1000 1001 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 1002 c.Assert(err, check.IsNil, check.Commentf(out)) 1003 defer deleteInterface(c, bridgeName) 1004 1005 args := []string{"--bridge", bridgeName, "--icc=false"} 1006 err = d.StartWithBusybox(args...) 1007 c.Assert(err, check.IsNil) 1008 defer d.Restart() 1009 1010 ipTablesCmd := exec.Command("iptables", "-nvL", "FORWARD") 1011 out, _, err = runCommandWithOutput(ipTablesCmd) 1012 c.Assert(err, check.IsNil) 1013 1014 regex := fmt.Sprintf("DROP.*all.*%s.*%s", bridgeName, bridgeName) 1015 matched, _ := regexp.MatchString(regex, out) 1016 c.Assert(matched, check.Equals, true, 1017 check.Commentf("iptables output should have contained %q, but was %q", regex, out)) 1018 1019 out, err = d.Cmd("run", "-d", "--expose", "4567", "--name", "icc1", "busybox", "nc", "-l", "-p", "4567") 1020 c.Assert(err, check.IsNil, check.Commentf(out)) 1021 1022 out, err = d.Cmd("run", "--link", "icc1:icc1", "busybox", "nc", "icc1", "4567") 1023 c.Assert(err, check.IsNil, check.Commentf(out)) 1024 } 1025 1026 func (s *DockerDaemonSuite) TestDaemonLinksIpTablesRulesWhenLinkAndUnlink(c *check.C) { 1027 bridgeName := "external-bridge" 1028 bridgeIP := "192.169.1.1/24" 1029 1030 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 1031 c.Assert(err, check.IsNil, check.Commentf(out)) 1032 defer deleteInterface(c, bridgeName) 1033 1034 err = s.d.StartWithBusybox("--bridge", bridgeName, "--icc=false") 1035 c.Assert(err, check.IsNil) 1036 defer s.d.Restart() 1037 1038 _, err = s.d.Cmd("run", "-d", "--name", "child", "--publish", "8080:80", "busybox", "top") 1039 c.Assert(err, check.IsNil) 1040 _, err = s.d.Cmd("run", "-d", "--name", "parent", "--link", "child:http", "busybox", "top") 1041 c.Assert(err, check.IsNil) 1042 1043 childIP := s.d.findContainerIP("child") 1044 parentIP := s.d.findContainerIP("parent") 1045 1046 sourceRule := []string{"-i", bridgeName, "-o", bridgeName, "-p", "tcp", "-s", childIP, "--sport", "80", "-d", parentIP, "-j", "ACCEPT"} 1047 destinationRule := []string{"-i", bridgeName, "-o", bridgeName, "-p", "tcp", "-s", parentIP, "--dport", "80", "-d", childIP, "-j", "ACCEPT"} 1048 if !iptables.Exists("filter", "DOCKER", sourceRule...) || !iptables.Exists("filter", "DOCKER", destinationRule...) { 1049 c.Fatal("Iptables rules not found") 1050 } 1051 1052 s.d.Cmd("rm", "--link", "parent/http") 1053 if iptables.Exists("filter", "DOCKER", sourceRule...) || iptables.Exists("filter", "DOCKER", destinationRule...) { 1054 c.Fatal("Iptables rules should be removed when unlink") 1055 } 1056 1057 s.d.Cmd("kill", "child") 1058 s.d.Cmd("kill", "parent") 1059 } 1060 1061 func (s *DockerDaemonSuite) TestDaemonUlimitDefaults(c *check.C) { 1062 testRequires(c, DaemonIsLinux) 1063 1064 if err := s.d.StartWithBusybox("--default-ulimit", "nofile=42:42", "--default-ulimit", "nproc=1024:1024"); err != nil { 1065 c.Fatal(err) 1066 } 1067 1068 out, err := s.d.Cmd("run", "--ulimit", "nproc=2048", "--name=test", "busybox", "/bin/sh", "-c", "echo $(ulimit -n); echo $(ulimit -p)") 1069 if err != nil { 1070 c.Fatal(out, err) 1071 } 1072 1073 outArr := strings.Split(out, "\n") 1074 if len(outArr) < 2 { 1075 c.Fatalf("got unexpected output: %s", out) 1076 } 1077 nofile := strings.TrimSpace(outArr[0]) 1078 nproc := strings.TrimSpace(outArr[1]) 1079 1080 if nofile != "42" { 1081 c.Fatalf("expected `ulimit -n` to be `42`, got: %s", nofile) 1082 } 1083 if nproc != "2048" { 1084 c.Fatalf("exepcted `ulimit -p` to be 2048, got: %s", nproc) 1085 } 1086 1087 // Now restart daemon with a new default 1088 if err := s.d.Restart("--default-ulimit", "nofile=43"); err != nil { 1089 c.Fatal(err) 1090 } 1091 1092 out, err = s.d.Cmd("start", "-a", "test") 1093 if err != nil { 1094 c.Fatal(err) 1095 } 1096 1097 outArr = strings.Split(out, "\n") 1098 if len(outArr) < 2 { 1099 c.Fatalf("got unexpected output: %s", out) 1100 } 1101 nofile = strings.TrimSpace(outArr[0]) 1102 nproc = strings.TrimSpace(outArr[1]) 1103 1104 if nofile != "43" { 1105 c.Fatalf("expected `ulimit -n` to be `43`, got: %s", nofile) 1106 } 1107 if nproc != "2048" { 1108 c.Fatalf("exepcted `ulimit -p` to be 2048, got: %s", nproc) 1109 } 1110 } 1111 1112 // #11315 1113 func (s *DockerDaemonSuite) TestDaemonRestartRenameContainer(c *check.C) { 1114 if err := s.d.StartWithBusybox(); err != nil { 1115 c.Fatal(err) 1116 } 1117 1118 if out, err := s.d.Cmd("run", "--name=test", "busybox"); err != nil { 1119 c.Fatal(err, out) 1120 } 1121 1122 if out, err := s.d.Cmd("rename", "test", "test2"); err != nil { 1123 c.Fatal(err, out) 1124 } 1125 1126 if err := s.d.Restart(); err != nil { 1127 c.Fatal(err) 1128 } 1129 1130 if out, err := s.d.Cmd("start", "test2"); err != nil { 1131 c.Fatal(err, out) 1132 } 1133 } 1134 1135 func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefault(c *check.C) { 1136 if err := s.d.StartWithBusybox(); err != nil { 1137 c.Fatal(err) 1138 } 1139 1140 out, err := s.d.Cmd("run", "--name=test", "busybox", "echo", "testline") 1141 c.Assert(err, check.IsNil, check.Commentf(out)) 1142 id, err := s.d.getIDByName("test") 1143 c.Assert(err, check.IsNil) 1144 1145 logPath := filepath.Join(s.d.root, "containers", id, id+"-json.log") 1146 1147 if _, err := os.Stat(logPath); err != nil { 1148 c.Fatal(err) 1149 } 1150 f, err := os.Open(logPath) 1151 if err != nil { 1152 c.Fatal(err) 1153 } 1154 var res struct { 1155 Log string `json:"log"` 1156 Stream string `json:"stream"` 1157 Time time.Time `json:"time"` 1158 } 1159 if err := json.NewDecoder(f).Decode(&res); err != nil { 1160 c.Fatal(err) 1161 } 1162 if res.Log != "testline\n" { 1163 c.Fatalf("Unexpected log line: %q, expected: %q", res.Log, "testline\n") 1164 } 1165 if res.Stream != "stdout" { 1166 c.Fatalf("Unexpected stream: %q, expected: %q", res.Stream, "stdout") 1167 } 1168 if !time.Now().After(res.Time) { 1169 c.Fatalf("Log time %v in future", res.Time) 1170 } 1171 } 1172 1173 func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefaultOverride(c *check.C) { 1174 if err := s.d.StartWithBusybox(); err != nil { 1175 c.Fatal(err) 1176 } 1177 1178 out, err := s.d.Cmd("run", "--name=test", "--log-driver=none", "busybox", "echo", "testline") 1179 if err != nil { 1180 c.Fatal(out, err) 1181 } 1182 id, err := s.d.getIDByName("test") 1183 c.Assert(err, check.IsNil) 1184 1185 logPath := filepath.Join(s.d.root, "containers", id, id+"-json.log") 1186 1187 if _, err := os.Stat(logPath); err == nil || !os.IsNotExist(err) { 1188 c.Fatalf("%s shouldn't exits, error on Stat: %s", logPath, err) 1189 } 1190 } 1191 1192 func (s *DockerDaemonSuite) TestDaemonLoggingDriverNone(c *check.C) { 1193 if err := s.d.StartWithBusybox("--log-driver=none"); err != nil { 1194 c.Fatal(err) 1195 } 1196 1197 out, err := s.d.Cmd("run", "--name=test", "busybox", "echo", "testline") 1198 if err != nil { 1199 c.Fatal(out, err) 1200 } 1201 id, err := s.d.getIDByName("test") 1202 c.Assert(err, check.IsNil) 1203 1204 logPath := filepath.Join(s.d.folder, "graph", "containers", id, id+"-json.log") 1205 1206 if _, err := os.Stat(logPath); err == nil || !os.IsNotExist(err) { 1207 c.Fatalf("%s shouldn't exits, error on Stat: %s", logPath, err) 1208 } 1209 } 1210 1211 func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneOverride(c *check.C) { 1212 if err := s.d.StartWithBusybox("--log-driver=none"); err != nil { 1213 c.Fatal(err) 1214 } 1215 1216 out, err := s.d.Cmd("run", "--name=test", "--log-driver=json-file", "busybox", "echo", "testline") 1217 if err != nil { 1218 c.Fatal(out, err) 1219 } 1220 id, err := s.d.getIDByName("test") 1221 c.Assert(err, check.IsNil) 1222 1223 logPath := filepath.Join(s.d.root, "containers", id, id+"-json.log") 1224 1225 if _, err := os.Stat(logPath); err != nil { 1226 c.Fatal(err) 1227 } 1228 f, err := os.Open(logPath) 1229 if err != nil { 1230 c.Fatal(err) 1231 } 1232 var res struct { 1233 Log string `json:"log"` 1234 Stream string `json:"stream"` 1235 Time time.Time `json:"time"` 1236 } 1237 if err := json.NewDecoder(f).Decode(&res); err != nil { 1238 c.Fatal(err) 1239 } 1240 if res.Log != "testline\n" { 1241 c.Fatalf("Unexpected log line: %q, expected: %q", res.Log, "testline\n") 1242 } 1243 if res.Stream != "stdout" { 1244 c.Fatalf("Unexpected stream: %q, expected: %q", res.Stream, "stdout") 1245 } 1246 if !time.Now().After(res.Time) { 1247 c.Fatalf("Log time %v in future", res.Time) 1248 } 1249 } 1250 1251 func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneLogsError(c *check.C) { 1252 c.Assert(s.d.StartWithBusybox("--log-driver=none"), checker.IsNil) 1253 1254 out, err := s.d.Cmd("run", "--name=test", "busybox", "echo", "testline") 1255 c.Assert(err, checker.IsNil, check.Commentf(out)) 1256 1257 out, err = s.d.Cmd("logs", "test") 1258 c.Assert(err, check.NotNil, check.Commentf("Logs should fail with 'none' driver")) 1259 expected := `"logs" command is supported only for "json-file" and "journald" logging drivers (got: none)` 1260 c.Assert(out, checker.Contains, expected) 1261 } 1262 1263 func (s *DockerDaemonSuite) TestDaemonDots(c *check.C) { 1264 if err := s.d.StartWithBusybox(); err != nil { 1265 c.Fatal(err) 1266 } 1267 1268 // Now create 4 containers 1269 if _, err := s.d.Cmd("create", "busybox"); err != nil { 1270 c.Fatalf("Error creating container: %q", err) 1271 } 1272 if _, err := s.d.Cmd("create", "busybox"); err != nil { 1273 c.Fatalf("Error creating container: %q", err) 1274 } 1275 if _, err := s.d.Cmd("create", "busybox"); err != nil { 1276 c.Fatalf("Error creating container: %q", err) 1277 } 1278 if _, err := s.d.Cmd("create", "busybox"); err != nil { 1279 c.Fatalf("Error creating container: %q", err) 1280 } 1281 1282 s.d.Stop() 1283 1284 s.d.Start("--log-level=debug") 1285 s.d.Stop() 1286 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 1287 if strings.Contains(string(content), "....") { 1288 c.Fatalf("Debug level should not have ....\n%s", string(content)) 1289 } 1290 1291 s.d.Start("--log-level=error") 1292 s.d.Stop() 1293 content, _ = ioutil.ReadFile(s.d.logFile.Name()) 1294 if strings.Contains(string(content), "....") { 1295 c.Fatalf("Error level should not have ....\n%s", string(content)) 1296 } 1297 1298 s.d.Start("--log-level=info") 1299 s.d.Stop() 1300 content, _ = ioutil.ReadFile(s.d.logFile.Name()) 1301 if !strings.Contains(string(content), "....") { 1302 c.Fatalf("Info level should have ....\n%s", string(content)) 1303 } 1304 } 1305 1306 func (s *DockerDaemonSuite) TestDaemonUnixSockCleanedUp(c *check.C) { 1307 dir, err := ioutil.TempDir("", "socket-cleanup-test") 1308 if err != nil { 1309 c.Fatal(err) 1310 } 1311 defer os.RemoveAll(dir) 1312 1313 sockPath := filepath.Join(dir, "docker.sock") 1314 if err := s.d.Start("--host", "unix://"+sockPath); err != nil { 1315 c.Fatal(err) 1316 } 1317 1318 if _, err := os.Stat(sockPath); err != nil { 1319 c.Fatal("socket does not exist") 1320 } 1321 1322 if err := s.d.Stop(); err != nil { 1323 c.Fatal(err) 1324 } 1325 1326 if _, err := os.Stat(sockPath); err == nil || !os.IsNotExist(err) { 1327 c.Fatal("unix socket is not cleaned up") 1328 } 1329 } 1330 1331 func (s *DockerDaemonSuite) TestDaemonWithWrongkey(c *check.C) { 1332 type Config struct { 1333 Crv string `json:"crv"` 1334 D string `json:"d"` 1335 Kid string `json:"kid"` 1336 Kty string `json:"kty"` 1337 X string `json:"x"` 1338 Y string `json:"y"` 1339 } 1340 1341 os.Remove("/etc/docker/key.json") 1342 if err := s.d.Start(); err != nil { 1343 c.Fatalf("Failed to start daemon: %v", err) 1344 } 1345 1346 if err := s.d.Stop(); err != nil { 1347 c.Fatalf("Could not stop daemon: %v", err) 1348 } 1349 1350 config := &Config{} 1351 bytes, err := ioutil.ReadFile("/etc/docker/key.json") 1352 if err != nil { 1353 c.Fatalf("Error reading key.json file: %s", err) 1354 } 1355 1356 // byte[] to Data-Struct 1357 if err := json.Unmarshal(bytes, &config); err != nil { 1358 c.Fatalf("Error Unmarshal: %s", err) 1359 } 1360 1361 //replace config.Kid with the fake value 1362 config.Kid = "VSAJ:FUYR:X3H2:B2VZ:KZ6U:CJD5:K7BX:ZXHY:UZXT:P4FT:MJWG:HRJ4" 1363 1364 // NEW Data-Struct to byte[] 1365 newBytes, err := json.Marshal(&config) 1366 if err != nil { 1367 c.Fatalf("Error Marshal: %s", err) 1368 } 1369 1370 // write back 1371 if err := ioutil.WriteFile("/etc/docker/key.json", newBytes, 0400); err != nil { 1372 c.Fatalf("Error ioutil.WriteFile: %s", err) 1373 } 1374 1375 defer os.Remove("/etc/docker/key.json") 1376 1377 if err := s.d.Start(); err == nil { 1378 c.Fatalf("It should not be successful to start daemon with wrong key: %v", err) 1379 } 1380 1381 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 1382 1383 if !strings.Contains(string(content), "Public Key ID does not match") { 1384 c.Fatal("Missing KeyID message from daemon logs") 1385 } 1386 } 1387 1388 func (s *DockerDaemonSuite) TestDaemonRestartKillWait(c *check.C) { 1389 if err := s.d.StartWithBusybox(); err != nil { 1390 c.Fatalf("Could not start daemon with busybox: %v", err) 1391 } 1392 1393 out, err := s.d.Cmd("run", "-id", "busybox", "/bin/cat") 1394 if err != nil { 1395 c.Fatalf("Could not run /bin/cat: err=%v\n%s", err, out) 1396 } 1397 containerID := strings.TrimSpace(out) 1398 1399 if out, err := s.d.Cmd("kill", containerID); err != nil { 1400 c.Fatalf("Could not kill %s: err=%v\n%s", containerID, err, out) 1401 } 1402 1403 if err := s.d.Restart(); err != nil { 1404 c.Fatalf("Could not restart daemon: %v", err) 1405 } 1406 1407 errchan := make(chan error) 1408 go func() { 1409 if out, err := s.d.Cmd("wait", containerID); err != nil { 1410 errchan <- fmt.Errorf("%v:\n%s", err, out) 1411 } 1412 close(errchan) 1413 }() 1414 1415 select { 1416 case <-time.After(5 * time.Second): 1417 c.Fatal("Waiting on a stopped (killed) container timed out") 1418 case err := <-errchan: 1419 if err != nil { 1420 c.Fatal(err) 1421 } 1422 } 1423 } 1424 1425 // TestHttpsInfo connects via two-way authenticated HTTPS to the info endpoint 1426 func (s *DockerDaemonSuite) TestHttpsInfo(c *check.C) { 1427 const ( 1428 testDaemonHTTPSAddr = "tcp://localhost:4271" 1429 ) 1430 1431 if err := s.d.Start("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-cert.pem", 1432 "--tlskey", "fixtures/https/server-key.pem", "-H", testDaemonHTTPSAddr); err != nil { 1433 c.Fatalf("Could not start daemon with busybox: %v", err) 1434 } 1435 1436 args := []string{ 1437 "--host", testDaemonHTTPSAddr, 1438 "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", 1439 "--tlscert", "fixtures/https/client-cert.pem", 1440 "--tlskey", "fixtures/https/client-key.pem", 1441 "info", 1442 } 1443 out, err := s.d.Cmd(args...) 1444 if err != nil { 1445 c.Fatalf("Error Occurred: %s and output: %s", err, out) 1446 } 1447 } 1448 1449 // TestHttpsRun connects via two-way authenticated HTTPS to the create, attach, start, and wait endpoints. 1450 // https://github.com/docker/docker/issues/19280 1451 func (s *DockerDaemonSuite) TestHttpsRun(c *check.C) { 1452 const ( 1453 testDaemonHTTPSAddr = "tcp://localhost:4271" 1454 ) 1455 1456 if err := s.d.StartWithBusybox("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-cert.pem", 1457 "--tlskey", "fixtures/https/server-key.pem", "-H", testDaemonHTTPSAddr); err != nil { 1458 c.Fatalf("Could not start daemon with busybox: %v", err) 1459 } 1460 1461 args := []string{ 1462 "--host", testDaemonHTTPSAddr, 1463 "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", 1464 "--tlscert", "fixtures/https/client-cert.pem", 1465 "--tlskey", "fixtures/https/client-key.pem", 1466 "run", "busybox", "echo", "TLS response", 1467 } 1468 out, err := s.d.Cmd(args...) 1469 if err != nil { 1470 c.Fatalf("Error Occurred: %s and output: %s", err, out) 1471 } 1472 1473 if !strings.Contains(out, "TLS response") { 1474 c.Fatalf("expected output to include `TLS response`, got %v", out) 1475 } 1476 } 1477 1478 // TestTlsVerify verifies that --tlsverify=false turns on tls 1479 func (s *DockerDaemonSuite) TestTlsVerify(c *check.C) { 1480 out, err := exec.Command(dockerdBinary, "--tlsverify=false").CombinedOutput() 1481 if err == nil || !strings.Contains(string(out), "Could not load X509 key pair") { 1482 c.Fatalf("Daemon should not have started due to missing certs: %v\n%s", err, string(out)) 1483 } 1484 } 1485 1486 // TestHttpsInfoRogueCert connects via two-way authenticated HTTPS to the info endpoint 1487 // by using a rogue client certificate and checks that it fails with the expected error. 1488 func (s *DockerDaemonSuite) TestHttpsInfoRogueCert(c *check.C) { 1489 const ( 1490 errBadCertificate = "bad certificate" 1491 testDaemonHTTPSAddr = "tcp://localhost:4271" 1492 ) 1493 1494 if err := s.d.Start("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-cert.pem", 1495 "--tlskey", "fixtures/https/server-key.pem", "-H", testDaemonHTTPSAddr); err != nil { 1496 c.Fatalf("Could not start daemon with busybox: %v", err) 1497 } 1498 1499 args := []string{ 1500 "--host", testDaemonHTTPSAddr, 1501 "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", 1502 "--tlscert", "fixtures/https/client-rogue-cert.pem", 1503 "--tlskey", "fixtures/https/client-rogue-key.pem", 1504 "info", 1505 } 1506 out, err := s.d.Cmd(args...) 1507 if err == nil || !strings.Contains(out, errBadCertificate) { 1508 c.Fatalf("Expected err: %s, got instead: %s and output: %s", errBadCertificate, err, out) 1509 } 1510 } 1511 1512 // TestHttpsInfoRogueServerCert connects via two-way authenticated HTTPS to the info endpoint 1513 // which provides a rogue server certificate and checks that it fails with the expected error 1514 func (s *DockerDaemonSuite) TestHttpsInfoRogueServerCert(c *check.C) { 1515 const ( 1516 errCaUnknown = "x509: certificate signed by unknown authority" 1517 testDaemonRogueHTTPSAddr = "tcp://localhost:4272" 1518 ) 1519 if err := s.d.Start("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-rogue-cert.pem", 1520 "--tlskey", "fixtures/https/server-rogue-key.pem", "-H", testDaemonRogueHTTPSAddr); err != nil { 1521 c.Fatalf("Could not start daemon with busybox: %v", err) 1522 } 1523 1524 args := []string{ 1525 "--host", testDaemonRogueHTTPSAddr, 1526 "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", 1527 "--tlscert", "fixtures/https/client-rogue-cert.pem", 1528 "--tlskey", "fixtures/https/client-rogue-key.pem", 1529 "info", 1530 } 1531 out, err := s.d.Cmd(args...) 1532 if err == nil || !strings.Contains(out, errCaUnknown) { 1533 c.Fatalf("Expected err: %s, got instead: %s and output: %s", errCaUnknown, err, out) 1534 } 1535 } 1536 1537 func pingContainers(c *check.C, d *Daemon, expectFailure bool) { 1538 var dargs []string 1539 if d != nil { 1540 dargs = []string{"--host", d.sock()} 1541 } 1542 1543 args := append(dargs, "run", "-d", "--name", "container1", "busybox", "top") 1544 dockerCmd(c, args...) 1545 1546 args = append(dargs, "run", "--rm", "--link", "container1:alias1", "busybox", "sh", "-c") 1547 pingCmd := "ping -c 1 %s -W 1" 1548 args = append(args, fmt.Sprintf(pingCmd, "alias1")) 1549 _, _, err := dockerCmdWithError(args...) 1550 1551 if expectFailure { 1552 c.Assert(err, check.NotNil) 1553 } else { 1554 c.Assert(err, check.IsNil) 1555 } 1556 1557 args = append(dargs, "rm", "-f", "container1") 1558 dockerCmd(c, args...) 1559 } 1560 1561 func (s *DockerDaemonSuite) TestDaemonRestartWithSocketAsVolume(c *check.C) { 1562 c.Assert(s.d.StartWithBusybox(), check.IsNil) 1563 1564 socket := filepath.Join(s.d.folder, "docker.sock") 1565 1566 out, err := s.d.Cmd("run", "--restart=always", "-v", socket+":/sock", "busybox") 1567 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1568 c.Assert(s.d.Restart(), check.IsNil) 1569 } 1570 1571 // os.Kill should kill daemon ungracefully, leaving behind container mounts. 1572 // A subsequent daemon restart shoud clean up said mounts. 1573 func (s *DockerDaemonSuite) TestCleanupMountsAfterDaemonAndContainerKill(c *check.C) { 1574 c.Assert(s.d.StartWithBusybox(), check.IsNil) 1575 1576 out, err := s.d.Cmd("run", "-d", "busybox", "top") 1577 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1578 id := strings.TrimSpace(out) 1579 c.Assert(s.d.cmd.Process.Signal(os.Kill), check.IsNil) 1580 mountOut, err := ioutil.ReadFile("/proc/self/mountinfo") 1581 c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut)) 1582 1583 // container mounts should exist even after daemon has crashed. 1584 comment := check.Commentf("%s should stay mounted from older daemon start:\nDaemon root repository %s\n%s", id, s.d.folder, mountOut) 1585 c.Assert(strings.Contains(string(mountOut), id), check.Equals, true, comment) 1586 1587 // kill the container 1588 runCmd := exec.Command(ctrBinary, "--address", "unix:///var/run/docker/libcontainerd/docker-containerd.sock", "containers", "kill", id) 1589 if out, ec, err := runCommandWithOutput(runCmd); err != nil { 1590 c.Fatalf("Failed to run ctr, ExitCode: %d, err: %v output: %s id: %s\n", ec, err, out, id) 1591 } 1592 1593 // restart daemon. 1594 if err := s.d.Restart(); err != nil { 1595 c.Fatal(err) 1596 } 1597 1598 // Now, container mounts should be gone. 1599 mountOut, err = ioutil.ReadFile("/proc/self/mountinfo") 1600 c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut)) 1601 comment = check.Commentf("%s is still mounted from older daemon start:\nDaemon root repository %s\n%s", id, s.d.folder, mountOut) 1602 c.Assert(strings.Contains(string(mountOut), id), check.Equals, false, comment) 1603 } 1604 1605 // os.Interrupt should perform a graceful daemon shutdown and hence cleanup mounts. 1606 func (s *DockerDaemonSuite) TestCleanupMountsAfterGracefulShutdown(c *check.C) { 1607 c.Assert(s.d.StartWithBusybox(), check.IsNil) 1608 1609 out, err := s.d.Cmd("run", "-d", "busybox", "top") 1610 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1611 id := strings.TrimSpace(out) 1612 1613 // Send SIGINT and daemon should clean up 1614 c.Assert(s.d.cmd.Process.Signal(os.Interrupt), check.IsNil) 1615 // Wait for the daemon to stop. 1616 c.Assert(<-s.d.wait, checker.IsNil) 1617 1618 mountOut, err := ioutil.ReadFile("/proc/self/mountinfo") 1619 c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut)) 1620 1621 comment := check.Commentf("%s is still mounted from older daemon start:\nDaemon root repository %s\n%s", id, s.d.folder, mountOut) 1622 c.Assert(strings.Contains(string(mountOut), id), check.Equals, false, comment) 1623 } 1624 1625 func (s *DockerDaemonSuite) TestRunContainerWithBridgeNone(c *check.C) { 1626 testRequires(c, DaemonIsLinux, NotUserNamespace) 1627 c.Assert(s.d.StartWithBusybox("-b", "none"), check.IsNil) 1628 1629 out, err := s.d.Cmd("run", "--rm", "busybox", "ip", "l") 1630 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1631 c.Assert(strings.Contains(out, "eth0"), check.Equals, false, 1632 check.Commentf("There shouldn't be eth0 in container in default(bridge) mode when bridge network is disabled: %s", out)) 1633 1634 out, err = s.d.Cmd("run", "--rm", "--net=bridge", "busybox", "ip", "l") 1635 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1636 c.Assert(strings.Contains(out, "eth0"), check.Equals, false, 1637 check.Commentf("There shouldn't be eth0 in container in bridge mode when bridge network is disabled: %s", out)) 1638 // the extra grep and awk clean up the output of `ip` to only list the number and name of 1639 // interfaces, allowing for different versions of ip (e.g. inside and outside the container) to 1640 // be used while still verifying that the interface list is the exact same 1641 cmd := exec.Command("sh", "-c", "ip l | grep -E '^[0-9]+:' | awk -F: ' { print $1\":\"$2 } '") 1642 stdout := bytes.NewBuffer(nil) 1643 cmd.Stdout = stdout 1644 if err := cmd.Run(); err != nil { 1645 c.Fatal("Failed to get host network interface") 1646 } 1647 out, err = s.d.Cmd("run", "--rm", "--net=host", "busybox", "sh", "-c", "ip l | grep -E '^[0-9]+:' | awk -F: ' { print $1\":\"$2 } '") 1648 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1649 c.Assert(out, check.Equals, fmt.Sprintf("%s", stdout), 1650 check.Commentf("The network interfaces in container should be the same with host when --net=host when bridge network is disabled: %s", out)) 1651 } 1652 1653 func (s *DockerDaemonSuite) TestDaemonRestartWithContainerRunning(t *check.C) { 1654 if err := s.d.StartWithBusybox(); err != nil { 1655 t.Fatal(err) 1656 } 1657 if out, err := s.d.Cmd("run", "-d", "--name", "test", "busybox", "top"); err != nil { 1658 t.Fatal(out, err) 1659 } 1660 1661 if err := s.d.Restart(); err != nil { 1662 t.Fatal(err) 1663 } 1664 // Container 'test' should be removed without error 1665 if out, err := s.d.Cmd("rm", "test"); err != nil { 1666 t.Fatal(out, err) 1667 } 1668 } 1669 1670 func (s *DockerDaemonSuite) TestDaemonRestartCleanupNetns(c *check.C) { 1671 if err := s.d.StartWithBusybox(); err != nil { 1672 c.Fatal(err) 1673 } 1674 out, err := s.d.Cmd("run", "--name", "netns", "-d", "busybox", "top") 1675 if err != nil { 1676 c.Fatal(out, err) 1677 } 1678 1679 // Get sandbox key via inspect 1680 out, err = s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.SandboxKey}}'", "netns") 1681 if err != nil { 1682 c.Fatalf("Error inspecting container: %s, %v", out, err) 1683 } 1684 fileName := strings.Trim(out, " \r\n'") 1685 1686 if out, err := s.d.Cmd("stop", "netns"); err != nil { 1687 c.Fatal(out, err) 1688 } 1689 1690 // Test if the file still exists 1691 out, _, err = runCommandWithOutput(exec.Command("stat", "-c", "%n", fileName)) 1692 out = strings.TrimSpace(out) 1693 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1694 c.Assert(out, check.Equals, fileName, check.Commentf("Output: %s", out)) 1695 1696 // Remove the container and restart the daemon 1697 if out, err := s.d.Cmd("rm", "netns"); err != nil { 1698 c.Fatal(out, err) 1699 } 1700 1701 if err := s.d.Restart(); err != nil { 1702 c.Fatal(err) 1703 } 1704 1705 // Test again and see now the netns file does not exist 1706 out, _, err = runCommandWithOutput(exec.Command("stat", "-c", "%n", fileName)) 1707 out = strings.TrimSpace(out) 1708 c.Assert(err, check.Not(check.IsNil), check.Commentf("Output: %s", out)) 1709 } 1710 1711 // tests regression detailed in #13964 where DOCKER_TLS_VERIFY env is ignored 1712 func (s *DockerDaemonSuite) TestDaemonNoTlsCliTlsVerifyWithEnv(c *check.C) { 1713 host := "tcp://localhost:4271" 1714 c.Assert(s.d.Start("-H", host), check.IsNil) 1715 cmd := exec.Command(dockerBinary, "-H", host, "info") 1716 cmd.Env = []string{"DOCKER_TLS_VERIFY=1", "DOCKER_CERT_PATH=fixtures/https"} 1717 out, _, err := runCommandWithOutput(cmd) 1718 c.Assert(err, check.Not(check.IsNil), check.Commentf("%s", out)) 1719 c.Assert(strings.Contains(out, "error occurred trying to connect"), check.Equals, true) 1720 1721 } 1722 1723 func setupV6() error { 1724 // Hack to get the right IPv6 address on docker0, which has already been created 1725 return exec.Command("ip", "addr", "add", "fe80::1/64", "dev", "docker0").Run() 1726 } 1727 1728 func teardownV6() error { 1729 return exec.Command("ip", "addr", "del", "fe80::1/64", "dev", "docker0").Run() 1730 } 1731 1732 func (s *DockerDaemonSuite) TestDaemonRestartWithContainerWithRestartPolicyAlways(c *check.C) { 1733 c.Assert(s.d.StartWithBusybox(), check.IsNil) 1734 1735 out, err := s.d.Cmd("run", "-d", "--restart", "always", "busybox", "top") 1736 c.Assert(err, check.IsNil) 1737 id := strings.TrimSpace(out) 1738 1739 _, err = s.d.Cmd("stop", id) 1740 c.Assert(err, check.IsNil) 1741 _, err = s.d.Cmd("wait", id) 1742 c.Assert(err, check.IsNil) 1743 1744 out, err = s.d.Cmd("ps", "-q") 1745 c.Assert(err, check.IsNil) 1746 c.Assert(out, check.Equals, "") 1747 1748 c.Assert(s.d.Restart(), check.IsNil) 1749 1750 out, err = s.d.Cmd("ps", "-q") 1751 c.Assert(err, check.IsNil) 1752 c.Assert(strings.TrimSpace(out), check.Equals, id[:12]) 1753 } 1754 1755 func (s *DockerDaemonSuite) TestDaemonWideLogConfig(c *check.C) { 1756 if err := s.d.StartWithBusybox("--log-opt=max-size=1k"); err != nil { 1757 c.Fatal(err) 1758 } 1759 name := "logtest" 1760 out, err := s.d.Cmd("run", "-d", "--log-opt=max-file=5", "--name", name, "busybox", "top") 1761 c.Assert(err, check.IsNil, check.Commentf("Output: %s, err: %v", out, err)) 1762 1763 out, err = s.d.Cmd("inspect", "-f", "{{ .HostConfig.LogConfig.Config }}", name) 1764 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1765 c.Assert(out, checker.Contains, "max-size:1k") 1766 c.Assert(out, checker.Contains, "max-file:5") 1767 1768 out, err = s.d.Cmd("inspect", "-f", "{{ .HostConfig.LogConfig.Type }}", name) 1769 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1770 c.Assert(strings.TrimSpace(out), checker.Equals, "json-file") 1771 } 1772 1773 func (s *DockerDaemonSuite) TestDaemonRestartWithPausedContainer(c *check.C) { 1774 if err := s.d.StartWithBusybox(); err != nil { 1775 c.Fatal(err) 1776 } 1777 if out, err := s.d.Cmd("run", "-i", "-d", "--name", "test", "busybox", "top"); err != nil { 1778 c.Fatal(err, out) 1779 } 1780 if out, err := s.d.Cmd("pause", "test"); err != nil { 1781 c.Fatal(err, out) 1782 } 1783 if err := s.d.Restart(); err != nil { 1784 c.Fatal(err) 1785 } 1786 1787 errchan := make(chan error) 1788 go func() { 1789 out, err := s.d.Cmd("start", "test") 1790 if err != nil { 1791 errchan <- fmt.Errorf("%v:\n%s", err, out) 1792 } 1793 name := strings.TrimSpace(out) 1794 if name != "test" { 1795 errchan <- fmt.Errorf("Paused container start error on docker daemon restart, expected 'test' but got '%s'", name) 1796 } 1797 close(errchan) 1798 }() 1799 1800 select { 1801 case <-time.After(5 * time.Second): 1802 c.Fatal("Waiting on start a container timed out") 1803 case err := <-errchan: 1804 if err != nil { 1805 c.Fatal(err) 1806 } 1807 } 1808 } 1809 1810 func (s *DockerDaemonSuite) TestDaemonRestartRmVolumeInUse(c *check.C) { 1811 c.Assert(s.d.StartWithBusybox(), check.IsNil) 1812 1813 out, err := s.d.Cmd("create", "-v", "test:/foo", "busybox") 1814 c.Assert(err, check.IsNil, check.Commentf(out)) 1815 1816 c.Assert(s.d.Restart(), check.IsNil) 1817 1818 out, err = s.d.Cmd("volume", "rm", "test") 1819 c.Assert(err, check.NotNil, check.Commentf("should not be able to remove in use volume after daemon restart")) 1820 c.Assert(out, checker.Contains, "in use") 1821 } 1822 1823 func (s *DockerDaemonSuite) TestDaemonRestartLocalVolumes(c *check.C) { 1824 c.Assert(s.d.Start(), check.IsNil) 1825 1826 _, err := s.d.Cmd("volume", "create", "--name", "test") 1827 c.Assert(err, check.IsNil) 1828 c.Assert(s.d.Restart(), check.IsNil) 1829 1830 _, err = s.d.Cmd("volume", "inspect", "test") 1831 c.Assert(err, check.IsNil) 1832 } 1833 1834 func (s *DockerDaemonSuite) TestDaemonCorruptedLogDriverAddress(c *check.C) { 1835 c.Assert(s.d.Start("--log-driver=syslog", "--log-opt", "syslog-address=corrupted:42"), check.NotNil) 1836 expected := "Failed to set log opts: syslog-address should be in form proto://address" 1837 runCmd := exec.Command("grep", expected, s.d.LogFileName()) 1838 if out, _, err := runCommandWithOutput(runCmd); err != nil { 1839 c.Fatalf("Expected %q message; but doesn't exist in log: %q, err: %v", expected, out, err) 1840 } 1841 } 1842 1843 func (s *DockerDaemonSuite) TestDaemonCorruptedFluentdAddress(c *check.C) { 1844 c.Assert(s.d.Start("--log-driver=fluentd", "--log-opt", "fluentd-address=corrupted:c"), check.NotNil) 1845 expected := "Failed to set log opts: invalid fluentd-address corrupted:c: " 1846 runCmd := exec.Command("grep", expected, s.d.LogFileName()) 1847 if out, _, err := runCommandWithOutput(runCmd); err != nil { 1848 c.Fatalf("Expected %q message; but doesn't exist in log: %q, err: %v", expected, out, err) 1849 } 1850 } 1851 1852 func (s *DockerDaemonSuite) TestDaemonStartWithoutHost(c *check.C) { 1853 s.d.useDefaultHost = true 1854 defer func() { 1855 s.d.useDefaultHost = false 1856 }() 1857 c.Assert(s.d.Start(), check.IsNil) 1858 } 1859 1860 func (s *DockerDaemonSuite) TestDaemonStartWithDefalutTlsHost(c *check.C) { 1861 s.d.useDefaultTLSHost = true 1862 defer func() { 1863 s.d.useDefaultTLSHost = false 1864 }() 1865 if err := s.d.Start( 1866 "--tlsverify", 1867 "--tlscacert", "fixtures/https/ca.pem", 1868 "--tlscert", "fixtures/https/server-cert.pem", 1869 "--tlskey", "fixtures/https/server-key.pem"); err != nil { 1870 c.Fatalf("Could not start daemon: %v", err) 1871 } 1872 1873 // The client with --tlsverify should also use default host localhost:2376 1874 tmpHost := os.Getenv("DOCKER_HOST") 1875 defer func() { 1876 os.Setenv("DOCKER_HOST", tmpHost) 1877 }() 1878 1879 os.Setenv("DOCKER_HOST", "") 1880 1881 out, _ := dockerCmd( 1882 c, 1883 "--tlsverify", 1884 "--tlscacert", "fixtures/https/ca.pem", 1885 "--tlscert", "fixtures/https/client-cert.pem", 1886 "--tlskey", "fixtures/https/client-key.pem", 1887 "version", 1888 ) 1889 if !strings.Contains(out, "Server") { 1890 c.Fatalf("docker version should return information of server side") 1891 } 1892 } 1893 1894 func (s *DockerDaemonSuite) TestBridgeIPIsExcludedFromAllocatorPool(c *check.C) { 1895 defaultNetworkBridge := "docker0" 1896 deleteInterface(c, defaultNetworkBridge) 1897 1898 bridgeIP := "192.169.1.1" 1899 bridgeRange := bridgeIP + "/30" 1900 1901 err := s.d.StartWithBusybox("--bip", bridgeRange) 1902 c.Assert(err, check.IsNil) 1903 defer s.d.Restart() 1904 1905 var cont int 1906 for { 1907 contName := fmt.Sprintf("container%d", cont) 1908 _, err = s.d.Cmd("run", "--name", contName, "-d", "busybox", "/bin/sleep", "2") 1909 if err != nil { 1910 // pool exhausted 1911 break 1912 } 1913 ip, err := s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.IPAddress}}'", contName) 1914 c.Assert(err, check.IsNil) 1915 1916 c.Assert(ip, check.Not(check.Equals), bridgeIP) 1917 cont++ 1918 } 1919 } 1920 1921 // Test daemon for no space left on device error 1922 func (s *DockerDaemonSuite) TestDaemonNoSpaceLeftOnDeviceError(c *check.C) { 1923 testRequires(c, SameHostDaemon, DaemonIsLinux, Network) 1924 1925 testDir, err := ioutil.TempDir("", "no-space-left-on-device-test") 1926 c.Assert(err, checker.IsNil) 1927 defer os.RemoveAll(testDir) 1928 c.Assert(mount.MakeRShared(testDir), checker.IsNil) 1929 defer mount.Unmount(testDir) 1930 1931 // create a 2MiB image and mount it as graph root 1932 // Why in a container? Because `mount` sometimes behaves weirdly and often fails outright on this test in debian:jessie (which is what the test suite runs under if run from the Makefile) 1933 dockerCmd(c, "run", "--rm", "-v", testDir+":/test", "busybox", "sh", "-c", "dd of=/test/testfs.img bs=1M seek=2 count=0") 1934 out, _, err := runCommandWithOutput(exec.Command("mkfs.ext4", "-F", filepath.Join(testDir, "testfs.img"))) // `mkfs.ext4` is not in busybox 1935 c.Assert(err, checker.IsNil, check.Commentf(out)) 1936 1937 cmd := exec.Command("losetup", "-f", "--show", filepath.Join(testDir, "testfs.img")) 1938 loout, err := cmd.CombinedOutput() 1939 c.Assert(err, checker.IsNil) 1940 loopname := strings.TrimSpace(string(loout)) 1941 defer exec.Command("losetup", "-d", loopname).Run() 1942 1943 dockerCmd(c, "run", "--privileged", "--rm", "-v", testDir+":/test:shared", "busybox", "sh", "-c", fmt.Sprintf("mkdir -p /test/test-mount && mount -t ext4 -no loop,rw %v /test/test-mount", loopname)) 1944 defer mount.Unmount(filepath.Join(testDir, "test-mount")) 1945 1946 err = s.d.Start("--graph", filepath.Join(testDir, "test-mount")) 1947 defer s.d.Stop() 1948 c.Assert(err, check.IsNil) 1949 1950 // pull a repository large enough to fill the mount point 1951 pullOut, err := s.d.Cmd("pull", "registry:2") 1952 c.Assert(err, checker.NotNil, check.Commentf(pullOut)) 1953 c.Assert(pullOut, checker.Contains, "no space left on device") 1954 } 1955 1956 // Test daemon restart with container links + auto restart 1957 func (s *DockerDaemonSuite) TestDaemonRestartContainerLinksRestart(c *check.C) { 1958 d := NewDaemon(c) 1959 defer d.Stop() 1960 err := d.StartWithBusybox() 1961 c.Assert(err, checker.IsNil) 1962 1963 parent1Args := []string{} 1964 parent2Args := []string{} 1965 wg := sync.WaitGroup{} 1966 maxChildren := 10 1967 chErr := make(chan error, maxChildren) 1968 1969 for i := 0; i < maxChildren; i++ { 1970 wg.Add(1) 1971 name := fmt.Sprintf("test%d", i) 1972 1973 if i < maxChildren/2 { 1974 parent1Args = append(parent1Args, []string{"--link", name}...) 1975 } else { 1976 parent2Args = append(parent2Args, []string{"--link", name}...) 1977 } 1978 1979 go func() { 1980 _, err = d.Cmd("run", "-d", "--name", name, "--restart=always", "busybox", "top") 1981 chErr <- err 1982 wg.Done() 1983 }() 1984 } 1985 1986 wg.Wait() 1987 close(chErr) 1988 for err := range chErr { 1989 c.Assert(err, check.IsNil) 1990 } 1991 1992 parent1Args = append([]string{"run", "-d"}, parent1Args...) 1993 parent1Args = append(parent1Args, []string{"--name=parent1", "--restart=always", "busybox", "top"}...) 1994 parent2Args = append([]string{"run", "-d"}, parent2Args...) 1995 parent2Args = append(parent2Args, []string{"--name=parent2", "--restart=always", "busybox", "top"}...) 1996 1997 _, err = d.Cmd(parent1Args...) 1998 c.Assert(err, check.IsNil) 1999 _, err = d.Cmd(parent2Args...) 2000 c.Assert(err, check.IsNil) 2001 2002 err = d.Stop() 2003 c.Assert(err, check.IsNil) 2004 // clear the log file -- we don't need any of it but may for the next part 2005 // can ignore the error here, this is just a cleanup 2006 os.Truncate(d.LogFileName(), 0) 2007 err = d.Start() 2008 c.Assert(err, check.IsNil) 2009 2010 for _, num := range []string{"1", "2"} { 2011 out, err := d.Cmd("inspect", "-f", "{{ .State.Running }}", "parent"+num) 2012 c.Assert(err, check.IsNil) 2013 if strings.TrimSpace(out) != "true" { 2014 log, _ := ioutil.ReadFile(d.LogFileName()) 2015 c.Fatalf("parent container is not running\n%s", string(log)) 2016 } 2017 } 2018 } 2019 2020 func (s *DockerDaemonSuite) TestDaemonCgroupParent(c *check.C) { 2021 testRequires(c, DaemonIsLinux) 2022 2023 cgroupParent := "test" 2024 name := "cgroup-test" 2025 2026 err := s.d.StartWithBusybox("--cgroup-parent", cgroupParent) 2027 c.Assert(err, check.IsNil) 2028 defer s.d.Restart() 2029 2030 out, err := s.d.Cmd("run", "--name", name, "busybox", "cat", "/proc/self/cgroup") 2031 c.Assert(err, checker.IsNil) 2032 cgroupPaths := parseCgroupPaths(string(out)) 2033 c.Assert(len(cgroupPaths), checker.Not(checker.Equals), 0, check.Commentf("unexpected output - %q", string(out))) 2034 out, err = s.d.Cmd("inspect", "-f", "{{.Id}}", name) 2035 c.Assert(err, checker.IsNil) 2036 id := strings.TrimSpace(string(out)) 2037 expectedCgroup := path.Join(cgroupParent, id) 2038 found := false 2039 for _, path := range cgroupPaths { 2040 if strings.HasSuffix(path, expectedCgroup) { 2041 found = true 2042 break 2043 } 2044 } 2045 c.Assert(found, checker.True, check.Commentf("Cgroup path for container (%s) doesn't found in cgroups file: %s", expectedCgroup, cgroupPaths)) 2046 } 2047 2048 func (s *DockerDaemonSuite) TestDaemonRestartWithLinks(c *check.C) { 2049 testRequires(c, DaemonIsLinux) // Windows does not support links 2050 err := s.d.StartWithBusybox() 2051 c.Assert(err, check.IsNil) 2052 2053 out, err := s.d.Cmd("run", "-d", "--name=test", "busybox", "top") 2054 c.Assert(err, check.IsNil, check.Commentf(out)) 2055 2056 out, err = s.d.Cmd("run", "--name=test2", "--link", "test:abc", "busybox", "sh", "-c", "ping -c 1 -w 1 abc") 2057 c.Assert(err, check.IsNil, check.Commentf(out)) 2058 2059 c.Assert(s.d.Restart(), check.IsNil) 2060 2061 // should fail since test is not running yet 2062 out, err = s.d.Cmd("start", "test2") 2063 c.Assert(err, check.NotNil, check.Commentf(out)) 2064 2065 out, err = s.d.Cmd("start", "test") 2066 c.Assert(err, check.IsNil, check.Commentf(out)) 2067 out, err = s.d.Cmd("start", "-a", "test2") 2068 c.Assert(err, check.IsNil, check.Commentf(out)) 2069 c.Assert(strings.Contains(out, "1 packets transmitted, 1 packets received"), check.Equals, true, check.Commentf(out)) 2070 } 2071 2072 func (s *DockerDaemonSuite) TestDaemonRestartWithNames(c *check.C) { 2073 testRequires(c, DaemonIsLinux) // Windows does not support links 2074 err := s.d.StartWithBusybox() 2075 c.Assert(err, check.IsNil) 2076 2077 out, err := s.d.Cmd("create", "--name=test", "busybox") 2078 c.Assert(err, check.IsNil, check.Commentf(out)) 2079 2080 out, err = s.d.Cmd("run", "-d", "--name=test2", "busybox", "top") 2081 c.Assert(err, check.IsNil, check.Commentf(out)) 2082 test2ID := strings.TrimSpace(out) 2083 2084 out, err = s.d.Cmd("run", "-d", "--name=test3", "--link", "test2:abc", "busybox", "top") 2085 test3ID := strings.TrimSpace(out) 2086 2087 c.Assert(s.d.Restart(), check.IsNil) 2088 2089 out, err = s.d.Cmd("create", "--name=test", "busybox") 2090 c.Assert(err, check.NotNil, check.Commentf("expected error trying to create container with duplicate name")) 2091 // this one is no longer needed, removing simplifies the remainder of the test 2092 out, err = s.d.Cmd("rm", "-f", "test") 2093 c.Assert(err, check.IsNil, check.Commentf(out)) 2094 2095 out, err = s.d.Cmd("ps", "-a", "--no-trunc") 2096 c.Assert(err, check.IsNil, check.Commentf(out)) 2097 2098 lines := strings.Split(strings.TrimSpace(out), "\n")[1:] 2099 2100 test2validated := false 2101 test3validated := false 2102 for _, line := range lines { 2103 fields := strings.Fields(line) 2104 names := fields[len(fields)-1] 2105 switch fields[0] { 2106 case test2ID: 2107 c.Assert(names, check.Equals, "test2,test3/abc") 2108 test2validated = true 2109 case test3ID: 2110 c.Assert(names, check.Equals, "test3") 2111 test3validated = true 2112 } 2113 } 2114 2115 c.Assert(test2validated, check.Equals, true) 2116 c.Assert(test3validated, check.Equals, true) 2117 } 2118 2119 // TestDaemonRestartWithKilledRunningContainer requires live restore of running containers 2120 func (s *DockerDaemonSuite) TestDaemonRestartWithKilledRunningContainer(t *check.C) { 2121 // TODO(mlaventure): Not sure what would the exit code be on windows 2122 testRequires(t, DaemonIsLinux) 2123 if err := s.d.StartWithBusybox(); err != nil { 2124 t.Fatal(err) 2125 } 2126 2127 cid, err := s.d.Cmd("run", "-d", "--name", "test", "busybox", "top") 2128 defer s.d.Stop() 2129 if err != nil { 2130 t.Fatal(cid, err) 2131 } 2132 cid = strings.TrimSpace(cid) 2133 2134 pid, err := s.d.Cmd("inspect", "-f", "{{.State.Pid}}", cid) 2135 t.Assert(err, check.IsNil) 2136 pid = strings.TrimSpace(pid) 2137 2138 // Kill the daemon 2139 if err := s.d.Kill(); err != nil { 2140 t.Fatal(err) 2141 } 2142 2143 // kill the container 2144 runCmd := exec.Command(ctrBinary, "--address", "unix:///var/run/docker/libcontainerd/docker-containerd.sock", "containers", "kill", cid) 2145 if out, ec, err := runCommandWithOutput(runCmd); err != nil { 2146 t.Fatalf("Failed to run ctr, ExitCode: %d, err: '%v' output: '%s' cid: '%s'\n", ec, err, out, cid) 2147 } 2148 2149 // Give time to containerd to process the command if we don't 2150 // the exit event might be received after we do the inspect 2151 pidCmd := exec.Command("kill", "-0", pid) 2152 _, ec, _ := runCommandWithOutput(pidCmd) 2153 for ec == 0 { 2154 time.Sleep(1 * time.Second) 2155 _, ec, _ = runCommandWithOutput(pidCmd) 2156 } 2157 2158 // restart the daemon 2159 if err := s.d.Start(); err != nil { 2160 t.Fatal(err) 2161 } 2162 2163 // Check that we've got the correct exit code 2164 out, err := s.d.Cmd("inspect", "-f", "{{.State.ExitCode}}", cid) 2165 t.Assert(err, check.IsNil) 2166 2167 out = strings.TrimSpace(out) 2168 if out != "143" { 2169 t.Fatalf("Expected exit code '%s' got '%s' for container '%s'\n", "143", out, cid) 2170 } 2171 2172 } 2173 2174 // os.Kill should kill daemon ungracefully, leaving behind live containers. 2175 // The live containers should be known to the restarted daemon. Stopping 2176 // them now, should remove the mounts. 2177 func (s *DockerDaemonSuite) TestCleanupMountsAfterDaemonCrash(c *check.C) { 2178 testRequires(c, DaemonIsLinux) 2179 c.Assert(s.d.StartWithBusybox("--live-restore"), check.IsNil) 2180 2181 out, err := s.d.Cmd("run", "-d", "busybox", "top") 2182 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 2183 id := strings.TrimSpace(out) 2184 2185 c.Assert(s.d.cmd.Process.Signal(os.Kill), check.IsNil) 2186 mountOut, err := ioutil.ReadFile("/proc/self/mountinfo") 2187 c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut)) 2188 2189 // container mounts should exist even after daemon has crashed. 2190 comment := check.Commentf("%s should stay mounted from older daemon start:\nDaemon root repository %s\n%s", id, s.d.folder, mountOut) 2191 c.Assert(strings.Contains(string(mountOut), id), check.Equals, true, comment) 2192 2193 // restart daemon. 2194 if err := s.d.Restart("--live-restore"); err != nil { 2195 c.Fatal(err) 2196 } 2197 2198 // container should be running. 2199 out, err = s.d.Cmd("inspect", "--format={{.State.Running}}", id) 2200 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 2201 out = strings.TrimSpace(out) 2202 if out != "true" { 2203 c.Fatalf("Container %s expected to stay alive after daemon restart", id) 2204 } 2205 2206 // 'docker stop' should work. 2207 out, err = s.d.Cmd("stop", id) 2208 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 2209 2210 // Now, container mounts should be gone. 2211 mountOut, err = ioutil.ReadFile("/proc/self/mountinfo") 2212 c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut)) 2213 comment = check.Commentf("%s is still mounted from older daemon start:\nDaemon root repository %s\n%s", id, s.d.folder, mountOut) 2214 c.Assert(strings.Contains(string(mountOut), id), check.Equals, false, comment) 2215 } 2216 2217 // TestDaemonRestartWithUnpausedRunningContainer requires live restore of running containers. 2218 func (s *DockerDaemonSuite) TestDaemonRestartWithUnpausedRunningContainer(t *check.C) { 2219 // TODO(mlaventure): Not sure what would the exit code be on windows 2220 testRequires(t, DaemonIsLinux) 2221 if err := s.d.StartWithBusybox("--live-restore"); err != nil { 2222 t.Fatal(err) 2223 } 2224 2225 cid, err := s.d.Cmd("run", "-d", "--name", "test", "busybox", "top") 2226 defer s.d.Stop() 2227 if err != nil { 2228 t.Fatal(cid, err) 2229 } 2230 cid = strings.TrimSpace(cid) 2231 2232 pid, err := s.d.Cmd("inspect", "-f", "{{.State.Pid}}", cid) 2233 t.Assert(err, check.IsNil) 2234 pid = strings.TrimSpace(pid) 2235 2236 // pause the container 2237 if _, err := s.d.Cmd("pause", cid); err != nil { 2238 t.Fatal(cid, err) 2239 } 2240 2241 // Kill the daemon 2242 if err := s.d.Kill(); err != nil { 2243 t.Fatal(err) 2244 } 2245 2246 // resume the container 2247 runCmd := exec.Command(ctrBinary, "--address", "unix:///var/run/docker/libcontainerd/docker-containerd.sock", "containers", "resume", cid) 2248 if out, ec, err := runCommandWithOutput(runCmd); err != nil { 2249 t.Fatalf("Failed to run ctr, ExitCode: %d, err: '%v' output: '%s' cid: '%s'\n", ec, err, out, cid) 2250 } 2251 2252 // Give time to containerd to process the command if we don't 2253 // the resume event might be received after we do the inspect 2254 pidCmd := exec.Command("kill", "-0", pid) 2255 _, ec, _ := runCommandWithOutput(pidCmd) 2256 for ec == 0 { 2257 time.Sleep(1 * time.Second) 2258 _, ec, _ = runCommandWithOutput(pidCmd) 2259 } 2260 2261 // restart the daemon 2262 if err := s.d.Start("--live-restore"); err != nil { 2263 t.Fatal(err) 2264 } 2265 2266 // Check that we've got the correct status 2267 out, err := s.d.Cmd("inspect", "-f", "{{.State.Status}}", cid) 2268 t.Assert(err, check.IsNil) 2269 2270 out = strings.TrimSpace(out) 2271 if out != "running" { 2272 t.Fatalf("Expected exit code '%s' got '%s' for container '%s'\n", "running", out, cid) 2273 } 2274 if _, err := s.d.Cmd("kill", cid); err != nil { 2275 t.Fatal(err) 2276 } 2277 } 2278 2279 // TestRunLinksChanged checks that creating a new container with the same name does not update links 2280 // this ensures that the old, pre gh#16032 functionality continues on 2281 func (s *DockerDaemonSuite) TestRunLinksChanged(c *check.C) { 2282 testRequires(c, DaemonIsLinux) // Windows does not support links 2283 err := s.d.StartWithBusybox() 2284 c.Assert(err, check.IsNil) 2285 2286 out, err := s.d.Cmd("run", "-d", "--name=test", "busybox", "top") 2287 c.Assert(err, check.IsNil, check.Commentf(out)) 2288 2289 out, err = s.d.Cmd("run", "--name=test2", "--link=test:abc", "busybox", "sh", "-c", "ping -c 1 abc") 2290 c.Assert(err, check.IsNil, check.Commentf(out)) 2291 c.Assert(out, checker.Contains, "1 packets transmitted, 1 packets received") 2292 2293 out, err = s.d.Cmd("rm", "-f", "test") 2294 c.Assert(err, check.IsNil, check.Commentf(out)) 2295 2296 out, err = s.d.Cmd("run", "-d", "--name=test", "busybox", "top") 2297 c.Assert(err, check.IsNil, check.Commentf(out)) 2298 out, err = s.d.Cmd("start", "-a", "test2") 2299 c.Assert(err, check.NotNil, check.Commentf(out)) 2300 c.Assert(out, check.Not(checker.Contains), "1 packets transmitted, 1 packets received") 2301 2302 err = s.d.Restart() 2303 c.Assert(err, check.IsNil) 2304 out, err = s.d.Cmd("start", "-a", "test2") 2305 c.Assert(err, check.NotNil, check.Commentf(out)) 2306 c.Assert(out, check.Not(checker.Contains), "1 packets transmitted, 1 packets received") 2307 } 2308 2309 func (s *DockerDaemonSuite) TestDaemonStartWithoutColors(c *check.C) { 2310 testRequires(c, DaemonIsLinux, NotPpc64le) 2311 newD := NewDaemon(c) 2312 2313 infoLog := "\x1b[34mINFO\x1b" 2314 2315 p, tty, err := pty.Open() 2316 c.Assert(err, checker.IsNil) 2317 defer func() { 2318 tty.Close() 2319 p.Close() 2320 }() 2321 2322 b := bytes.NewBuffer(nil) 2323 go io.Copy(b, p) 2324 2325 // Enable coloring explicitly 2326 newD.StartWithLogFile(tty, "--raw-logs=false") 2327 newD.Stop() 2328 c.Assert(b.String(), checker.Contains, infoLog) 2329 2330 b.Reset() 2331 2332 // Disable coloring explicitly 2333 newD.StartWithLogFile(tty, "--raw-logs=true") 2334 newD.Stop() 2335 c.Assert(b.String(), check.Not(checker.Contains), infoLog) 2336 } 2337 2338 func (s *DockerDaemonSuite) TestDaemonDebugLog(c *check.C) { 2339 testRequires(c, DaemonIsLinux, NotPpc64le) 2340 newD := NewDaemon(c) 2341 2342 debugLog := "\x1b[37mDEBU\x1b" 2343 2344 p, tty, err := pty.Open() 2345 c.Assert(err, checker.IsNil) 2346 defer func() { 2347 tty.Close() 2348 p.Close() 2349 }() 2350 2351 b := bytes.NewBuffer(nil) 2352 go io.Copy(b, p) 2353 2354 newD.StartWithLogFile(tty, "--debug") 2355 newD.Stop() 2356 c.Assert(b.String(), checker.Contains, debugLog) 2357 } 2358 2359 func (s *DockerSuite) TestDaemonDiscoveryBackendConfigReload(c *check.C) { 2360 testRequires(c, SameHostDaemon, DaemonIsLinux) 2361 2362 // daemon config file 2363 daemonConfig := `{ "debug" : false }` 2364 configFilePath := "test.json" 2365 2366 configFile, err := os.Create(configFilePath) 2367 c.Assert(err, checker.IsNil) 2368 fmt.Fprintf(configFile, "%s", daemonConfig) 2369 2370 d := NewDaemon(c) 2371 err = d.Start(fmt.Sprintf("--config-file=%s", configFilePath)) 2372 c.Assert(err, checker.IsNil) 2373 defer d.Stop() 2374 2375 // daemon config file 2376 daemonConfig = `{ 2377 "cluster-store": "consul://consuladdr:consulport/some/path", 2378 "cluster-advertise": "192.168.56.100:0", 2379 "debug" : false 2380 }` 2381 2382 configFile.Close() 2383 os.Remove(configFilePath) 2384 2385 configFile, err = os.Create(configFilePath) 2386 c.Assert(err, checker.IsNil) 2387 defer os.Remove(configFilePath) 2388 fmt.Fprintf(configFile, "%s", daemonConfig) 2389 configFile.Close() 2390 2391 syscall.Kill(d.cmd.Process.Pid, syscall.SIGHUP) 2392 2393 time.Sleep(3 * time.Second) 2394 2395 out, err := d.Cmd("info") 2396 c.Assert(err, checker.IsNil) 2397 c.Assert(out, checker.Contains, fmt.Sprintf("Cluster Store: consul://consuladdr:consulport/some/path")) 2398 c.Assert(out, checker.Contains, fmt.Sprintf("Cluster Advertise: 192.168.56.100:0")) 2399 } 2400 2401 // Test for #21956 2402 func (s *DockerDaemonSuite) TestDaemonLogOptions(c *check.C) { 2403 err := s.d.StartWithBusybox("--log-driver=syslog", "--log-opt=syslog-address=udp://127.0.0.1:514") 2404 c.Assert(err, check.IsNil) 2405 2406 out, err := s.d.Cmd("run", "-d", "--log-driver=json-file", "busybox", "top") 2407 c.Assert(err, check.IsNil, check.Commentf(out)) 2408 id := strings.TrimSpace(out) 2409 2410 out, err = s.d.Cmd("inspect", "--format='{{.HostConfig.LogConfig}}'", id) 2411 c.Assert(err, check.IsNil, check.Commentf(out)) 2412 c.Assert(out, checker.Contains, "{json-file map[]}") 2413 } 2414 2415 // Test case for #20936, #22443 2416 func (s *DockerDaemonSuite) TestDaemonMaxConcurrency(c *check.C) { 2417 c.Assert(s.d.Start("--max-concurrent-uploads=6", "--max-concurrent-downloads=8"), check.IsNil) 2418 2419 expectedMaxConcurrentUploads := `level=debug msg="Max Concurrent Uploads: 6"` 2420 expectedMaxConcurrentDownloads := `level=debug msg="Max Concurrent Downloads: 8"` 2421 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 2422 c.Assert(string(content), checker.Contains, expectedMaxConcurrentUploads) 2423 c.Assert(string(content), checker.Contains, expectedMaxConcurrentDownloads) 2424 } 2425 2426 // Test case for #20936, #22443 2427 func (s *DockerDaemonSuite) TestDaemonMaxConcurrencyWithConfigFile(c *check.C) { 2428 testRequires(c, SameHostDaemon, DaemonIsLinux) 2429 2430 // daemon config file 2431 configFilePath := "test.json" 2432 configFile, err := os.Create(configFilePath) 2433 c.Assert(err, checker.IsNil) 2434 defer os.Remove(configFilePath) 2435 2436 daemonConfig := `{ "max-concurrent-downloads" : 8 }` 2437 fmt.Fprintf(configFile, "%s", daemonConfig) 2438 configFile.Close() 2439 c.Assert(s.d.Start(fmt.Sprintf("--config-file=%s", configFilePath)), check.IsNil) 2440 2441 expectedMaxConcurrentUploads := `level=debug msg="Max Concurrent Uploads: 5"` 2442 expectedMaxConcurrentDownloads := `level=debug msg="Max Concurrent Downloads: 8"` 2443 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 2444 c.Assert(string(content), checker.Contains, expectedMaxConcurrentUploads) 2445 c.Assert(string(content), checker.Contains, expectedMaxConcurrentDownloads) 2446 2447 configFile, err = os.Create(configFilePath) 2448 c.Assert(err, checker.IsNil) 2449 daemonConfig = `{ "max-concurrent-uploads" : 7, "max-concurrent-downloads" : 9 }` 2450 fmt.Fprintf(configFile, "%s", daemonConfig) 2451 configFile.Close() 2452 2453 syscall.Kill(s.d.cmd.Process.Pid, syscall.SIGHUP) 2454 2455 time.Sleep(3 * time.Second) 2456 2457 expectedMaxConcurrentUploads = `level=debug msg="Reset Max Concurrent Uploads: 7"` 2458 expectedMaxConcurrentDownloads = `level=debug msg="Reset Max Concurrent Downloads: 9"` 2459 content, _ = ioutil.ReadFile(s.d.logFile.Name()) 2460 c.Assert(string(content), checker.Contains, expectedMaxConcurrentUploads) 2461 c.Assert(string(content), checker.Contains, expectedMaxConcurrentDownloads) 2462 } 2463 2464 // Test case for #20936, #22443 2465 func (s *DockerDaemonSuite) TestDaemonMaxConcurrencyWithConfigFileReload(c *check.C) { 2466 testRequires(c, SameHostDaemon, DaemonIsLinux) 2467 2468 // daemon config file 2469 configFilePath := "test.json" 2470 configFile, err := os.Create(configFilePath) 2471 c.Assert(err, checker.IsNil) 2472 defer os.Remove(configFilePath) 2473 2474 daemonConfig := `{ "max-concurrent-uploads" : null }` 2475 fmt.Fprintf(configFile, "%s", daemonConfig) 2476 configFile.Close() 2477 c.Assert(s.d.Start(fmt.Sprintf("--config-file=%s", configFilePath)), check.IsNil) 2478 2479 expectedMaxConcurrentUploads := `level=debug msg="Max Concurrent Uploads: 5"` 2480 expectedMaxConcurrentDownloads := `level=debug msg="Max Concurrent Downloads: 3"` 2481 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 2482 c.Assert(string(content), checker.Contains, expectedMaxConcurrentUploads) 2483 c.Assert(string(content), checker.Contains, expectedMaxConcurrentDownloads) 2484 2485 configFile, err = os.Create(configFilePath) 2486 c.Assert(err, checker.IsNil) 2487 daemonConfig = `{ "max-concurrent-uploads" : 1, "max-concurrent-downloads" : null }` 2488 fmt.Fprintf(configFile, "%s", daemonConfig) 2489 configFile.Close() 2490 2491 syscall.Kill(s.d.cmd.Process.Pid, syscall.SIGHUP) 2492 2493 time.Sleep(3 * time.Second) 2494 2495 expectedMaxConcurrentUploads = `level=debug msg="Reset Max Concurrent Uploads: 1"` 2496 expectedMaxConcurrentDownloads = `level=debug msg="Reset Max Concurrent Downloads: 3"` 2497 content, _ = ioutil.ReadFile(s.d.logFile.Name()) 2498 c.Assert(string(content), checker.Contains, expectedMaxConcurrentUploads) 2499 c.Assert(string(content), checker.Contains, expectedMaxConcurrentDownloads) 2500 2501 configFile, err = os.Create(configFilePath) 2502 c.Assert(err, checker.IsNil) 2503 daemonConfig = `{ "labels":["foo=bar"] }` 2504 fmt.Fprintf(configFile, "%s", daemonConfig) 2505 configFile.Close() 2506 2507 syscall.Kill(s.d.cmd.Process.Pid, syscall.SIGHUP) 2508 2509 time.Sleep(3 * time.Second) 2510 2511 expectedMaxConcurrentUploads = `level=debug msg="Reset Max Concurrent Uploads: 5"` 2512 expectedMaxConcurrentDownloads = `level=debug msg="Reset Max Concurrent Downloads: 3"` 2513 content, _ = ioutil.ReadFile(s.d.logFile.Name()) 2514 c.Assert(string(content), checker.Contains, expectedMaxConcurrentUploads) 2515 c.Assert(string(content), checker.Contains, expectedMaxConcurrentDownloads) 2516 } 2517 2518 func (s *DockerDaemonSuite) TestBuildOnDisabledBridgeNetworkDaemon(c *check.C) { 2519 err := s.d.StartWithBusybox("-b=none", "--iptables=false") 2520 c.Assert(err, check.IsNil) 2521 s.d.c.Logf("dockerBinary %s", dockerBinary) 2522 out, code, err := s.d.buildImageWithOut("busyboxs", 2523 `FROM busybox 2524 RUN cat /etc/hosts`, false) 2525 comment := check.Commentf("Failed to build image. output %s, exitCode %d, err %v", out, code, err) 2526 c.Assert(err, check.IsNil, comment) 2527 c.Assert(code, check.Equals, 0, comment) 2528 } 2529 2530 // Test case for #21976 2531 func (s *DockerDaemonSuite) TestDaemonDNSInHostMode(c *check.C) { 2532 testRequires(c, SameHostDaemon, DaemonIsLinux) 2533 2534 err := s.d.StartWithBusybox("--dns", "1.2.3.4") 2535 c.Assert(err, checker.IsNil) 2536 2537 expectedOutput := "nameserver 1.2.3.4" 2538 out, _ := s.d.Cmd("run", "--net=host", "busybox", "cat", "/etc/resolv.conf") 2539 c.Assert(out, checker.Contains, expectedOutput, check.Commentf("Expected '%s', but got %q", expectedOutput, out)) 2540 } 2541 2542 // Test case for #21976 2543 func (s *DockerDaemonSuite) TestDaemonDNSSearchInHostMode(c *check.C) { 2544 testRequires(c, SameHostDaemon, DaemonIsLinux) 2545 2546 err := s.d.StartWithBusybox("--dns-search", "example.com") 2547 c.Assert(err, checker.IsNil) 2548 2549 expectedOutput := "search example.com" 2550 out, _ := s.d.Cmd("run", "--net=host", "busybox", "cat", "/etc/resolv.conf") 2551 c.Assert(out, checker.Contains, expectedOutput, check.Commentf("Expected '%s', but got %q", expectedOutput, out)) 2552 } 2553 2554 // Test case for #21976 2555 func (s *DockerDaemonSuite) TestDaemonDNSOptionsInHostMode(c *check.C) { 2556 testRequires(c, SameHostDaemon, DaemonIsLinux) 2557 2558 err := s.d.StartWithBusybox("--dns-opt", "timeout:3") 2559 c.Assert(err, checker.IsNil) 2560 2561 expectedOutput := "options timeout:3" 2562 out, _ := s.d.Cmd("run", "--net=host", "busybox", "cat", "/etc/resolv.conf") 2563 c.Assert(out, checker.Contains, expectedOutput, check.Commentf("Expected '%s', but got %q", expectedOutput, out)) 2564 } 2565 2566 func (s *DockerDaemonSuite) TestRunWithRuntimeFromConfigFile(c *check.C) { 2567 conf, err := ioutil.TempFile("", "config-file-") 2568 c.Assert(err, check.IsNil) 2569 configName := conf.Name() 2570 conf.Close() 2571 defer os.Remove(configName) 2572 2573 config := ` 2574 { 2575 "runtimes": { 2576 "oci": { 2577 "path": "docker-runc" 2578 }, 2579 "vm": { 2580 "path": "/usr/local/bin/vm-manager", 2581 "runtimeArgs": [ 2582 "--debug" 2583 ] 2584 } 2585 } 2586 } 2587 ` 2588 ioutil.WriteFile(configName, []byte(config), 0644) 2589 err = s.d.StartWithBusybox("--config-file", configName) 2590 c.Assert(err, check.IsNil) 2591 2592 // Run with default runtime 2593 out, err := s.d.Cmd("run", "--rm", "busybox", "ls") 2594 c.Assert(err, check.IsNil, check.Commentf(out)) 2595 2596 // Run with default runtime explicitly 2597 out, err = s.d.Cmd("run", "--rm", "--runtime=runc", "busybox", "ls") 2598 c.Assert(err, check.IsNil, check.Commentf(out)) 2599 2600 // Run with oci (same path as default) but keep it around 2601 out, err = s.d.Cmd("run", "--name", "oci-runtime-ls", "--runtime=oci", "busybox", "ls") 2602 c.Assert(err, check.IsNil, check.Commentf(out)) 2603 2604 // Run with "vm" 2605 out, err = s.d.Cmd("run", "--rm", "--runtime=vm", "busybox", "ls") 2606 c.Assert(err, check.NotNil, check.Commentf(out)) 2607 c.Assert(out, checker.Contains, "/usr/local/bin/vm-manager: no such file or directory") 2608 2609 // Reset config to only have the default 2610 config = ` 2611 { 2612 "runtimes": { 2613 } 2614 } 2615 ` 2616 ioutil.WriteFile(configName, []byte(config), 0644) 2617 syscall.Kill(s.d.cmd.Process.Pid, syscall.SIGHUP) 2618 // Give daemon time to reload config 2619 <-time.After(1 * time.Second) 2620 2621 // Run with default runtime 2622 out, err = s.d.Cmd("run", "--rm", "--runtime=runc", "busybox", "ls") 2623 c.Assert(err, check.IsNil, check.Commentf(out)) 2624 2625 // Run with "oci" 2626 out, err = s.d.Cmd("run", "--rm", "--runtime=oci", "busybox", "ls") 2627 c.Assert(err, check.NotNil, check.Commentf(out)) 2628 c.Assert(out, checker.Contains, "Unknown runtime specified oci") 2629 2630 // Start previously created container with oci 2631 out, err = s.d.Cmd("start", "oci-runtime-ls") 2632 c.Assert(err, check.NotNil, check.Commentf(out)) 2633 c.Assert(out, checker.Contains, "Unknown runtime specified oci") 2634 2635 // Check that we can't override the default runtime 2636 config = ` 2637 { 2638 "runtimes": { 2639 "runc": { 2640 "path": "my-runc" 2641 } 2642 } 2643 } 2644 ` 2645 ioutil.WriteFile(configName, []byte(config), 0644) 2646 syscall.Kill(s.d.cmd.Process.Pid, syscall.SIGHUP) 2647 // Give daemon time to reload config 2648 <-time.After(1 * time.Second) 2649 2650 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 2651 c.Assert(string(content), checker.Contains, `file configuration validation failed (runtime name 'runc' is reserved)`) 2652 2653 // Check that we can select a default runtime 2654 config = ` 2655 { 2656 "default-runtime": "vm", 2657 "runtimes": { 2658 "oci": { 2659 "path": "docker-runc" 2660 }, 2661 "vm": { 2662 "path": "/usr/local/bin/vm-manager", 2663 "runtimeArgs": [ 2664 "--debug" 2665 ] 2666 } 2667 } 2668 } 2669 ` 2670 ioutil.WriteFile(configName, []byte(config), 0644) 2671 syscall.Kill(s.d.cmd.Process.Pid, syscall.SIGHUP) 2672 // Give daemon time to reload config 2673 <-time.After(1 * time.Second) 2674 2675 out, err = s.d.Cmd("run", "--rm", "busybox", "ls") 2676 c.Assert(err, check.NotNil, check.Commentf(out)) 2677 c.Assert(out, checker.Contains, "/usr/local/bin/vm-manager: no such file or directory") 2678 2679 // Run with default runtime explicitly 2680 out, err = s.d.Cmd("run", "--rm", "--runtime=runc", "busybox", "ls") 2681 c.Assert(err, check.IsNil, check.Commentf(out)) 2682 } 2683 2684 func (s *DockerDaemonSuite) TestRunWithRuntimeFromCommandLine(c *check.C) { 2685 err := s.d.StartWithBusybox("--add-runtime", "oci=docker-runc", "--add-runtime", "vm=/usr/local/bin/vm-manager") 2686 c.Assert(err, check.IsNil) 2687 2688 // Run with default runtime 2689 out, err := s.d.Cmd("run", "--rm", "busybox", "ls") 2690 c.Assert(err, check.IsNil, check.Commentf(out)) 2691 2692 // Run with default runtime explicitly 2693 out, err = s.d.Cmd("run", "--rm", "--runtime=runc", "busybox", "ls") 2694 c.Assert(err, check.IsNil, check.Commentf(out)) 2695 2696 // Run with oci (same path as default) but keep it around 2697 out, err = s.d.Cmd("run", "--name", "oci-runtime-ls", "--runtime=oci", "busybox", "ls") 2698 c.Assert(err, check.IsNil, check.Commentf(out)) 2699 2700 // Run with "vm" 2701 out, err = s.d.Cmd("run", "--rm", "--runtime=vm", "busybox", "ls") 2702 c.Assert(err, check.NotNil, check.Commentf(out)) 2703 c.Assert(out, checker.Contains, "/usr/local/bin/vm-manager: no such file or directory") 2704 2705 // Start a daemon without any extra runtimes 2706 s.d.Stop() 2707 err = s.d.StartWithBusybox() 2708 c.Assert(err, check.IsNil) 2709 2710 // Run with default runtime 2711 out, err = s.d.Cmd("run", "--rm", "--runtime=runc", "busybox", "ls") 2712 c.Assert(err, check.IsNil, check.Commentf(out)) 2713 2714 // Run with "oci" 2715 out, err = s.d.Cmd("run", "--rm", "--runtime=oci", "busybox", "ls") 2716 c.Assert(err, check.NotNil, check.Commentf(out)) 2717 c.Assert(out, checker.Contains, "Unknown runtime specified oci") 2718 2719 // Start previously created container with oci 2720 out, err = s.d.Cmd("start", "oci-runtime-ls") 2721 c.Assert(err, check.NotNil, check.Commentf(out)) 2722 c.Assert(out, checker.Contains, "Unknown runtime specified oci") 2723 2724 // Check that we can't override the default runtime 2725 s.d.Stop() 2726 err = s.d.Start("--add-runtime", "runc=my-runc") 2727 c.Assert(err, check.NotNil) 2728 2729 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 2730 c.Assert(string(content), checker.Contains, `runtime name 'runc' is reserved`) 2731 2732 // Check that we can select a default runtime 2733 s.d.Stop() 2734 err = s.d.StartWithBusybox("--default-runtime=vm", "--add-runtime", "oci=docker-runc", "--add-runtime", "vm=/usr/local/bin/vm-manager") 2735 c.Assert(err, check.IsNil) 2736 2737 out, err = s.d.Cmd("run", "--rm", "busybox", "ls") 2738 c.Assert(err, check.NotNil, check.Commentf(out)) 2739 c.Assert(out, checker.Contains, "/usr/local/bin/vm-manager: no such file or directory") 2740 2741 // Run with default runtime explicitly 2742 out, err = s.d.Cmd("run", "--rm", "--runtime=runc", "busybox", "ls") 2743 c.Assert(err, check.IsNil, check.Commentf(out)) 2744 } 2745 2746 func (s *DockerDaemonSuite) TestDaemonRestartWithAutoRemoveContainer(c *check.C) { 2747 err := s.d.StartWithBusybox() 2748 c.Assert(err, checker.IsNil) 2749 2750 // top1 will exist after daemon restarts 2751 out, err := s.d.Cmd("run", "-d", "--name", "top1", "busybox:latest", "top") 2752 c.Assert(err, checker.IsNil, check.Commentf("run top1: %v", out)) 2753 // top2 will be removed after daemon restarts 2754 out, err = s.d.Cmd("run", "-d", "--rm", "--name", "top2", "busybox:latest", "top") 2755 c.Assert(err, checker.IsNil, check.Commentf("run top2: %v", out)) 2756 2757 out, err = s.d.Cmd("ps") 2758 c.Assert(out, checker.Contains, "top1", check.Commentf("top1 should be running")) 2759 c.Assert(out, checker.Contains, "top2", check.Commentf("top2 should be running")) 2760 2761 // now restart daemon gracefully 2762 err = s.d.Restart() 2763 c.Assert(err, checker.IsNil) 2764 2765 out, err = s.d.Cmd("ps", "-a") 2766 c.Assert(err, checker.IsNil, check.Commentf("out: %v", out)) 2767 c.Assert(out, checker.Contains, "top1", check.Commentf("top1 should exist after daemon restarts")) 2768 c.Assert(out, checker.Not(checker.Contains), "top2", check.Commentf("top2 should be removed after daemon restarts")) 2769 }