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