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