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