github.com/hustcat/docker@v1.3.3-0.20160314103604-901c67a8eeab/integration-cli/docker_cli_daemon_test.go (about) 1 // +build daemon,!windows 2 3 package main 4 5 import ( 6 "bytes" 7 "encoding/json" 8 "fmt" 9 "io" 10 "io/ioutil" 11 "net" 12 "os" 13 "os/exec" 14 "path" 15 "path/filepath" 16 "regexp" 17 "strconv" 18 "strings" 19 "sync" 20 "syscall" 21 "time" 22 23 "github.com/docker/docker/pkg/integration/checker" 24 "github.com/docker/go-units" 25 "github.com/docker/libnetwork/iptables" 26 "github.com/docker/libtrust" 27 "github.com/go-check/check" 28 "github.com/kr/pty" 29 ) 30 31 func (s *DockerDaemonSuite) TestDaemonRestartWithRunningContainersPorts(c *check.C) { 32 if err := s.d.StartWithBusybox(); err != nil { 33 c.Fatalf("Could not start daemon with busybox: %v", err) 34 } 35 36 if out, err := s.d.Cmd("run", "-d", "--name", "top1", "-p", "1234:80", "--restart", "always", "busybox:latest", "top"); err != nil { 37 c.Fatalf("Could not run top1: err=%v\n%s", err, out) 38 } 39 // --restart=no by default 40 if out, err := s.d.Cmd("run", "-d", "--name", "top2", "-p", "80", "busybox:latest", "top"); err != nil { 41 c.Fatalf("Could not run top2: err=%v\n%s", err, out) 42 } 43 44 testRun := func(m map[string]bool, prefix string) { 45 var format string 46 for cont, shouldRun := range m { 47 out, err := s.d.Cmd("ps") 48 if err != nil { 49 c.Fatalf("Could not run ps: err=%v\n%q", err, out) 50 } 51 if shouldRun { 52 format = "%scontainer %q is not running" 53 } else { 54 format = "%scontainer %q is running" 55 } 56 if shouldRun != strings.Contains(out, cont) { 57 c.Fatalf(format, prefix, cont) 58 } 59 } 60 } 61 62 testRun(map[string]bool{"top1": true, "top2": true}, "") 63 64 if err := s.d.Restart(); err != nil { 65 c.Fatalf("Could not restart daemon: %v", err) 66 } 67 testRun(map[string]bool{"top1": true, "top2": false}, "After daemon restart: ") 68 } 69 70 func (s *DockerDaemonSuite) TestDaemonRestartWithVolumesRefs(c *check.C) { 71 if err := s.d.StartWithBusybox(); err != nil { 72 c.Fatal(err) 73 } 74 75 if out, err := s.d.Cmd("run", "--name", "volrestarttest1", "-v", "/foo", "busybox"); err != nil { 76 c.Fatal(err, out) 77 } 78 79 if err := s.d.Restart(); err != nil { 80 c.Fatal(err) 81 } 82 83 if _, err := s.d.Cmd("run", "-d", "--volumes-from", "volrestarttest1", "--name", "volrestarttest2", "busybox", "top"); err != nil { 84 c.Fatal(err) 85 } 86 87 if out, err := s.d.Cmd("rm", "-fv", "volrestarttest2"); err != nil { 88 c.Fatal(err, out) 89 } 90 91 out, err := s.d.Cmd("inspect", "-f", "{{json .Mounts}}", "volrestarttest1") 92 c.Assert(err, check.IsNil) 93 94 if _, err := inspectMountPointJSON(out, "/foo"); err != nil { 95 c.Fatalf("Expected volume to exist: /foo, error: %v\n", err) 96 } 97 } 98 99 // #11008 100 func (s *DockerDaemonSuite) TestDaemonRestartUnlessStopped(c *check.C) { 101 err := s.d.StartWithBusybox() 102 c.Assert(err, check.IsNil) 103 104 out, err := s.d.Cmd("run", "-d", "--name", "top1", "--restart", "always", "busybox:latest", "top") 105 c.Assert(err, check.IsNil, check.Commentf("run top1: %v", out)) 106 107 out, err = s.d.Cmd("run", "-d", "--name", "top2", "--restart", "unless-stopped", "busybox:latest", "top") 108 c.Assert(err, check.IsNil, check.Commentf("run top2: %v", out)) 109 110 testRun := func(m map[string]bool, prefix string) { 111 var format string 112 for name, shouldRun := range m { 113 out, err := s.d.Cmd("ps") 114 c.Assert(err, check.IsNil, check.Commentf("run ps: %v", out)) 115 if shouldRun { 116 format = "%scontainer %q is not running" 117 } else { 118 format = "%scontainer %q is running" 119 } 120 c.Assert(strings.Contains(out, name), check.Equals, shouldRun, check.Commentf(format, prefix, name)) 121 } 122 } 123 124 // both running 125 testRun(map[string]bool{"top1": true, "top2": true}, "") 126 127 out, err = s.d.Cmd("stop", "top1") 128 c.Assert(err, check.IsNil, check.Commentf(out)) 129 130 out, err = s.d.Cmd("stop", "top2") 131 c.Assert(err, check.IsNil, check.Commentf(out)) 132 133 // both stopped 134 testRun(map[string]bool{"top1": false, "top2": false}, "") 135 136 err = s.d.Restart() 137 c.Assert(err, check.IsNil) 138 139 // restart=always running 140 testRun(map[string]bool{"top1": true, "top2": false}, "After daemon restart: ") 141 142 out, err = s.d.Cmd("start", "top2") 143 c.Assert(err, check.IsNil, check.Commentf("start top2: %v", out)) 144 145 err = s.d.Restart() 146 c.Assert(err, check.IsNil) 147 148 // both running 149 testRun(map[string]bool{"top1": true, "top2": true}, "After second daemon restart: ") 150 151 } 152 153 func (s *DockerDaemonSuite) TestDaemonStartIptablesFalse(c *check.C) { 154 if err := s.d.Start("--iptables=false"); err != nil { 155 c.Fatalf("we should have been able to start the daemon with passing iptables=false: %v", err) 156 } 157 } 158 159 // Make sure we cannot shrink base device at daemon restart. 160 func (s *DockerDaemonSuite) TestDaemonRestartWithInvalidBasesize(c *check.C) { 161 testRequires(c, Devicemapper) 162 c.Assert(s.d.Start(), check.IsNil) 163 164 oldBasesizeBytes := s.d.getBaseDeviceSize(c) 165 var newBasesizeBytes int64 = 1073741824 //1GB in bytes 166 167 if newBasesizeBytes < oldBasesizeBytes { 168 err := s.d.Restart("--storage-opt", fmt.Sprintf("dm.basesize=%d", newBasesizeBytes)) 169 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)) 170 } 171 c.Assert(s.d.Stop(), check.IsNil) 172 } 173 174 // Make sure we can grow base device at daemon restart. 175 func (s *DockerDaemonSuite) TestDaemonRestartWithIncreasedBasesize(c *check.C) { 176 testRequires(c, Devicemapper) 177 c.Assert(s.d.Start(), check.IsNil) 178 179 oldBasesizeBytes := s.d.getBaseDeviceSize(c) 180 181 var newBasesizeBytes int64 = 53687091200 //50GB in bytes 182 183 if newBasesizeBytes < oldBasesizeBytes { 184 c.Skip(fmt.Sprintf("New base device size (%v) must be greater than (%s)", units.HumanSize(float64(newBasesizeBytes)), units.HumanSize(float64(oldBasesizeBytes)))) 185 } 186 187 err := s.d.Restart("--storage-opt", fmt.Sprintf("dm.basesize=%d", newBasesizeBytes)) 188 c.Assert(err, check.IsNil, check.Commentf("we should have been able to start the daemon with increased base device size: %v", err)) 189 190 basesizeAfterRestart := s.d.getBaseDeviceSize(c) 191 newBasesize, err := convertBasesize(newBasesizeBytes) 192 c.Assert(err, check.IsNil, check.Commentf("Error in converting base device size: %v", err)) 193 c.Assert(newBasesize, check.Equals, basesizeAfterRestart, check.Commentf("Basesize passed is not equal to Basesize set")) 194 c.Assert(s.d.Stop(), check.IsNil) 195 } 196 197 // Issue #8444: If docker0 bridge is modified (intentionally or unintentionally) and 198 // no longer has an IP associated, we should gracefully handle that case and associate 199 // an IP with it rather than fail daemon start 200 func (s *DockerDaemonSuite) TestDaemonStartBridgeWithoutIPAssociation(c *check.C) { 201 // rather than depending on brctl commands to verify docker0 is created and up 202 // let's start the daemon and stop it, and then make a modification to run the 203 // actual test 204 if err := s.d.Start(); err != nil { 205 c.Fatalf("Could not start daemon: %v", err) 206 } 207 if err := s.d.Stop(); err != nil { 208 c.Fatalf("Could not stop daemon: %v", err) 209 } 210 211 // now we will remove the ip from docker0 and then try starting the daemon 212 ipCmd := exec.Command("ip", "addr", "flush", "dev", "docker0") 213 stdout, stderr, _, err := runCommandWithStdoutStderr(ipCmd) 214 if err != nil { 215 c.Fatalf("failed to remove docker0 IP association: %v, stdout: %q, stderr: %q", err, stdout, stderr) 216 } 217 218 if err := s.d.Start(); err != nil { 219 warning := "**WARNING: Docker bridge network in bad state--delete docker0 bridge interface to fix" 220 c.Fatalf("Could not start daemon when docker0 has no IP address: %v\n%s", err, warning) 221 } 222 } 223 224 func (s *DockerDaemonSuite) TestDaemonIptablesClean(c *check.C) { 225 if err := s.d.StartWithBusybox(); err != nil { 226 c.Fatalf("Could not start daemon with busybox: %v", err) 227 } 228 229 if out, err := s.d.Cmd("run", "-d", "--name", "top", "-p", "80", "busybox:latest", "top"); err != nil { 230 c.Fatalf("Could not run top: %s, %v", out, err) 231 } 232 233 // get output from iptables with container running 234 ipTablesSearchString := "tcp dpt:80" 235 ipTablesCmd := exec.Command("iptables", "-nvL") 236 out, _, err := runCommandWithOutput(ipTablesCmd) 237 if err != nil { 238 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 239 } 240 241 if !strings.Contains(out, ipTablesSearchString) { 242 c.Fatalf("iptables output should have contained %q, but was %q", ipTablesSearchString, out) 243 } 244 245 if err := s.d.Stop(); err != nil { 246 c.Fatalf("Could not stop daemon: %v", err) 247 } 248 249 // get output from iptables after restart 250 ipTablesCmd = exec.Command("iptables", "-nvL") 251 out, _, err = runCommandWithOutput(ipTablesCmd) 252 if err != nil { 253 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 254 } 255 256 if strings.Contains(out, ipTablesSearchString) { 257 c.Fatalf("iptables output should not have contained %q, but was %q", ipTablesSearchString, out) 258 } 259 } 260 261 func (s *DockerDaemonSuite) TestDaemonIptablesCreate(c *check.C) { 262 if err := s.d.StartWithBusybox(); err != nil { 263 c.Fatalf("Could not start daemon with busybox: %v", err) 264 } 265 266 if out, err := s.d.Cmd("run", "-d", "--name", "top", "--restart=always", "-p", "80", "busybox:latest", "top"); err != nil { 267 c.Fatalf("Could not run top: %s, %v", out, err) 268 } 269 270 // get output from iptables with container running 271 ipTablesSearchString := "tcp dpt:80" 272 ipTablesCmd := exec.Command("iptables", "-nvL") 273 out, _, err := runCommandWithOutput(ipTablesCmd) 274 if err != nil { 275 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 276 } 277 278 if !strings.Contains(out, ipTablesSearchString) { 279 c.Fatalf("iptables output should have contained %q, but was %q", ipTablesSearchString, out) 280 } 281 282 if err := s.d.Restart(); err != nil { 283 c.Fatalf("Could not restart daemon: %v", err) 284 } 285 286 // make sure the container is not running 287 runningOut, err := s.d.Cmd("inspect", "--format='{{.State.Running}}'", "top") 288 if err != nil { 289 c.Fatalf("Could not inspect on container: %s, %v", out, err) 290 } 291 if strings.TrimSpace(runningOut) != "true" { 292 c.Fatalf("Container should have been restarted after daemon restart. Status running should have been true but was: %q", strings.TrimSpace(runningOut)) 293 } 294 295 // get output from iptables after restart 296 ipTablesCmd = exec.Command("iptables", "-nvL") 297 out, _, err = runCommandWithOutput(ipTablesCmd) 298 if err != nil { 299 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 300 } 301 302 if !strings.Contains(out, ipTablesSearchString) { 303 c.Fatalf("iptables output after restart should have contained %q, but was %q", ipTablesSearchString, out) 304 } 305 } 306 307 // TestDaemonIPv6Enabled checks that when the daemon is started with --ipv6=true that the docker0 bridge 308 // has the fe80::1 address and that a container is assigned a link-local address 309 func (s *DockerSuite) TestDaemonIPv6Enabled(c *check.C) { 310 testRequires(c, IPv6) 311 312 if err := setupV6(); err != nil { 313 c.Fatal("Could not set up host for IPv6 tests") 314 } 315 316 d := NewDaemon(c) 317 318 if err := d.StartWithBusybox("--ipv6"); err != nil { 319 c.Fatal(err) 320 } 321 defer d.Stop() 322 323 iface, err := net.InterfaceByName("docker0") 324 if err != nil { 325 c.Fatalf("Error getting docker0 interface: %v", err) 326 } 327 328 addrs, err := iface.Addrs() 329 if err != nil { 330 c.Fatalf("Error getting addresses for docker0 interface: %v", err) 331 } 332 333 var found bool 334 expected := "fe80::1/64" 335 336 for i := range addrs { 337 if addrs[i].String() == expected { 338 found = true 339 } 340 } 341 342 if !found { 343 c.Fatalf("Bridge does not have an IPv6 Address") 344 } 345 346 if out, err := d.Cmd("run", "-itd", "--name=ipv6test", "busybox:latest"); err != nil { 347 c.Fatalf("Could not run container: %s, %v", out, err) 348 } 349 350 out, err := d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.LinkLocalIPv6Address}}'", "ipv6test") 351 out = strings.Trim(out, " \r\n'") 352 353 if err != nil { 354 c.Fatalf("Error inspecting container: %s, %v", out, err) 355 } 356 357 if ip := net.ParseIP(out); ip == nil { 358 c.Fatalf("Container should have a link-local IPv6 address") 359 } 360 361 out, err = d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.GlobalIPv6Address}}'", "ipv6test") 362 out = strings.Trim(out, " \r\n'") 363 364 if err != nil { 365 c.Fatalf("Error inspecting container: %s, %v", out, err) 366 } 367 368 if ip := net.ParseIP(out); ip != nil { 369 c.Fatalf("Container should not have a global IPv6 address: %v", out) 370 } 371 372 if err := teardownV6(); err != nil { 373 c.Fatal("Could not perform teardown for IPv6 tests") 374 } 375 376 } 377 378 // TestDaemonIPv6FixedCIDR checks that when the daemon is started with --ipv6=true and a fixed CIDR 379 // that running containers are given a link-local and global IPv6 address 380 func (s *DockerDaemonSuite) TestDaemonIPv6FixedCIDR(c *check.C) { 381 // IPv6 setup is messing with local bridge address. 382 testRequires(c, SameHostDaemon) 383 err := setupV6() 384 c.Assert(err, checker.IsNil, check.Commentf("Could not set up host for IPv6 tests")) 385 386 err = s.d.StartWithBusybox("--ipv6", "--fixed-cidr-v6='2001:db8:2::/64'", "--default-gateway-v6='2001:db8:2::100'") 387 c.Assert(err, checker.IsNil, check.Commentf("Could not start daemon with busybox: %v", err)) 388 389 out, err := s.d.Cmd("run", "-itd", "--name=ipv6test", "busybox:latest") 390 c.Assert(err, checker.IsNil, check.Commentf("Could not run container: %s, %v", out, err)) 391 392 out, err = s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.GlobalIPv6Address}}'", "ipv6test") 393 out = strings.Trim(out, " \r\n'") 394 395 c.Assert(err, checker.IsNil, check.Commentf(out)) 396 397 ip := net.ParseIP(out) 398 c.Assert(ip, checker.NotNil, check.Commentf("Container should have a global IPv6 address")) 399 400 out, err = s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.IPv6Gateway}}'", "ipv6test") 401 c.Assert(err, checker.IsNil, check.Commentf(out)) 402 403 c.Assert(strings.Trim(out, " \r\n'"), checker.Equals, "2001:db8:2::100", check.Commentf("Container should have a global IPv6 gateway")) 404 405 err = teardownV6() 406 c.Assert(err, checker.IsNil, check.Commentf("Could not perform teardown for IPv6 tests")) 407 } 408 409 // TestDaemonIPv6FixedCIDRAndMac checks that when the daemon is started with ipv6 fixed CIDR 410 // the running containers are given a an IPv6 address derived from the MAC address and the ipv6 fixed CIDR 411 func (s *DockerDaemonSuite) TestDaemonIPv6FixedCIDRAndMac(c *check.C) { 412 // IPv6 setup is messing with local bridge address. 413 testRequires(c, SameHostDaemon) 414 err := setupV6() 415 c.Assert(err, checker.IsNil) 416 417 err = s.d.StartWithBusybox("--ipv6", "--fixed-cidr-v6='2001:db8:1::/64'") 418 c.Assert(err, checker.IsNil) 419 420 out, err := s.d.Cmd("run", "-itd", "--name=ipv6test", "--mac-address", "AA:BB:CC:DD:EE:FF", "busybox") 421 c.Assert(err, checker.IsNil) 422 423 out, err = s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.GlobalIPv6Address}}'", "ipv6test") 424 c.Assert(err, checker.IsNil) 425 c.Assert(strings.Trim(out, " \r\n'"), checker.Equals, "2001:db8:1::aabb:ccdd:eeff") 426 427 err = teardownV6() 428 c.Assert(err, checker.IsNil) 429 } 430 431 func (s *DockerDaemonSuite) TestDaemonLogLevelWrong(c *check.C) { 432 c.Assert(s.d.Start("--log-level=bogus"), check.NotNil, check.Commentf("Daemon shouldn't start with wrong log level")) 433 } 434 435 func (s *DockerDaemonSuite) TestDaemonLogLevelDebug(c *check.C) { 436 if err := s.d.Start("--log-level=debug"); err != nil { 437 c.Fatal(err) 438 } 439 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 440 if !strings.Contains(string(content), `level=debug`) { 441 c.Fatalf(`Missing level="debug" in log file:\n%s`, string(content)) 442 } 443 } 444 445 func (s *DockerDaemonSuite) TestDaemonLogLevelFatal(c *check.C) { 446 // we creating new daemons to create new logFile 447 if err := s.d.Start("--log-level=fatal"); err != nil { 448 c.Fatal(err) 449 } 450 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 451 if strings.Contains(string(content), `level=debug`) { 452 c.Fatalf(`Should not have level="debug" in log file:\n%s`, string(content)) 453 } 454 } 455 456 func (s *DockerDaemonSuite) TestDaemonFlagD(c *check.C) { 457 if err := s.d.Start("-D"); err != nil { 458 c.Fatal(err) 459 } 460 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 461 if !strings.Contains(string(content), `level=debug`) { 462 c.Fatalf(`Should have level="debug" in log file using -D:\n%s`, string(content)) 463 } 464 } 465 466 func (s *DockerDaemonSuite) TestDaemonFlagDebug(c *check.C) { 467 if err := s.d.Start("--debug"); err != nil { 468 c.Fatal(err) 469 } 470 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 471 if !strings.Contains(string(content), `level=debug`) { 472 c.Fatalf(`Should have level="debug" in log file using --debug:\n%s`, string(content)) 473 } 474 } 475 476 func (s *DockerDaemonSuite) TestDaemonFlagDebugLogLevelFatal(c *check.C) { 477 if err := s.d.Start("--debug", "--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 have level="debug" in log file when using both --debug and --log-level=fatal:\n%s`, string(content)) 483 } 484 } 485 486 func (s *DockerDaemonSuite) TestDaemonAllocatesListeningPort(c *check.C) { 487 listeningPorts := [][]string{ 488 {"0.0.0.0", "0.0.0.0", "5678"}, 489 {"127.0.0.1", "127.0.0.1", "1234"}, 490 {"localhost", "127.0.0.1", "1235"}, 491 } 492 493 cmdArgs := make([]string, 0, len(listeningPorts)*2) 494 for _, hostDirective := range listeningPorts { 495 cmdArgs = append(cmdArgs, "--host", fmt.Sprintf("tcp://%s:%s", hostDirective[0], hostDirective[2])) 496 } 497 498 if err := s.d.StartWithBusybox(cmdArgs...); err != nil { 499 c.Fatalf("Could not start daemon with busybox: %v", err) 500 } 501 502 for _, hostDirective := range listeningPorts { 503 output, err := s.d.Cmd("run", "-p", fmt.Sprintf("%s:%s:80", hostDirective[1], hostDirective[2]), "busybox", "true") 504 if err == nil { 505 c.Fatalf("Container should not start, expected port already allocated error: %q", output) 506 } else if !strings.Contains(output, "port is already allocated") { 507 c.Fatalf("Expected port is already allocated error: %q", output) 508 } 509 } 510 } 511 512 func (s *DockerDaemonSuite) TestDaemonKeyGeneration(c *check.C) { 513 // TODO: skip or update for Windows daemon 514 os.Remove("/etc/docker/key.json") 515 if err := s.d.Start(); err != nil { 516 c.Fatalf("Could not start daemon: %v", err) 517 } 518 s.d.Stop() 519 520 k, err := libtrust.LoadKeyFile("/etc/docker/key.json") 521 if err != nil { 522 c.Fatalf("Error opening key file") 523 } 524 kid := k.KeyID() 525 // Test Key ID is a valid fingerprint (e.g. QQXN:JY5W:TBXI:MK3X:GX6P:PD5D:F56N:NHCS:LVRZ:JA46:R24J:XEFF) 526 if len(kid) != 59 { 527 c.Fatalf("Bad key ID: %s", kid) 528 } 529 } 530 531 func (s *DockerDaemonSuite) TestDaemonKeyMigration(c *check.C) { 532 // TODO: skip or update for Windows daemon 533 os.Remove("/etc/docker/key.json") 534 k1, err := libtrust.GenerateECP256PrivateKey() 535 if err != nil { 536 c.Fatalf("Error generating private key: %s", err) 537 } 538 if err := os.MkdirAll(filepath.Join(os.Getenv("HOME"), ".docker"), 0755); err != nil { 539 c.Fatalf("Error creating .docker directory: %s", err) 540 } 541 if err := libtrust.SaveKey(filepath.Join(os.Getenv("HOME"), ".docker", "key.json"), k1); err != nil { 542 c.Fatalf("Error saving private key: %s", err) 543 } 544 545 if err := s.d.Start(); err != nil { 546 c.Fatalf("Could not start daemon: %v", err) 547 } 548 s.d.Stop() 549 550 k2, err := libtrust.LoadKeyFile("/etc/docker/key.json") 551 if err != nil { 552 c.Fatalf("Error opening key file") 553 } 554 if k1.KeyID() != k2.KeyID() { 555 c.Fatalf("Key not migrated") 556 } 557 } 558 559 // GH#11320 - verify that the daemon exits on failure properly 560 // Note that this explicitly tests the conflict of {-b,--bridge} and {--bip} options as the means 561 // to get a daemon init failure; no other tests for -b/--bip conflict are therefore required 562 func (s *DockerDaemonSuite) TestDaemonExitOnFailure(c *check.C) { 563 //attempt to start daemon with incorrect flags (we know -b and --bip conflict) 564 if err := s.d.Start("--bridge", "nosuchbridge", "--bip", "1.1.1.1"); err != nil { 565 //verify we got the right error 566 if !strings.Contains(err.Error(), "Daemon exited and never started") { 567 c.Fatalf("Expected daemon not to start, got %v", err) 568 } 569 // look in the log and make sure we got the message that daemon is shutting down 570 runCmd := exec.Command("grep", "Error starting daemon", s.d.LogFileName()) 571 if out, _, err := runCommandWithOutput(runCmd); err != nil { 572 c.Fatalf("Expected 'Error starting daemon' message; but doesn't exist in log: %q, err: %v", out, err) 573 } 574 } else { 575 //if we didn't get an error and the daemon is running, this is a failure 576 c.Fatal("Conflicting options should cause the daemon to error out with a failure") 577 } 578 } 579 580 func (s *DockerDaemonSuite) TestDaemonBridgeExternal(c *check.C) { 581 d := s.d 582 err := d.Start("--bridge", "nosuchbridge") 583 c.Assert(err, check.NotNil, check.Commentf("--bridge option with an invalid bridge should cause the daemon to fail")) 584 defer d.Restart() 585 586 bridgeName := "external-bridge" 587 bridgeIP := "192.169.1.1/24" 588 _, bridgeIPNet, _ := net.ParseCIDR(bridgeIP) 589 590 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 591 c.Assert(err, check.IsNil, check.Commentf(out)) 592 defer deleteInterface(c, bridgeName) 593 594 err = d.StartWithBusybox("--bridge", bridgeName) 595 c.Assert(err, check.IsNil) 596 597 ipTablesSearchString := bridgeIPNet.String() 598 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 599 out, _, err = runCommandWithOutput(ipTablesCmd) 600 c.Assert(err, check.IsNil) 601 602 c.Assert(strings.Contains(out, ipTablesSearchString), check.Equals, true, 603 check.Commentf("iptables output should have contained %q, but was %q", 604 ipTablesSearchString, out)) 605 606 _, err = d.Cmd("run", "-d", "--name", "ExtContainer", "busybox", "top") 607 c.Assert(err, check.IsNil) 608 609 containerIP := d.findContainerIP("ExtContainer") 610 ip := net.ParseIP(containerIP) 611 c.Assert(bridgeIPNet.Contains(ip), check.Equals, true, 612 check.Commentf("Container IP-Address must be in the same subnet range : %s", 613 containerIP)) 614 } 615 616 func createInterface(c *check.C, ifType string, ifName string, ipNet string) (string, error) { 617 args := []string{"link", "add", "name", ifName, "type", ifType} 618 ipLinkCmd := exec.Command("ip", args...) 619 out, _, err := runCommandWithOutput(ipLinkCmd) 620 if err != nil { 621 return out, err 622 } 623 624 ifCfgCmd := exec.Command("ifconfig", ifName, ipNet, "up") 625 out, _, err = runCommandWithOutput(ifCfgCmd) 626 return out, err 627 } 628 629 func deleteInterface(c *check.C, ifName string) { 630 ifCmd := exec.Command("ip", "link", "delete", ifName) 631 out, _, err := runCommandWithOutput(ifCmd) 632 c.Assert(err, check.IsNil, check.Commentf(out)) 633 634 flushCmd := exec.Command("iptables", "-t", "nat", "--flush") 635 out, _, err = runCommandWithOutput(flushCmd) 636 c.Assert(err, check.IsNil, check.Commentf(out)) 637 638 flushCmd = exec.Command("iptables", "--flush") 639 out, _, err = runCommandWithOutput(flushCmd) 640 c.Assert(err, check.IsNil, check.Commentf(out)) 641 } 642 643 func (s *DockerDaemonSuite) TestDaemonBridgeIP(c *check.C) { 644 // TestDaemonBridgeIP Steps 645 // 1. Delete the existing docker0 Bridge 646 // 2. Set --bip daemon configuration and start the new Docker Daemon 647 // 3. Check if the bip config has taken effect using ifconfig and iptables commands 648 // 4. Launch a Container and make sure the IP-Address is in the expected subnet 649 // 5. Delete the docker0 Bridge 650 // 6. Restart the Docker Daemon (via deferred action) 651 // This Restart takes care of bringing docker0 interface back to auto-assigned IP 652 653 defaultNetworkBridge := "docker0" 654 deleteInterface(c, defaultNetworkBridge) 655 656 d := s.d 657 658 bridgeIP := "192.169.1.1/24" 659 ip, bridgeIPNet, _ := net.ParseCIDR(bridgeIP) 660 661 err := d.StartWithBusybox("--bip", bridgeIP) 662 c.Assert(err, check.IsNil) 663 defer d.Restart() 664 665 ifconfigSearchString := ip.String() 666 ifconfigCmd := exec.Command("ifconfig", defaultNetworkBridge) 667 out, _, _, err := runCommandWithStdoutStderr(ifconfigCmd) 668 c.Assert(err, check.IsNil) 669 670 c.Assert(strings.Contains(out, ifconfigSearchString), check.Equals, true, 671 check.Commentf("ifconfig output should have contained %q, but was %q", 672 ifconfigSearchString, out)) 673 674 ipTablesSearchString := bridgeIPNet.String() 675 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 676 out, _, err = runCommandWithOutput(ipTablesCmd) 677 c.Assert(err, check.IsNil) 678 679 c.Assert(strings.Contains(out, ipTablesSearchString), check.Equals, true, 680 check.Commentf("iptables output should have contained %q, but was %q", 681 ipTablesSearchString, out)) 682 683 out, err = d.Cmd("run", "-d", "--name", "test", "busybox", "top") 684 c.Assert(err, check.IsNil) 685 686 containerIP := d.findContainerIP("test") 687 ip = net.ParseIP(containerIP) 688 c.Assert(bridgeIPNet.Contains(ip), check.Equals, true, 689 check.Commentf("Container IP-Address must be in the same subnet range : %s", 690 containerIP)) 691 deleteInterface(c, defaultNetworkBridge) 692 } 693 694 func (s *DockerDaemonSuite) TestDaemonRestartWithBridgeIPChange(c *check.C) { 695 if err := s.d.Start(); err != nil { 696 c.Fatalf("Could not start daemon: %v", err) 697 } 698 defer s.d.Restart() 699 if err := s.d.Stop(); err != nil { 700 c.Fatalf("Could not stop daemon: %v", err) 701 } 702 703 // now we will change the docker0's IP and then try starting the daemon 704 bridgeIP := "192.169.100.1/24" 705 _, bridgeIPNet, _ := net.ParseCIDR(bridgeIP) 706 707 ipCmd := exec.Command("ifconfig", "docker0", bridgeIP) 708 stdout, stderr, _, err := runCommandWithStdoutStderr(ipCmd) 709 if err != nil { 710 c.Fatalf("failed to change docker0's IP association: %v, stdout: %q, stderr: %q", err, stdout, stderr) 711 } 712 713 if err := s.d.Start("--bip", bridgeIP); err != nil { 714 c.Fatalf("Could not start daemon: %v", err) 715 } 716 717 //check if the iptables contains new bridgeIP MASQUERADE rule 718 ipTablesSearchString := bridgeIPNet.String() 719 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 720 out, _, err := runCommandWithOutput(ipTablesCmd) 721 if err != nil { 722 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 723 } 724 if !strings.Contains(out, ipTablesSearchString) { 725 c.Fatalf("iptables output should have contained new MASQUERADE rule with IP %q, but was %q", ipTablesSearchString, out) 726 } 727 } 728 729 func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr(c *check.C) { 730 d := s.d 731 732 bridgeName := "external-bridge" 733 bridgeIP := "192.169.1.1/24" 734 735 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 736 c.Assert(err, check.IsNil, check.Commentf(out)) 737 defer deleteInterface(c, bridgeName) 738 739 args := []string{"--bridge", bridgeName, "--fixed-cidr", "192.169.1.0/30"} 740 err = d.StartWithBusybox(args...) 741 c.Assert(err, check.IsNil) 742 defer d.Restart() 743 744 for i := 0; i < 4; i++ { 745 cName := "Container" + strconv.Itoa(i) 746 out, err := d.Cmd("run", "-d", "--name", cName, "busybox", "top") 747 if err != nil { 748 c.Assert(strings.Contains(out, "no available IPv4 addresses"), check.Equals, true, 749 check.Commentf("Could not run a Container : %s %s", err.Error(), out)) 750 } 751 } 752 } 753 754 func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr2(c *check.C) { 755 d := s.d 756 757 bridgeName := "external-bridge" 758 bridgeIP := "10.2.2.1/16" 759 760 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 761 c.Assert(err, check.IsNil, check.Commentf(out)) 762 defer deleteInterface(c, bridgeName) 763 764 err = d.StartWithBusybox("--bip", bridgeIP, "--fixed-cidr", "10.2.2.0/24") 765 c.Assert(err, check.IsNil) 766 defer s.d.Restart() 767 768 out, err = d.Cmd("run", "-d", "--name", "bb", "busybox", "top") 769 c.Assert(err, checker.IsNil, check.Commentf(out)) 770 defer d.Cmd("stop", "bb") 771 772 out, err = d.Cmd("exec", "bb", "/bin/sh", "-c", "ifconfig eth0 | awk '/inet addr/{print substr($2,6)}'") 773 c.Assert(out, checker.Equals, "10.2.2.0\n") 774 775 out, err = d.Cmd("run", "--rm", "busybox", "/bin/sh", "-c", "ifconfig eth0 | awk '/inet addr/{print substr($2,6)}'") 776 c.Assert(err, checker.IsNil, check.Commentf(out)) 777 c.Assert(out, checker.Equals, "10.2.2.2\n") 778 } 779 780 func (s *DockerDaemonSuite) TestDaemonBridgeFixedCIDREqualBridgeNetwork(c *check.C) { 781 d := s.d 782 783 bridgeName := "external-bridge" 784 bridgeIP := "172.27.42.1/16" 785 786 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 787 c.Assert(err, check.IsNil, check.Commentf(out)) 788 defer deleteInterface(c, bridgeName) 789 790 err = d.StartWithBusybox("--bridge", bridgeName, "--fixed-cidr", bridgeIP) 791 c.Assert(err, check.IsNil) 792 defer s.d.Restart() 793 794 out, err = d.Cmd("run", "-d", "busybox", "top") 795 c.Assert(err, check.IsNil, check.Commentf(out)) 796 cid1 := strings.TrimSpace(out) 797 defer d.Cmd("stop", cid1) 798 } 799 800 func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4Implicit(c *check.C) { 801 defaultNetworkBridge := "docker0" 802 deleteInterface(c, defaultNetworkBridge) 803 804 d := s.d 805 806 bridgeIP := "192.169.1.1" 807 bridgeIPNet := fmt.Sprintf("%s/24", bridgeIP) 808 809 err := d.StartWithBusybox("--bip", bridgeIPNet) 810 c.Assert(err, check.IsNil) 811 defer d.Restart() 812 813 expectedMessage := fmt.Sprintf("default via %s dev", bridgeIP) 814 out, err := d.Cmd("run", "busybox", "ip", "-4", "route", "list", "0/0") 815 c.Assert(strings.Contains(out, expectedMessage), check.Equals, true, 816 check.Commentf("Implicit default gateway should be bridge IP %s, but default route was '%s'", 817 bridgeIP, strings.TrimSpace(out))) 818 deleteInterface(c, defaultNetworkBridge) 819 } 820 821 func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4Explicit(c *check.C) { 822 defaultNetworkBridge := "docker0" 823 deleteInterface(c, defaultNetworkBridge) 824 825 d := s.d 826 827 bridgeIP := "192.169.1.1" 828 bridgeIPNet := fmt.Sprintf("%s/24", bridgeIP) 829 gatewayIP := "192.169.1.254" 830 831 err := d.StartWithBusybox("--bip", bridgeIPNet, "--default-gateway", gatewayIP) 832 c.Assert(err, check.IsNil) 833 defer d.Restart() 834 835 expectedMessage := fmt.Sprintf("default via %s dev", gatewayIP) 836 out, err := d.Cmd("run", "busybox", "ip", "-4", "route", "list", "0/0") 837 c.Assert(strings.Contains(out, expectedMessage), check.Equals, true, 838 check.Commentf("Explicit default gateway should be %s, but default route was '%s'", 839 gatewayIP, strings.TrimSpace(out))) 840 deleteInterface(c, defaultNetworkBridge) 841 } 842 843 func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4ExplicitOutsideContainerSubnet(c *check.C) { 844 defaultNetworkBridge := "docker0" 845 deleteInterface(c, defaultNetworkBridge) 846 847 // Program a custom default gateway outside of the container subnet, daemon should accept it and start 848 err := s.d.StartWithBusybox("--bip", "172.16.0.10/16", "--fixed-cidr", "172.16.1.0/24", "--default-gateway", "172.16.0.254") 849 c.Assert(err, check.IsNil) 850 851 deleteInterface(c, defaultNetworkBridge) 852 s.d.Restart() 853 } 854 855 func (s *DockerDaemonSuite) TestDaemonDefaultNetworkInvalidClusterConfig(c *check.C) { 856 testRequires(c, DaemonIsLinux, SameHostDaemon) 857 858 // Start daemon without docker0 bridge 859 defaultNetworkBridge := "docker0" 860 deleteInterface(c, defaultNetworkBridge) 861 862 d := NewDaemon(c) 863 discoveryBackend := "consul://consuladdr:consulport/some/path" 864 err := d.Start(fmt.Sprintf("--cluster-store=%s", discoveryBackend)) 865 c.Assert(err, checker.IsNil) 866 867 // Start daemon with docker0 bridge 868 ifconfigCmd := exec.Command("ifconfig", defaultNetworkBridge) 869 _, err = runCommand(ifconfigCmd) 870 c.Assert(err, check.IsNil) 871 872 err = d.Restart(fmt.Sprintf("--cluster-store=%s", discoveryBackend)) 873 c.Assert(err, checker.IsNil) 874 875 d.Stop() 876 } 877 878 func (s *DockerDaemonSuite) TestDaemonIP(c *check.C) { 879 d := s.d 880 881 ipStr := "192.170.1.1/24" 882 ip, _, _ := net.ParseCIDR(ipStr) 883 args := []string{"--ip", ip.String()} 884 err := d.StartWithBusybox(args...) 885 c.Assert(err, check.IsNil) 886 defer d.Restart() 887 888 out, err := d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top") 889 c.Assert(err, check.NotNil, 890 check.Commentf("Running a container must fail with an invalid --ip option")) 891 c.Assert(strings.Contains(out, "Error starting userland proxy"), check.Equals, true) 892 893 ifName := "dummy" 894 out, err = createInterface(c, "dummy", ifName, ipStr) 895 c.Assert(err, check.IsNil, check.Commentf(out)) 896 defer deleteInterface(c, ifName) 897 898 _, err = d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top") 899 c.Assert(err, check.IsNil) 900 901 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 902 out, _, err = runCommandWithOutput(ipTablesCmd) 903 c.Assert(err, check.IsNil) 904 905 regex := fmt.Sprintf("DNAT.*%s.*dpt:8000", ip.String()) 906 matched, _ := regexp.MatchString(regex, out) 907 c.Assert(matched, check.Equals, true, 908 check.Commentf("iptables output should have contained %q, but was %q", regex, out)) 909 } 910 911 func (s *DockerDaemonSuite) TestDaemonICCPing(c *check.C) { 912 testRequires(c, bridgeNfIptables) 913 d := s.d 914 915 bridgeName := "external-bridge" 916 bridgeIP := "192.169.1.1/24" 917 918 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 919 c.Assert(err, check.IsNil, check.Commentf(out)) 920 defer deleteInterface(c, bridgeName) 921 922 args := []string{"--bridge", bridgeName, "--icc=false"} 923 err = d.StartWithBusybox(args...) 924 c.Assert(err, check.IsNil) 925 defer d.Restart() 926 927 ipTablesCmd := exec.Command("iptables", "-nvL", "FORWARD") 928 out, _, err = runCommandWithOutput(ipTablesCmd) 929 c.Assert(err, check.IsNil) 930 931 regex := fmt.Sprintf("DROP.*all.*%s.*%s", bridgeName, bridgeName) 932 matched, _ := regexp.MatchString(regex, out) 933 c.Assert(matched, check.Equals, true, 934 check.Commentf("iptables output should have contained %q, but was %q", regex, out)) 935 936 // Pinging another container must fail with --icc=false 937 pingContainers(c, d, true) 938 939 ipStr := "192.171.1.1/24" 940 ip, _, _ := net.ParseCIDR(ipStr) 941 ifName := "icc-dummy" 942 943 createInterface(c, "dummy", ifName, ipStr) 944 945 // But, Pinging external or a Host interface must succeed 946 pingCmd := fmt.Sprintf("ping -c 1 %s -W 1", ip.String()) 947 runArgs := []string{"--rm", "busybox", "sh", "-c", pingCmd} 948 _, err = d.Cmd("run", runArgs...) 949 c.Assert(err, check.IsNil) 950 } 951 952 func (s *DockerDaemonSuite) TestDaemonICCLinkExpose(c *check.C) { 953 d := s.d 954 955 bridgeName := "external-bridge" 956 bridgeIP := "192.169.1.1/24" 957 958 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 959 c.Assert(err, check.IsNil, check.Commentf(out)) 960 defer deleteInterface(c, bridgeName) 961 962 args := []string{"--bridge", bridgeName, "--icc=false"} 963 err = d.StartWithBusybox(args...) 964 c.Assert(err, check.IsNil) 965 defer d.Restart() 966 967 ipTablesCmd := exec.Command("iptables", "-nvL", "FORWARD") 968 out, _, err = runCommandWithOutput(ipTablesCmd) 969 c.Assert(err, check.IsNil) 970 971 regex := fmt.Sprintf("DROP.*all.*%s.*%s", bridgeName, bridgeName) 972 matched, _ := regexp.MatchString(regex, out) 973 c.Assert(matched, check.Equals, true, 974 check.Commentf("iptables output should have contained %q, but was %q", regex, out)) 975 976 out, err = d.Cmd("run", "-d", "--expose", "4567", "--name", "icc1", "busybox", "nc", "-l", "-p", "4567") 977 c.Assert(err, check.IsNil, check.Commentf(out)) 978 979 out, err = d.Cmd("run", "--link", "icc1:icc1", "busybox", "nc", "icc1", "4567") 980 c.Assert(err, check.IsNil, check.Commentf(out)) 981 } 982 983 func (s *DockerDaemonSuite) TestDaemonLinksIpTablesRulesWhenLinkAndUnlink(c *check.C) { 984 bridgeName := "external-bridge" 985 bridgeIP := "192.169.1.1/24" 986 987 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 988 c.Assert(err, check.IsNil, check.Commentf(out)) 989 defer deleteInterface(c, bridgeName) 990 991 err = s.d.StartWithBusybox("--bridge", bridgeName, "--icc=false") 992 c.Assert(err, check.IsNil) 993 defer s.d.Restart() 994 995 _, err = s.d.Cmd("run", "-d", "--name", "child", "--publish", "8080:80", "busybox", "top") 996 c.Assert(err, check.IsNil) 997 _, err = s.d.Cmd("run", "-d", "--name", "parent", "--link", "child:http", "busybox", "top") 998 c.Assert(err, check.IsNil) 999 1000 childIP := s.d.findContainerIP("child") 1001 parentIP := s.d.findContainerIP("parent") 1002 1003 sourceRule := []string{"-i", bridgeName, "-o", bridgeName, "-p", "tcp", "-s", childIP, "--sport", "80", "-d", parentIP, "-j", "ACCEPT"} 1004 destinationRule := []string{"-i", bridgeName, "-o", bridgeName, "-p", "tcp", "-s", parentIP, "--dport", "80", "-d", childIP, "-j", "ACCEPT"} 1005 if !iptables.Exists("filter", "DOCKER", sourceRule...) || !iptables.Exists("filter", "DOCKER", destinationRule...) { 1006 c.Fatal("Iptables rules not found") 1007 } 1008 1009 s.d.Cmd("rm", "--link", "parent/http") 1010 if iptables.Exists("filter", "DOCKER", sourceRule...) || iptables.Exists("filter", "DOCKER", destinationRule...) { 1011 c.Fatal("Iptables rules should be removed when unlink") 1012 } 1013 1014 s.d.Cmd("kill", "child") 1015 s.d.Cmd("kill", "parent") 1016 } 1017 1018 func (s *DockerDaemonSuite) TestDaemonUlimitDefaults(c *check.C) { 1019 testRequires(c, DaemonIsLinux) 1020 1021 if err := s.d.StartWithBusybox("--default-ulimit", "nofile=42:42", "--default-ulimit", "nproc=1024:1024"); err != nil { 1022 c.Fatal(err) 1023 } 1024 1025 out, err := s.d.Cmd("run", "--ulimit", "nproc=2048", "--name=test", "busybox", "/bin/sh", "-c", "echo $(ulimit -n); echo $(ulimit -p)") 1026 if err != nil { 1027 c.Fatal(out, err) 1028 } 1029 1030 outArr := strings.Split(out, "\n") 1031 if len(outArr) < 2 { 1032 c.Fatalf("got unexpected output: %s", out) 1033 } 1034 nofile := strings.TrimSpace(outArr[0]) 1035 nproc := strings.TrimSpace(outArr[1]) 1036 1037 if nofile != "42" { 1038 c.Fatalf("expected `ulimit -n` to be `42`, got: %s", nofile) 1039 } 1040 if nproc != "2048" { 1041 c.Fatalf("exepcted `ulimit -p` to be 2048, got: %s", nproc) 1042 } 1043 1044 // Now restart daemon with a new default 1045 if err := s.d.Restart("--default-ulimit", "nofile=43"); err != nil { 1046 c.Fatal(err) 1047 } 1048 1049 out, err = s.d.Cmd("start", "-a", "test") 1050 if err != nil { 1051 c.Fatal(err) 1052 } 1053 1054 outArr = strings.Split(out, "\n") 1055 if len(outArr) < 2 { 1056 c.Fatalf("got unexpected output: %s", out) 1057 } 1058 nofile = strings.TrimSpace(outArr[0]) 1059 nproc = strings.TrimSpace(outArr[1]) 1060 1061 if nofile != "43" { 1062 c.Fatalf("expected `ulimit -n` to be `43`, got: %s", nofile) 1063 } 1064 if nproc != "2048" { 1065 c.Fatalf("exepcted `ulimit -p` to be 2048, got: %s", nproc) 1066 } 1067 } 1068 1069 // #11315 1070 func (s *DockerDaemonSuite) TestDaemonRestartRenameContainer(c *check.C) { 1071 if err := s.d.StartWithBusybox(); err != nil { 1072 c.Fatal(err) 1073 } 1074 1075 if out, err := s.d.Cmd("run", "--name=test", "busybox"); err != nil { 1076 c.Fatal(err, out) 1077 } 1078 1079 if out, err := s.d.Cmd("rename", "test", "test2"); err != nil { 1080 c.Fatal(err, out) 1081 } 1082 1083 if err := s.d.Restart(); err != nil { 1084 c.Fatal(err) 1085 } 1086 1087 if out, err := s.d.Cmd("start", "test2"); err != nil { 1088 c.Fatal(err, out) 1089 } 1090 } 1091 1092 func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefault(c *check.C) { 1093 if err := s.d.StartWithBusybox(); err != nil { 1094 c.Fatal(err) 1095 } 1096 1097 out, err := s.d.Cmd("run", "--name=test", "busybox", "echo", "testline") 1098 c.Assert(err, check.IsNil, check.Commentf(out)) 1099 id, err := s.d.getIDByName("test") 1100 c.Assert(err, check.IsNil) 1101 1102 logPath := filepath.Join(s.d.root, "containers", id, id+"-json.log") 1103 1104 if _, err := os.Stat(logPath); err != nil { 1105 c.Fatal(err) 1106 } 1107 f, err := os.Open(logPath) 1108 if err != nil { 1109 c.Fatal(err) 1110 } 1111 var res struct { 1112 Log string `json:"log"` 1113 Stream string `json:"stream"` 1114 Time time.Time `json:"time"` 1115 } 1116 if err := json.NewDecoder(f).Decode(&res); err != nil { 1117 c.Fatal(err) 1118 } 1119 if res.Log != "testline\n" { 1120 c.Fatalf("Unexpected log line: %q, expected: %q", res.Log, "testline\n") 1121 } 1122 if res.Stream != "stdout" { 1123 c.Fatalf("Unexpected stream: %q, expected: %q", res.Stream, "stdout") 1124 } 1125 if !time.Now().After(res.Time) { 1126 c.Fatalf("Log time %v in future", res.Time) 1127 } 1128 } 1129 1130 func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefaultOverride(c *check.C) { 1131 if err := s.d.StartWithBusybox(); err != nil { 1132 c.Fatal(err) 1133 } 1134 1135 out, err := s.d.Cmd("run", "--name=test", "--log-driver=none", "busybox", "echo", "testline") 1136 if err != nil { 1137 c.Fatal(out, err) 1138 } 1139 id, err := s.d.getIDByName("test") 1140 c.Assert(err, check.IsNil) 1141 1142 logPath := filepath.Join(s.d.root, "containers", id, id+"-json.log") 1143 1144 if _, err := os.Stat(logPath); err == nil || !os.IsNotExist(err) { 1145 c.Fatalf("%s shouldn't exits, error on Stat: %s", logPath, err) 1146 } 1147 } 1148 1149 func (s *DockerDaemonSuite) TestDaemonLoggingDriverNone(c *check.C) { 1150 if err := s.d.StartWithBusybox("--log-driver=none"); err != nil { 1151 c.Fatal(err) 1152 } 1153 1154 out, err := s.d.Cmd("run", "--name=test", "busybox", "echo", "testline") 1155 if err != nil { 1156 c.Fatal(out, err) 1157 } 1158 id, err := s.d.getIDByName("test") 1159 c.Assert(err, check.IsNil) 1160 1161 logPath := filepath.Join(s.d.folder, "graph", "containers", id, id+"-json.log") 1162 1163 if _, err := os.Stat(logPath); err == nil || !os.IsNotExist(err) { 1164 c.Fatalf("%s shouldn't exits, error on Stat: %s", logPath, err) 1165 } 1166 } 1167 1168 func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneOverride(c *check.C) { 1169 if err := s.d.StartWithBusybox("--log-driver=none"); err != nil { 1170 c.Fatal(err) 1171 } 1172 1173 out, err := s.d.Cmd("run", "--name=test", "--log-driver=json-file", "busybox", "echo", "testline") 1174 if err != nil { 1175 c.Fatal(out, err) 1176 } 1177 id, err := s.d.getIDByName("test") 1178 c.Assert(err, check.IsNil) 1179 1180 logPath := filepath.Join(s.d.root, "containers", id, id+"-json.log") 1181 1182 if _, err := os.Stat(logPath); err != nil { 1183 c.Fatal(err) 1184 } 1185 f, err := os.Open(logPath) 1186 if err != nil { 1187 c.Fatal(err) 1188 } 1189 var res struct { 1190 Log string `json:"log"` 1191 Stream string `json:"stream"` 1192 Time time.Time `json:"time"` 1193 } 1194 if err := json.NewDecoder(f).Decode(&res); err != nil { 1195 c.Fatal(err) 1196 } 1197 if res.Log != "testline\n" { 1198 c.Fatalf("Unexpected log line: %q, expected: %q", res.Log, "testline\n") 1199 } 1200 if res.Stream != "stdout" { 1201 c.Fatalf("Unexpected stream: %q, expected: %q", res.Stream, "stdout") 1202 } 1203 if !time.Now().After(res.Time) { 1204 c.Fatalf("Log time %v in future", res.Time) 1205 } 1206 } 1207 1208 func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneLogsError(c *check.C) { 1209 c.Assert(s.d.StartWithBusybox("--log-driver=none"), checker.IsNil) 1210 1211 out, err := s.d.Cmd("run", "--name=test", "busybox", "echo", "testline") 1212 c.Assert(err, checker.IsNil, check.Commentf(out)) 1213 1214 out, err = s.d.Cmd("logs", "test") 1215 c.Assert(err, check.NotNil, check.Commentf("Logs should fail with 'none' driver")) 1216 expected := `"logs" command is supported only for "json-file" and "journald" logging drivers (got: none)` 1217 c.Assert(out, checker.Contains, expected) 1218 } 1219 1220 func (s *DockerDaemonSuite) TestDaemonDots(c *check.C) { 1221 if err := s.d.StartWithBusybox(); err != nil { 1222 c.Fatal(err) 1223 } 1224 1225 // Now create 4 containers 1226 if _, err := s.d.Cmd("create", "busybox"); err != nil { 1227 c.Fatalf("Error creating container: %q", err) 1228 } 1229 if _, err := s.d.Cmd("create", "busybox"); err != nil { 1230 c.Fatalf("Error creating container: %q", err) 1231 } 1232 if _, err := s.d.Cmd("create", "busybox"); err != nil { 1233 c.Fatalf("Error creating container: %q", err) 1234 } 1235 if _, err := s.d.Cmd("create", "busybox"); err != nil { 1236 c.Fatalf("Error creating container: %q", err) 1237 } 1238 1239 s.d.Stop() 1240 1241 s.d.Start("--log-level=debug") 1242 s.d.Stop() 1243 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 1244 if strings.Contains(string(content), "....") { 1245 c.Fatalf("Debug level should not have ....\n%s", string(content)) 1246 } 1247 1248 s.d.Start("--log-level=error") 1249 s.d.Stop() 1250 content, _ = ioutil.ReadFile(s.d.logFile.Name()) 1251 if strings.Contains(string(content), "....") { 1252 c.Fatalf("Error level should not have ....\n%s", string(content)) 1253 } 1254 1255 s.d.Start("--log-level=info") 1256 s.d.Stop() 1257 content, _ = ioutil.ReadFile(s.d.logFile.Name()) 1258 if !strings.Contains(string(content), "....") { 1259 c.Fatalf("Info level should have ....\n%s", string(content)) 1260 } 1261 } 1262 1263 func (s *DockerDaemonSuite) TestDaemonUnixSockCleanedUp(c *check.C) { 1264 dir, err := ioutil.TempDir("", "socket-cleanup-test") 1265 if err != nil { 1266 c.Fatal(err) 1267 } 1268 defer os.RemoveAll(dir) 1269 1270 sockPath := filepath.Join(dir, "docker.sock") 1271 if err := s.d.Start("--host", "unix://"+sockPath); err != nil { 1272 c.Fatal(err) 1273 } 1274 1275 if _, err := os.Stat(sockPath); err != nil { 1276 c.Fatal("socket does not exist") 1277 } 1278 1279 if err := s.d.Stop(); err != nil { 1280 c.Fatal(err) 1281 } 1282 1283 if _, err := os.Stat(sockPath); err == nil || !os.IsNotExist(err) { 1284 c.Fatal("unix socket is not cleaned up") 1285 } 1286 } 1287 1288 func (s *DockerDaemonSuite) TestDaemonWithWrongkey(c *check.C) { 1289 type Config struct { 1290 Crv string `json:"crv"` 1291 D string `json:"d"` 1292 Kid string `json:"kid"` 1293 Kty string `json:"kty"` 1294 X string `json:"x"` 1295 Y string `json:"y"` 1296 } 1297 1298 os.Remove("/etc/docker/key.json") 1299 if err := s.d.Start(); err != nil { 1300 c.Fatalf("Failed to start daemon: %v", err) 1301 } 1302 1303 if err := s.d.Stop(); err != nil { 1304 c.Fatalf("Could not stop daemon: %v", err) 1305 } 1306 1307 config := &Config{} 1308 bytes, err := ioutil.ReadFile("/etc/docker/key.json") 1309 if err != nil { 1310 c.Fatalf("Error reading key.json file: %s", err) 1311 } 1312 1313 // byte[] to Data-Struct 1314 if err := json.Unmarshal(bytes, &config); err != nil { 1315 c.Fatalf("Error Unmarshal: %s", err) 1316 } 1317 1318 //replace config.Kid with the fake value 1319 config.Kid = "VSAJ:FUYR:X3H2:B2VZ:KZ6U:CJD5:K7BX:ZXHY:UZXT:P4FT:MJWG:HRJ4" 1320 1321 // NEW Data-Struct to byte[] 1322 newBytes, err := json.Marshal(&config) 1323 if err != nil { 1324 c.Fatalf("Error Marshal: %s", err) 1325 } 1326 1327 // write back 1328 if err := ioutil.WriteFile("/etc/docker/key.json", newBytes, 0400); err != nil { 1329 c.Fatalf("Error ioutil.WriteFile: %s", err) 1330 } 1331 1332 defer os.Remove("/etc/docker/key.json") 1333 1334 if err := s.d.Start(); err == nil { 1335 c.Fatalf("It should not be successful to start daemon with wrong key: %v", err) 1336 } 1337 1338 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 1339 1340 if !strings.Contains(string(content), "Public Key ID does not match") { 1341 c.Fatal("Missing KeyID message from daemon logs") 1342 } 1343 } 1344 1345 func (s *DockerDaemonSuite) TestDaemonRestartKillWait(c *check.C) { 1346 if err := s.d.StartWithBusybox(); err != nil { 1347 c.Fatalf("Could not start daemon with busybox: %v", err) 1348 } 1349 1350 out, err := s.d.Cmd("run", "-id", "busybox", "/bin/cat") 1351 if err != nil { 1352 c.Fatalf("Could not run /bin/cat: err=%v\n%s", err, out) 1353 } 1354 containerID := strings.TrimSpace(out) 1355 1356 if out, err := s.d.Cmd("kill", containerID); err != nil { 1357 c.Fatalf("Could not kill %s: err=%v\n%s", containerID, err, out) 1358 } 1359 1360 if err := s.d.Restart(); err != nil { 1361 c.Fatalf("Could not restart daemon: %v", err) 1362 } 1363 1364 errchan := make(chan error) 1365 go func() { 1366 if out, err := s.d.Cmd("wait", containerID); err != nil { 1367 errchan <- fmt.Errorf("%v:\n%s", err, out) 1368 } 1369 close(errchan) 1370 }() 1371 1372 select { 1373 case <-time.After(5 * time.Second): 1374 c.Fatal("Waiting on a stopped (killed) container timed out") 1375 case err := <-errchan: 1376 if err != nil { 1377 c.Fatal(err) 1378 } 1379 } 1380 } 1381 1382 // TestHttpsInfo connects via two-way authenticated HTTPS to the info endpoint 1383 func (s *DockerDaemonSuite) TestHttpsInfo(c *check.C) { 1384 const ( 1385 testDaemonHTTPSAddr = "tcp://localhost:4271" 1386 ) 1387 1388 if err := s.d.Start("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-cert.pem", 1389 "--tlskey", "fixtures/https/server-key.pem", "-H", testDaemonHTTPSAddr); err != nil { 1390 c.Fatalf("Could not start daemon with busybox: %v", err) 1391 } 1392 1393 daemonArgs := []string{"--host", testDaemonHTTPSAddr, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/client-cert.pem", "--tlskey", "fixtures/https/client-key.pem"} 1394 out, err := s.d.CmdWithArgs(daemonArgs, "info") 1395 if err != nil { 1396 c.Fatalf("Error Occurred: %s and output: %s", err, out) 1397 } 1398 } 1399 1400 // TestHttpsRun connects via two-way authenticated HTTPS to the create, attach, start, and wait endpoints. 1401 // https://github.com/docker/docker/issues/19280 1402 func (s *DockerDaemonSuite) TestHttpsRun(c *check.C) { 1403 const ( 1404 testDaemonHTTPSAddr = "tcp://localhost:4271" 1405 ) 1406 1407 if err := s.d.StartWithBusybox("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-cert.pem", 1408 "--tlskey", "fixtures/https/server-key.pem", "-H", testDaemonHTTPSAddr); err != nil { 1409 c.Fatalf("Could not start daemon with busybox: %v", err) 1410 } 1411 1412 daemonArgs := []string{"--host", testDaemonHTTPSAddr, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/client-cert.pem", "--tlskey", "fixtures/https/client-key.pem"} 1413 out, err := s.d.CmdWithArgs(daemonArgs, "run", "busybox", "echo", "TLS response") 1414 if err != nil { 1415 c.Fatalf("Error Occurred: %s and output: %s", err, out) 1416 } 1417 1418 if !strings.Contains(out, "TLS response") { 1419 c.Fatalf("expected output to include `TLS response`, got %v", out) 1420 } 1421 } 1422 1423 // TestTlsVerify verifies that --tlsverify=false turns on tls 1424 func (s *DockerDaemonSuite) TestTlsVerify(c *check.C) { 1425 out, err := exec.Command(dockerBinary, "daemon", "--tlsverify=false").CombinedOutput() 1426 if err == nil || !strings.Contains(string(out), "Could not load X509 key pair") { 1427 c.Fatalf("Daemon should not have started due to missing certs: %v\n%s", err, string(out)) 1428 } 1429 } 1430 1431 // TestHttpsInfoRogueCert connects via two-way authenticated HTTPS to the info endpoint 1432 // by using a rogue client certificate and checks that it fails with the expected error. 1433 func (s *DockerDaemonSuite) TestHttpsInfoRogueCert(c *check.C) { 1434 const ( 1435 errBadCertificate = "remote error: bad certificate" 1436 testDaemonHTTPSAddr = "tcp://localhost:4271" 1437 ) 1438 1439 if err := s.d.Start("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-cert.pem", 1440 "--tlskey", "fixtures/https/server-key.pem", "-H", testDaemonHTTPSAddr); err != nil { 1441 c.Fatalf("Could not start daemon with busybox: %v", err) 1442 } 1443 1444 daemonArgs := []string{"--host", testDaemonHTTPSAddr, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/client-rogue-cert.pem", "--tlskey", "fixtures/https/client-rogue-key.pem"} 1445 out, err := s.d.CmdWithArgs(daemonArgs, "info") 1446 if err == nil || !strings.Contains(out, errBadCertificate) { 1447 c.Fatalf("Expected err: %s, got instead: %s and output: %s", errBadCertificate, err, out) 1448 } 1449 } 1450 1451 // TestHttpsInfoRogueServerCert connects via two-way authenticated HTTPS to the info endpoint 1452 // which provides a rogue server certificate and checks that it fails with the expected error 1453 func (s *DockerDaemonSuite) TestHttpsInfoRogueServerCert(c *check.C) { 1454 const ( 1455 errCaUnknown = "x509: certificate signed by unknown authority" 1456 testDaemonRogueHTTPSAddr = "tcp://localhost:4272" 1457 ) 1458 if err := s.d.Start("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-rogue-cert.pem", 1459 "--tlskey", "fixtures/https/server-rogue-key.pem", "-H", testDaemonRogueHTTPSAddr); err != nil { 1460 c.Fatalf("Could not start daemon with busybox: %v", err) 1461 } 1462 1463 daemonArgs := []string{"--host", testDaemonRogueHTTPSAddr, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/client-rogue-cert.pem", "--tlskey", "fixtures/https/client-rogue-key.pem"} 1464 out, err := s.d.CmdWithArgs(daemonArgs, "info") 1465 if err == nil || !strings.Contains(out, errCaUnknown) { 1466 c.Fatalf("Expected err: %s, got instead: %s and output: %s", errCaUnknown, err, out) 1467 } 1468 } 1469 1470 func pingContainers(c *check.C, d *Daemon, expectFailure bool) { 1471 var dargs []string 1472 if d != nil { 1473 dargs = []string{"--host", d.sock()} 1474 } 1475 1476 args := append(dargs, "run", "-d", "--name", "container1", "busybox", "top") 1477 dockerCmd(c, args...) 1478 1479 args = append(dargs, "run", "--rm", "--link", "container1:alias1", "busybox", "sh", "-c") 1480 pingCmd := "ping -c 1 %s -W 1" 1481 args = append(args, fmt.Sprintf(pingCmd, "alias1")) 1482 _, _, err := dockerCmdWithError(args...) 1483 1484 if expectFailure { 1485 c.Assert(err, check.NotNil) 1486 } else { 1487 c.Assert(err, check.IsNil) 1488 } 1489 1490 args = append(dargs, "rm", "-f", "container1") 1491 dockerCmd(c, args...) 1492 } 1493 1494 func (s *DockerDaemonSuite) TestDaemonRestartWithSocketAsVolume(c *check.C) { 1495 c.Assert(s.d.StartWithBusybox(), check.IsNil) 1496 1497 socket := filepath.Join(s.d.folder, "docker.sock") 1498 1499 out, err := s.d.Cmd("run", "--restart=always", "-v", socket+":/sock", "busybox") 1500 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1501 c.Assert(s.d.Restart(), check.IsNil) 1502 } 1503 1504 func (s *DockerDaemonSuite) TestCleanupMountsAfterCrash(c *check.C) { 1505 c.Assert(s.d.StartWithBusybox(), check.IsNil) 1506 1507 out, err := s.d.Cmd("run", "-d", "busybox", "top") 1508 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1509 id := strings.TrimSpace(out) 1510 c.Assert(s.d.cmd.Process.Signal(os.Kill), check.IsNil) 1511 c.Assert(s.d.Start(), check.IsNil) 1512 mountOut, err := ioutil.ReadFile("/proc/self/mountinfo") 1513 c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut)) 1514 1515 comment := check.Commentf("%s is still mounted from older daemon start:\nDaemon root repository %s\n%s", id, s.d.folder, mountOut) 1516 c.Assert(strings.Contains(string(mountOut), id), check.Equals, false, comment) 1517 } 1518 1519 func (s *DockerDaemonSuite) TestRunContainerWithBridgeNone(c *check.C) { 1520 testRequires(c, DaemonIsLinux, NotUserNamespace) 1521 c.Assert(s.d.StartWithBusybox("-b", "none"), check.IsNil) 1522 1523 out, err := s.d.Cmd("run", "--rm", "busybox", "ip", "l") 1524 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1525 c.Assert(strings.Contains(out, "eth0"), check.Equals, false, 1526 check.Commentf("There shouldn't be eth0 in container in default(bridge) mode when bridge network is disabled: %s", out)) 1527 1528 out, err = s.d.Cmd("run", "--rm", "--net=bridge", "busybox", "ip", "l") 1529 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1530 c.Assert(strings.Contains(out, "eth0"), check.Equals, false, 1531 check.Commentf("There shouldn't be eth0 in container in bridge mode when bridge network is disabled: %s", out)) 1532 // the extra grep and awk clean up the output of `ip` to only list the number and name of 1533 // interfaces, allowing for different versions of ip (e.g. inside and outside the container) to 1534 // be used while still verifying that the interface list is the exact same 1535 cmd := exec.Command("sh", "-c", "ip l | grep -E '^[0-9]+:' | awk -F: ' { print $1\":\"$2 } '") 1536 stdout := bytes.NewBuffer(nil) 1537 cmd.Stdout = stdout 1538 if err := cmd.Run(); err != nil { 1539 c.Fatal("Failed to get host network interface") 1540 } 1541 out, err = s.d.Cmd("run", "--rm", "--net=host", "busybox", "sh", "-c", "ip l | grep -E '^[0-9]+:' | awk -F: ' { print $1\":\"$2 } '") 1542 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1543 c.Assert(out, check.Equals, fmt.Sprintf("%s", stdout), 1544 check.Commentf("The network interfaces in container should be the same with host when --net=host when bridge network is disabled: %s", out)) 1545 } 1546 1547 func (s *DockerDaemonSuite) TestDaemonRestartWithContainerRunning(t *check.C) { 1548 if err := s.d.StartWithBusybox(); err != nil { 1549 t.Fatal(err) 1550 } 1551 if out, err := s.d.Cmd("run", "-d", "--name", "test", "busybox", "top"); err != nil { 1552 t.Fatal(out, err) 1553 } 1554 1555 if err := s.d.Restart(); err != nil { 1556 t.Fatal(err) 1557 } 1558 // Container 'test' should be removed without error 1559 if out, err := s.d.Cmd("rm", "test"); err != nil { 1560 t.Fatal(out, err) 1561 } 1562 } 1563 1564 func (s *DockerDaemonSuite) TestDaemonRestartCleanupNetns(c *check.C) { 1565 if err := s.d.StartWithBusybox(); err != nil { 1566 c.Fatal(err) 1567 } 1568 out, err := s.d.Cmd("run", "--name", "netns", "-d", "busybox", "top") 1569 if err != nil { 1570 c.Fatal(out, err) 1571 } 1572 1573 // Get sandbox key via inspect 1574 out, err = s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.SandboxKey}}'", "netns") 1575 if err != nil { 1576 c.Fatalf("Error inspecting container: %s, %v", out, err) 1577 } 1578 fileName := strings.Trim(out, " \r\n'") 1579 1580 if out, err := s.d.Cmd("stop", "netns"); err != nil { 1581 c.Fatal(out, err) 1582 } 1583 1584 // Test if the file still exists 1585 out, _, err = runCommandWithOutput(exec.Command("stat", "-c", "%n", fileName)) 1586 out = strings.TrimSpace(out) 1587 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1588 c.Assert(out, check.Equals, fileName, check.Commentf("Output: %s", out)) 1589 1590 // Remove the container and restart the daemon 1591 if out, err := s.d.Cmd("rm", "netns"); err != nil { 1592 c.Fatal(out, err) 1593 } 1594 1595 if err := s.d.Restart(); err != nil { 1596 c.Fatal(err) 1597 } 1598 1599 // Test again and see now the netns file does not exist 1600 out, _, err = runCommandWithOutput(exec.Command("stat", "-c", "%n", fileName)) 1601 out = strings.TrimSpace(out) 1602 c.Assert(err, check.Not(check.IsNil), check.Commentf("Output: %s", out)) 1603 } 1604 1605 // tests regression detailed in #13964 where DOCKER_TLS_VERIFY env is ignored 1606 func (s *DockerDaemonSuite) TestDaemonNoTlsCliTlsVerifyWithEnv(c *check.C) { 1607 host := "tcp://localhost:4271" 1608 c.Assert(s.d.Start("-H", host), check.IsNil) 1609 cmd := exec.Command(dockerBinary, "-H", host, "info") 1610 cmd.Env = []string{"DOCKER_TLS_VERIFY=1", "DOCKER_CERT_PATH=fixtures/https"} 1611 out, _, err := runCommandWithOutput(cmd) 1612 c.Assert(err, check.Not(check.IsNil), check.Commentf("%s", out)) 1613 c.Assert(strings.Contains(out, "error occurred trying to connect"), check.Equals, true) 1614 1615 } 1616 1617 func setupV6() error { 1618 // Hack to get the right IPv6 address on docker0, which has already been created 1619 return exec.Command("ip", "addr", "add", "fe80::1/64", "dev", "docker0").Run() 1620 } 1621 1622 func teardownV6() error { 1623 return exec.Command("ip", "addr", "del", "fe80::1/64", "dev", "docker0").Run() 1624 } 1625 1626 func (s *DockerDaemonSuite) TestDaemonRestartWithContainerWithRestartPolicyAlways(c *check.C) { 1627 c.Assert(s.d.StartWithBusybox(), check.IsNil) 1628 1629 out, err := s.d.Cmd("run", "-d", "--restart", "always", "busybox", "top") 1630 c.Assert(err, check.IsNil) 1631 id := strings.TrimSpace(out) 1632 1633 _, err = s.d.Cmd("stop", id) 1634 c.Assert(err, check.IsNil) 1635 _, err = s.d.Cmd("wait", id) 1636 c.Assert(err, check.IsNil) 1637 1638 out, err = s.d.Cmd("ps", "-q") 1639 c.Assert(err, check.IsNil) 1640 c.Assert(out, check.Equals, "") 1641 1642 c.Assert(s.d.Restart(), check.IsNil) 1643 1644 out, err = s.d.Cmd("ps", "-q") 1645 c.Assert(err, check.IsNil) 1646 c.Assert(strings.TrimSpace(out), check.Equals, id[:12]) 1647 } 1648 1649 func (s *DockerDaemonSuite) TestDaemonWideLogConfig(c *check.C) { 1650 if err := s.d.StartWithBusybox("--log-driver=json-file", "--log-opt=max-size=1k"); err != nil { 1651 c.Fatal(err) 1652 } 1653 out, err := s.d.Cmd("run", "-d", "--name=logtest", "busybox", "top") 1654 c.Assert(err, check.IsNil, check.Commentf("Output: %s, err: %v", out, err)) 1655 out, err = s.d.Cmd("inspect", "-f", "{{ .HostConfig.LogConfig.Config }}", "logtest") 1656 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1657 cfg := strings.TrimSpace(out) 1658 if cfg != "map[max-size:1k]" { 1659 c.Fatalf("Unexpected log-opt: %s, expected map[max-size:1k]", cfg) 1660 } 1661 } 1662 1663 func (s *DockerDaemonSuite) TestDaemonRestartWithPausedContainer(c *check.C) { 1664 if err := s.d.StartWithBusybox(); err != nil { 1665 c.Fatal(err) 1666 } 1667 if out, err := s.d.Cmd("run", "-i", "-d", "--name", "test", "busybox", "top"); err != nil { 1668 c.Fatal(err, out) 1669 } 1670 if out, err := s.d.Cmd("pause", "test"); err != nil { 1671 c.Fatal(err, out) 1672 } 1673 if err := s.d.Restart(); err != nil { 1674 c.Fatal(err) 1675 } 1676 1677 errchan := make(chan error) 1678 go func() { 1679 out, err := s.d.Cmd("start", "test") 1680 if err != nil { 1681 errchan <- fmt.Errorf("%v:\n%s", err, out) 1682 } 1683 name := strings.TrimSpace(out) 1684 if name != "test" { 1685 errchan <- fmt.Errorf("Paused container start error on docker daemon restart, expected 'test' but got '%s'", name) 1686 } 1687 close(errchan) 1688 }() 1689 1690 select { 1691 case <-time.After(5 * time.Second): 1692 c.Fatal("Waiting on start a container timed out") 1693 case err := <-errchan: 1694 if err != nil { 1695 c.Fatal(err) 1696 } 1697 } 1698 } 1699 1700 func (s *DockerDaemonSuite) TestDaemonRestartRmVolumeInUse(c *check.C) { 1701 c.Assert(s.d.StartWithBusybox(), check.IsNil) 1702 1703 out, err := s.d.Cmd("create", "-v", "test:/foo", "busybox") 1704 c.Assert(err, check.IsNil, check.Commentf(out)) 1705 1706 c.Assert(s.d.Restart(), check.IsNil) 1707 1708 out, err = s.d.Cmd("volume", "rm", "test") 1709 c.Assert(err, check.NotNil, check.Commentf("should not be able to remove in use volume after daemon restart")) 1710 c.Assert(out, checker.Contains, "in use") 1711 } 1712 1713 func (s *DockerDaemonSuite) TestDaemonRestartLocalVolumes(c *check.C) { 1714 c.Assert(s.d.Start(), check.IsNil) 1715 1716 _, err := s.d.Cmd("volume", "create", "--name", "test") 1717 c.Assert(err, check.IsNil) 1718 c.Assert(s.d.Restart(), check.IsNil) 1719 1720 _, err = s.d.Cmd("volume", "inspect", "test") 1721 c.Assert(err, check.IsNil) 1722 } 1723 1724 func (s *DockerDaemonSuite) TestDaemonCorruptedLogDriverAddress(c *check.C) { 1725 c.Assert(s.d.Start("--log-driver=syslog", "--log-opt", "syslog-address=corrupted:42"), check.NotNil) 1726 expected := "Failed to set log opts: syslog-address should be in form proto://address" 1727 runCmd := exec.Command("grep", expected, s.d.LogFileName()) 1728 if out, _, err := runCommandWithOutput(runCmd); err != nil { 1729 c.Fatalf("Expected %q message; but doesn't exist in log: %q, err: %v", expected, out, err) 1730 } 1731 } 1732 1733 func (s *DockerDaemonSuite) TestDaemonCorruptedFluentdAddress(c *check.C) { 1734 c.Assert(s.d.Start("--log-driver=fluentd", "--log-opt", "fluentd-address=corrupted:c"), check.NotNil) 1735 expected := "Failed to set log opts: invalid fluentd-address corrupted:c: " 1736 runCmd := exec.Command("grep", expected, s.d.LogFileName()) 1737 if out, _, err := runCommandWithOutput(runCmd); err != nil { 1738 c.Fatalf("Expected %q message; but doesn't exist in log: %q, err: %v", expected, out, err) 1739 } 1740 } 1741 1742 func (s *DockerDaemonSuite) TestDaemonStartWithoutHost(c *check.C) { 1743 s.d.useDefaultHost = true 1744 defer func() { 1745 s.d.useDefaultHost = false 1746 }() 1747 c.Assert(s.d.Start(), check.IsNil) 1748 } 1749 1750 func (s *DockerDaemonSuite) TestDaemonStartWithDefalutTlsHost(c *check.C) { 1751 s.d.useDefaultTLSHost = true 1752 defer func() { 1753 s.d.useDefaultTLSHost = false 1754 }() 1755 if err := s.d.Start( 1756 "--tlsverify", 1757 "--tlscacert", "fixtures/https/ca.pem", 1758 "--tlscert", "fixtures/https/server-cert.pem", 1759 "--tlskey", "fixtures/https/server-key.pem"); err != nil { 1760 c.Fatalf("Could not start daemon: %v", err) 1761 } 1762 1763 // The client with --tlsverify should also use default host localhost:2376 1764 tmpHost := os.Getenv("DOCKER_HOST") 1765 defer func() { 1766 os.Setenv("DOCKER_HOST", tmpHost) 1767 }() 1768 1769 os.Setenv("DOCKER_HOST", "") 1770 1771 out, _ := dockerCmd( 1772 c, 1773 "--tlsverify", 1774 "--tlscacert", "fixtures/https/ca.pem", 1775 "--tlscert", "fixtures/https/client-cert.pem", 1776 "--tlskey", "fixtures/https/client-key.pem", 1777 "version", 1778 ) 1779 if !strings.Contains(out, "Server") { 1780 c.Fatalf("docker version should return information of server side") 1781 } 1782 } 1783 1784 func (s *DockerDaemonSuite) TestBridgeIPIsExcludedFromAllocatorPool(c *check.C) { 1785 defaultNetworkBridge := "docker0" 1786 deleteInterface(c, defaultNetworkBridge) 1787 1788 bridgeIP := "192.169.1.1" 1789 bridgeRange := bridgeIP + "/30" 1790 1791 err := s.d.StartWithBusybox("--bip", bridgeRange) 1792 c.Assert(err, check.IsNil) 1793 defer s.d.Restart() 1794 1795 var cont int 1796 for { 1797 contName := fmt.Sprintf("container%d", cont) 1798 _, err = s.d.Cmd("run", "--name", contName, "-d", "busybox", "/bin/sleep", "2") 1799 if err != nil { 1800 // pool exhausted 1801 break 1802 } 1803 ip, err := s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.IPAddress}}'", contName) 1804 c.Assert(err, check.IsNil) 1805 1806 c.Assert(ip, check.Not(check.Equals), bridgeIP) 1807 cont++ 1808 } 1809 } 1810 1811 // Test daemon for no space left on device error 1812 func (s *DockerDaemonSuite) TestDaemonNoSpaceleftOnDeviceError(c *check.C) { 1813 testRequires(c, SameHostDaemon, DaemonIsLinux, Network) 1814 1815 // create a 2MiB image and mount it as graph root 1816 cmd := exec.Command("dd", "of=/tmp/testfs.img", "bs=1M", "seek=2", "count=0") 1817 if err := cmd.Run(); err != nil { 1818 c.Fatalf("dd failed: %v", err) 1819 } 1820 cmd = exec.Command("mkfs.ext4", "-F", "/tmp/testfs.img") 1821 if err := cmd.Run(); err != nil { 1822 c.Fatalf("mkfs.ext4 failed: %v", err) 1823 } 1824 cmd = exec.Command("mkdir", "-p", "/tmp/testfs-mount") 1825 if err := cmd.Run(); err != nil { 1826 c.Fatalf("mkdir failed: %v", err) 1827 } 1828 cmd = exec.Command("mount", "-t", "ext4", "-no", "loop,rw", "/tmp/testfs.img", "/tmp/testfs-mount") 1829 if err := cmd.Run(); err != nil { 1830 c.Fatalf("mount failed: %v", err) 1831 } 1832 err := s.d.Start("--graph", "/tmp/testfs-mount") 1833 c.Assert(err, check.IsNil) 1834 1835 // pull a repository large enough to fill the mount point 1836 out, err := s.d.Cmd("pull", "registry:2") 1837 c.Assert(out, checker.Contains, "no space left on device") 1838 } 1839 1840 // Test daemon restart with container links + auto restart 1841 func (s *DockerDaemonSuite) TestDaemonRestartContainerLinksRestart(c *check.C) { 1842 d := NewDaemon(c) 1843 err := d.StartWithBusybox() 1844 c.Assert(err, checker.IsNil) 1845 1846 parent1Args := []string{} 1847 parent2Args := []string{} 1848 wg := sync.WaitGroup{} 1849 maxChildren := 10 1850 chErr := make(chan error, maxChildren) 1851 1852 for i := 0; i < maxChildren; i++ { 1853 wg.Add(1) 1854 name := fmt.Sprintf("test%d", i) 1855 1856 if i < maxChildren/2 { 1857 parent1Args = append(parent1Args, []string{"--link", name}...) 1858 } else { 1859 parent2Args = append(parent2Args, []string{"--link", name}...) 1860 } 1861 1862 go func() { 1863 _, err = d.Cmd("run", "-d", "--name", name, "--restart=always", "busybox", "top") 1864 chErr <- err 1865 wg.Done() 1866 }() 1867 } 1868 1869 wg.Wait() 1870 close(chErr) 1871 for err := range chErr { 1872 c.Assert(err, check.IsNil) 1873 } 1874 1875 parent1Args = append([]string{"run", "-d"}, parent1Args...) 1876 parent1Args = append(parent1Args, []string{"--name=parent1", "--restart=always", "busybox", "top"}...) 1877 parent2Args = append([]string{"run", "-d"}, parent2Args...) 1878 parent2Args = append(parent2Args, []string{"--name=parent2", "--restart=always", "busybox", "top"}...) 1879 1880 _, err = d.Cmd(parent1Args[0], parent1Args[1:]...) 1881 c.Assert(err, check.IsNil) 1882 _, err = d.Cmd(parent2Args[0], parent2Args[1:]...) 1883 c.Assert(err, check.IsNil) 1884 1885 err = d.Stop() 1886 c.Assert(err, check.IsNil) 1887 // clear the log file -- we don't need any of it but may for the next part 1888 // can ignore the error here, this is just a cleanup 1889 os.Truncate(d.LogFileName(), 0) 1890 err = d.Start() 1891 c.Assert(err, check.IsNil) 1892 1893 for _, num := range []string{"1", "2"} { 1894 out, err := d.Cmd("inspect", "-f", "{{ .State.Running }}", "parent"+num) 1895 c.Assert(err, check.IsNil) 1896 if strings.TrimSpace(out) != "true" { 1897 log, _ := ioutil.ReadFile(d.LogFileName()) 1898 c.Fatalf("parent container is not running\n%s", string(log)) 1899 } 1900 } 1901 } 1902 1903 func (s *DockerDaemonSuite) TestDaemonCgroupParent(c *check.C) { 1904 testRequires(c, DaemonIsLinux) 1905 1906 cgroupParent := "test" 1907 name := "cgroup-test" 1908 1909 err := s.d.StartWithBusybox("--cgroup-parent", cgroupParent) 1910 c.Assert(err, check.IsNil) 1911 defer s.d.Restart() 1912 1913 out, err := s.d.Cmd("run", "--name", name, "busybox", "cat", "/proc/self/cgroup") 1914 c.Assert(err, checker.IsNil) 1915 cgroupPaths := parseCgroupPaths(string(out)) 1916 c.Assert(len(cgroupPaths), checker.Not(checker.Equals), 0, check.Commentf("unexpected output - %q", string(out))) 1917 out, err = s.d.Cmd("inspect", "-f", "{{.Id}}", name) 1918 c.Assert(err, checker.IsNil) 1919 id := strings.TrimSpace(string(out)) 1920 expectedCgroup := path.Join(cgroupParent, id) 1921 found := false 1922 for _, path := range cgroupPaths { 1923 if strings.HasSuffix(path, expectedCgroup) { 1924 found = true 1925 break 1926 } 1927 } 1928 c.Assert(found, checker.True, check.Commentf("Cgroup path for container (%s) doesn't found in cgroups file: %s", expectedCgroup, cgroupPaths)) 1929 } 1930 1931 func (s *DockerDaemonSuite) TestDaemonRestartWithLinks(c *check.C) { 1932 testRequires(c, DaemonIsLinux) // Windows does not support links 1933 err := s.d.StartWithBusybox() 1934 c.Assert(err, check.IsNil) 1935 1936 out, err := s.d.Cmd("run", "-d", "--name=test", "busybox", "top") 1937 c.Assert(err, check.IsNil, check.Commentf(out)) 1938 1939 out, err = s.d.Cmd("run", "--name=test2", "--link", "test:abc", "busybox", "sh", "-c", "ping -c 1 -w 1 abc") 1940 c.Assert(err, check.IsNil, check.Commentf(out)) 1941 1942 c.Assert(s.d.Restart(), check.IsNil) 1943 1944 // should fail since test is not running yet 1945 out, err = s.d.Cmd("start", "test2") 1946 c.Assert(err, check.NotNil, check.Commentf(out)) 1947 1948 out, err = s.d.Cmd("start", "test") 1949 c.Assert(err, check.IsNil, check.Commentf(out)) 1950 out, err = s.d.Cmd("start", "-a", "test2") 1951 c.Assert(err, check.IsNil, check.Commentf(out)) 1952 c.Assert(strings.Contains(out, "1 packets transmitted, 1 packets received"), check.Equals, true, check.Commentf(out)) 1953 } 1954 1955 func (s *DockerDaemonSuite) TestDaemonRestartWithNames(c *check.C) { 1956 testRequires(c, DaemonIsLinux) // Windows does not support links 1957 err := s.d.StartWithBusybox() 1958 c.Assert(err, check.IsNil) 1959 1960 out, err := s.d.Cmd("create", "--name=test", "busybox") 1961 c.Assert(err, check.IsNil, check.Commentf(out)) 1962 1963 out, err = s.d.Cmd("run", "-d", "--name=test2", "busybox", "top") 1964 c.Assert(err, check.IsNil, check.Commentf(out)) 1965 test2ID := strings.TrimSpace(out) 1966 1967 out, err = s.d.Cmd("run", "-d", "--name=test3", "--link", "test2:abc", "busybox", "top") 1968 test3ID := strings.TrimSpace(out) 1969 1970 c.Assert(s.d.Restart(), check.IsNil) 1971 1972 out, err = s.d.Cmd("create", "--name=test", "busybox") 1973 c.Assert(err, check.NotNil, check.Commentf("expected error trying to create container with duplicate name")) 1974 // this one is no longer needed, removing simplifies the remainder of the test 1975 out, err = s.d.Cmd("rm", "-f", "test") 1976 c.Assert(err, check.IsNil, check.Commentf(out)) 1977 1978 out, err = s.d.Cmd("ps", "-a", "--no-trunc") 1979 c.Assert(err, check.IsNil, check.Commentf(out)) 1980 1981 lines := strings.Split(strings.TrimSpace(out), "\n")[1:] 1982 1983 test2validated := false 1984 test3validated := false 1985 for _, line := range lines { 1986 fields := strings.Fields(line) 1987 names := fields[len(fields)-1] 1988 switch fields[0] { 1989 case test2ID: 1990 c.Assert(names, check.Equals, "test2,test3/abc") 1991 test2validated = true 1992 case test3ID: 1993 c.Assert(names, check.Equals, "test3") 1994 test3validated = true 1995 } 1996 } 1997 1998 c.Assert(test2validated, check.Equals, true) 1999 c.Assert(test3validated, check.Equals, true) 2000 } 2001 2002 // TestRunLinksChanged checks that creating a new container with the same name does not update links 2003 // this ensures that the old, pre gh#16032 functionality continues on 2004 func (s *DockerDaemonSuite) TestRunLinksChanged(c *check.C) { 2005 testRequires(c, DaemonIsLinux) // Windows does not support links 2006 err := s.d.StartWithBusybox() 2007 c.Assert(err, check.IsNil) 2008 2009 out, err := s.d.Cmd("run", "-d", "--name=test", "busybox", "top") 2010 c.Assert(err, check.IsNil, check.Commentf(out)) 2011 2012 out, err = s.d.Cmd("run", "--name=test2", "--link=test:abc", "busybox", "sh", "-c", "ping -c 1 abc") 2013 c.Assert(err, check.IsNil, check.Commentf(out)) 2014 c.Assert(out, checker.Contains, "1 packets transmitted, 1 packets received") 2015 2016 out, err = s.d.Cmd("rm", "-f", "test") 2017 c.Assert(err, check.IsNil, check.Commentf(out)) 2018 2019 out, err = s.d.Cmd("run", "-d", "--name=test", "busybox", "top") 2020 c.Assert(err, check.IsNil, check.Commentf(out)) 2021 out, err = s.d.Cmd("start", "-a", "test2") 2022 c.Assert(err, check.NotNil, check.Commentf(out)) 2023 c.Assert(out, check.Not(checker.Contains), "1 packets transmitted, 1 packets received") 2024 2025 err = s.d.Restart() 2026 c.Assert(err, check.IsNil) 2027 out, err = s.d.Cmd("start", "-a", "test2") 2028 c.Assert(err, check.NotNil, check.Commentf(out)) 2029 c.Assert(out, check.Not(checker.Contains), "1 packets transmitted, 1 packets received") 2030 } 2031 2032 func (s *DockerDaemonSuite) TestDaemonStartWithoutColors(c *check.C) { 2033 testRequires(c, DaemonIsLinux, NotPpc64le) 2034 newD := NewDaemon(c) 2035 2036 infoLog := "\x1b[34mINFO\x1b" 2037 2038 p, tty, err := pty.Open() 2039 c.Assert(err, checker.IsNil) 2040 defer func() { 2041 tty.Close() 2042 p.Close() 2043 }() 2044 2045 b := bytes.NewBuffer(nil) 2046 go io.Copy(b, p) 2047 2048 // Enable coloring explicitly 2049 newD.StartWithLogFile(tty, "--raw-logs=false") 2050 newD.Stop() 2051 c.Assert(b.String(), checker.Contains, infoLog) 2052 2053 b.Reset() 2054 2055 // Disable coloring explicitly 2056 newD.StartWithLogFile(tty, "--raw-logs=true") 2057 newD.Stop() 2058 c.Assert(b.String(), check.Not(checker.Contains), infoLog) 2059 } 2060 2061 func (s *DockerDaemonSuite) TestDaemonDebugLog(c *check.C) { 2062 testRequires(c, DaemonIsLinux, NotPpc64le) 2063 newD := NewDaemon(c) 2064 2065 debugLog := "\x1b[37mDEBU\x1b" 2066 2067 p, tty, err := pty.Open() 2068 c.Assert(err, checker.IsNil) 2069 defer func() { 2070 tty.Close() 2071 p.Close() 2072 }() 2073 2074 b := bytes.NewBuffer(nil) 2075 go io.Copy(b, p) 2076 2077 newD.StartWithLogFile(tty, "--debug") 2078 newD.Stop() 2079 c.Assert(b.String(), checker.Contains, debugLog) 2080 } 2081 2082 func (s *DockerSuite) TestDaemonDiscoveryBackendConfigReload(c *check.C) { 2083 testRequires(c, SameHostDaemon, DaemonIsLinux) 2084 2085 // daemon config file 2086 daemonConfig := `{ "debug" : false }` 2087 configFilePath := "test.json" 2088 2089 configFile, err := os.Create(configFilePath) 2090 c.Assert(err, checker.IsNil) 2091 fmt.Fprintf(configFile, "%s", daemonConfig) 2092 2093 d := NewDaemon(c) 2094 err = d.Start(fmt.Sprintf("--config-file=%s", configFilePath)) 2095 c.Assert(err, checker.IsNil) 2096 defer d.Stop() 2097 2098 // daemon config file 2099 daemonConfig = `{ 2100 "cluster-store": "consul://consuladdr:consulport/some/path", 2101 "cluster-advertise": "192.168.56.100:0", 2102 "debug" : false 2103 }` 2104 2105 configFile.Close() 2106 os.Remove(configFilePath) 2107 2108 configFile, err = os.Create(configFilePath) 2109 c.Assert(err, checker.IsNil) 2110 defer os.Remove(configFilePath) 2111 fmt.Fprintf(configFile, "%s", daemonConfig) 2112 configFile.Close() 2113 2114 syscall.Kill(d.cmd.Process.Pid, syscall.SIGHUP) 2115 2116 time.Sleep(3 * time.Second) 2117 2118 out, err := d.Cmd("info") 2119 c.Assert(err, checker.IsNil) 2120 c.Assert(out, checker.Contains, fmt.Sprintf("Cluster store: consul://consuladdr:consulport/some/path")) 2121 c.Assert(out, checker.Contains, fmt.Sprintf("Cluster advertise: 192.168.56.100:0")) 2122 }