github.com/nf/docker@v1.8.1/integration-cli/docker_cli_daemon_test.go (about) 1 // +build daemon 2 3 package main 4 5 import ( 6 "encoding/json" 7 "fmt" 8 "io/ioutil" 9 "net" 10 "os" 11 "os/exec" 12 "path/filepath" 13 "regexp" 14 "strconv" 15 "strings" 16 "time" 17 18 "github.com/docker/libnetwork/iptables" 19 "github.com/docker/libtrust" 20 "github.com/go-check/check" 21 ) 22 23 func (s *DockerDaemonSuite) TestDaemonRestartWithRunningContainersPorts(c *check.C) { 24 if err := s.d.StartWithBusybox(); err != nil { 25 c.Fatalf("Could not start daemon with busybox: %v", err) 26 } 27 28 if out, err := s.d.Cmd("run", "-d", "--name", "top1", "-p", "1234:80", "--restart", "always", "busybox:latest", "top"); err != nil { 29 c.Fatalf("Could not run top1: err=%v\n%s", err, out) 30 } 31 // --restart=no by default 32 if out, err := s.d.Cmd("run", "-d", "--name", "top2", "-p", "80", "busybox:latest", "top"); err != nil { 33 c.Fatalf("Could not run top2: err=%v\n%s", err, out) 34 } 35 36 testRun := func(m map[string]bool, prefix string) { 37 var format string 38 for cont, shouldRun := range m { 39 out, err := s.d.Cmd("ps") 40 if err != nil { 41 c.Fatalf("Could not run ps: err=%v\n%q", err, out) 42 } 43 if shouldRun { 44 format = "%scontainer %q is not running" 45 } else { 46 format = "%scontainer %q is running" 47 } 48 if shouldRun != strings.Contains(out, cont) { 49 c.Fatalf(format, prefix, cont) 50 } 51 } 52 } 53 54 testRun(map[string]bool{"top1": true, "top2": true}, "") 55 56 if err := s.d.Restart(); err != nil { 57 c.Fatalf("Could not restart daemon: %v", err) 58 } 59 testRun(map[string]bool{"top1": true, "top2": false}, "After daemon restart: ") 60 } 61 62 func (s *DockerDaemonSuite) TestDaemonRestartWithVolumesRefs(c *check.C) { 63 if err := s.d.StartWithBusybox(); err != nil { 64 c.Fatal(err) 65 } 66 67 if out, err := s.d.Cmd("run", "-d", "--name", "volrestarttest1", "-v", "/foo", "busybox"); err != nil { 68 c.Fatal(err, out) 69 } 70 71 if err := s.d.Restart(); err != nil { 72 c.Fatal(err) 73 } 74 if _, err := s.d.Cmd("run", "-d", "--volumes-from", "volrestarttest1", "--name", "volrestarttest2", "busybox", "top"); err != nil { 75 c.Fatal(err) 76 } 77 78 if out, err := s.d.Cmd("rm", "-fv", "volrestarttest2"); err != nil { 79 c.Fatal(err, out) 80 } 81 82 out, err := s.d.Cmd("inspect", "-f", "{{json .Mounts}}", "volrestarttest1") 83 c.Assert(err, check.IsNil) 84 85 if _, err := inspectMountPointJSON(out, "/foo"); err != nil { 86 c.Fatalf("Expected volume to exist: /foo, error: %v\n", err) 87 } 88 } 89 90 func (s *DockerDaemonSuite) TestDaemonStartIptablesFalse(c *check.C) { 91 if err := s.d.Start("--iptables=false"); err != nil { 92 c.Fatalf("we should have been able to start the daemon with passing iptables=false: %v", err) 93 } 94 } 95 96 // Issue #8444: If docker0 bridge is modified (intentionally or unintentionally) and 97 // no longer has an IP associated, we should gracefully handle that case and associate 98 // an IP with it rather than fail daemon start 99 func (s *DockerDaemonSuite) TestDaemonStartBridgeWithoutIPAssociation(c *check.C) { 100 // rather than depending on brctl commands to verify docker0 is created and up 101 // let's start the daemon and stop it, and then make a modification to run the 102 // actual test 103 if err := s.d.Start(); err != nil { 104 c.Fatalf("Could not start daemon: %v", err) 105 } 106 if err := s.d.Stop(); err != nil { 107 c.Fatalf("Could not stop daemon: %v", err) 108 } 109 110 // now we will remove the ip from docker0 and then try starting the daemon 111 ipCmd := exec.Command("ip", "addr", "flush", "dev", "docker0") 112 stdout, stderr, _, err := runCommandWithStdoutStderr(ipCmd) 113 if err != nil { 114 c.Fatalf("failed to remove docker0 IP association: %v, stdout: %q, stderr: %q", err, stdout, stderr) 115 } 116 117 if err := s.d.Start(); err != nil { 118 warning := "**WARNING: Docker bridge network in bad state--delete docker0 bridge interface to fix" 119 c.Fatalf("Could not start daemon when docker0 has no IP address: %v\n%s", err, warning) 120 } 121 } 122 123 func (s *DockerDaemonSuite) TestDaemonIptablesClean(c *check.C) { 124 if err := s.d.StartWithBusybox(); err != nil { 125 c.Fatalf("Could not start daemon with busybox: %v", err) 126 } 127 128 if out, err := s.d.Cmd("run", "-d", "--name", "top", "-p", "80", "busybox:latest", "top"); err != nil { 129 c.Fatalf("Could not run top: %s, %v", out, err) 130 } 131 132 // get output from iptables with container running 133 ipTablesSearchString := "tcp dpt:80" 134 ipTablesCmd := exec.Command("iptables", "-nvL") 135 out, _, err := runCommandWithOutput(ipTablesCmd) 136 if err != nil { 137 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 138 } 139 140 if !strings.Contains(out, ipTablesSearchString) { 141 c.Fatalf("iptables output should have contained %q, but was %q", ipTablesSearchString, out) 142 } 143 144 if err := s.d.Stop(); err != nil { 145 c.Fatalf("Could not stop daemon: %v", err) 146 } 147 148 // get output from iptables after restart 149 ipTablesCmd = exec.Command("iptables", "-nvL") 150 out, _, err = runCommandWithOutput(ipTablesCmd) 151 if err != nil { 152 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 153 } 154 155 if strings.Contains(out, ipTablesSearchString) { 156 c.Fatalf("iptables output should not have contained %q, but was %q", ipTablesSearchString, out) 157 } 158 } 159 160 func (s *DockerDaemonSuite) TestDaemonIptablesCreate(c *check.C) { 161 if err := s.d.StartWithBusybox(); err != nil { 162 c.Fatalf("Could not start daemon with busybox: %v", err) 163 } 164 165 if out, err := s.d.Cmd("run", "-d", "--name", "top", "--restart=always", "-p", "80", "busybox:latest", "top"); err != nil { 166 c.Fatalf("Could not run top: %s, %v", out, err) 167 } 168 169 // get output from iptables with container running 170 ipTablesSearchString := "tcp dpt:80" 171 ipTablesCmd := exec.Command("iptables", "-nvL") 172 out, _, err := runCommandWithOutput(ipTablesCmd) 173 if err != nil { 174 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 175 } 176 177 if !strings.Contains(out, ipTablesSearchString) { 178 c.Fatalf("iptables output should have contained %q, but was %q", ipTablesSearchString, out) 179 } 180 181 if err := s.d.Restart(); err != nil { 182 c.Fatalf("Could not restart daemon: %v", err) 183 } 184 185 // make sure the container is not running 186 runningOut, err := s.d.Cmd("inspect", "--format='{{.State.Running}}'", "top") 187 if err != nil { 188 c.Fatalf("Could not inspect on container: %s, %v", out, err) 189 } 190 if strings.TrimSpace(runningOut) != "true" { 191 c.Fatalf("Container should have been restarted after daemon restart. Status running should have been true but was: %q", strings.TrimSpace(runningOut)) 192 } 193 194 // get output from iptables after restart 195 ipTablesCmd = exec.Command("iptables", "-nvL") 196 out, _, err = runCommandWithOutput(ipTablesCmd) 197 if err != nil { 198 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 199 } 200 201 if !strings.Contains(out, ipTablesSearchString) { 202 c.Fatalf("iptables output after restart should have contained %q, but was %q", ipTablesSearchString, out) 203 } 204 } 205 206 // TestDaemonIPv6Enabled checks that when the daemon is started with --ipv6=true that the docker0 bridge 207 // has the fe80::1 address and that a container is assigned a link-local address 208 func (s *DockerSuite) TestDaemonIPv6Enabled(c *check.C) { 209 testRequires(c, IPv6) 210 211 if err := setupV6(); err != nil { 212 c.Fatal("Could not set up host for IPv6 tests") 213 } 214 215 d := NewDaemon(c) 216 217 if err := d.StartWithBusybox("--ipv6"); err != nil { 218 c.Fatal(err) 219 } 220 defer d.Stop() 221 222 iface, err := net.InterfaceByName("docker0") 223 if err != nil { 224 c.Fatalf("Error getting docker0 interface: %v", err) 225 } 226 227 addrs, err := iface.Addrs() 228 if err != nil { 229 c.Fatalf("Error getting addresses for docker0 interface: %v", err) 230 } 231 232 var found bool 233 expected := "fe80::1/64" 234 235 for i := range addrs { 236 if addrs[i].String() == expected { 237 found = true 238 } 239 } 240 241 if !found { 242 c.Fatalf("Bridge does not have an IPv6 Address") 243 } 244 245 if out, err := d.Cmd("run", "-itd", "--name=ipv6test", "busybox:latest"); err != nil { 246 c.Fatalf("Could not run container: %s, %v", out, err) 247 } 248 249 out, err := d.Cmd("inspect", "--format", "'{{.NetworkSettings.LinkLocalIPv6Address}}'", "ipv6test") 250 out = strings.Trim(out, " \r\n'") 251 252 if err != nil { 253 c.Fatalf("Error inspecting container: %s, %v", out, err) 254 } 255 256 if ip := net.ParseIP(out); ip == nil { 257 c.Fatalf("Container should have a link-local IPv6 address") 258 } 259 260 out, err = d.Cmd("inspect", "--format", "'{{.NetworkSettings.GlobalIPv6Address}}'", "ipv6test") 261 out = strings.Trim(out, " \r\n'") 262 263 if err != nil { 264 c.Fatalf("Error inspecting container: %s, %v", out, err) 265 } 266 267 if ip := net.ParseIP(out); ip != nil { 268 c.Fatalf("Container should not have a global IPv6 address: %v", out) 269 } 270 271 if err := teardownV6(); err != nil { 272 c.Fatal("Could not perform teardown for IPv6 tests") 273 } 274 275 } 276 277 // TestDaemonIPv6FixedCIDR checks that when the daemon is started with --ipv6=true and a fixed CIDR 278 // that running containers are given a link-local and global IPv6 address 279 func (s *DockerSuite) TestDaemonIPv6FixedCIDR(c *check.C) { 280 testRequires(c, IPv6) 281 282 if err := setupV6(); err != nil { 283 c.Fatal("Could not set up host for IPv6 tests") 284 } 285 286 d := NewDaemon(c) 287 288 if err := d.StartWithBusybox("--ipv6", "--fixed-cidr-v6='2001:db8:1::/64'"); err != nil { 289 c.Fatalf("Could not start daemon with busybox: %v", err) 290 } 291 defer d.Stop() 292 293 if out, err := d.Cmd("run", "-itd", "--name=ipv6test", "busybox:latest"); err != nil { 294 c.Fatalf("Could not run container: %s, %v", out, err) 295 } 296 297 out, err := d.Cmd("inspect", "--format", "'{{.NetworkSettings.LinkLocalIPv6Address}}'", "ipv6test") 298 out = strings.Trim(out, " \r\n'") 299 300 if err != nil { 301 c.Fatalf("Error inspecting container: %s, %v", out, err) 302 } 303 304 if ip := net.ParseIP(out); ip == nil { 305 c.Fatalf("Container should have a link-local IPv6 address") 306 } 307 308 out, err = d.Cmd("inspect", "--format", "'{{.NetworkSettings.GlobalIPv6Address}}'", "ipv6test") 309 out = strings.Trim(out, " \r\n'") 310 311 if err != nil { 312 c.Fatalf("Error inspecting container: %s, %v", out, err) 313 } 314 315 if ip := net.ParseIP(out); ip == nil { 316 c.Fatalf("Container should have a global IPv6 address") 317 } 318 if err := teardownV6(); err != nil { 319 c.Fatal("Could not perform teardown for IPv6 tests") 320 } 321 } 322 323 func (s *DockerDaemonSuite) TestDaemonLogLevelWrong(c *check.C) { 324 c.Assert(s.d.Start("--log-level=bogus"), check.NotNil, check.Commentf("Daemon shouldn't start with wrong log level")) 325 } 326 327 func (s *DockerSuite) TestDaemonStartWithBackwardCompatibility(c *check.C) { 328 329 var validCommandArgs = [][]string{ 330 {"--selinux-enabled", "-l", "info"}, 331 {"--insecure-registry", "daemon"}, 332 } 333 334 var invalidCommandArgs = [][]string{ 335 {"--selinux-enabled", "--storage-opt"}, 336 {"-D", "-b"}, 337 {"--config", "/tmp"}, 338 } 339 340 for _, args := range validCommandArgs { 341 d := NewDaemon(c) 342 d.Command = "--daemon" 343 if err := d.Start(args...); err != nil { 344 c.Fatalf("Daemon should have started successfully with --daemon %v: %v", args, err) 345 } 346 d.Stop() 347 } 348 349 for _, args := range invalidCommandArgs { 350 d := NewDaemon(c) 351 if err := d.Start(args...); err == nil { 352 d.Stop() 353 c.Fatalf("Daemon should have failed to start with %v", args) 354 } 355 } 356 } 357 358 func (s *DockerSuite) TestDaemonStartWithDaemonCommand(c *check.C) { 359 360 type kind int 361 362 const ( 363 common kind = iota 364 daemon 365 ) 366 367 var flags = []map[kind][]string{ 368 {common: {"-l", "info"}, daemon: {"--selinux-enabled"}}, 369 {common: {"-D"}, daemon: {"--selinux-enabled", "-r"}}, 370 {common: {"-D"}, daemon: {"--restart"}}, 371 {common: {"--debug"}, daemon: {"--log-driver=json-file", "--log-opt=max-size=1k"}}, 372 } 373 374 var invalidGlobalFlags = [][]string{ 375 //Invalid because you cannot pass daemon flags as global flags. 376 {"--selinux-enabled", "-l", "info"}, 377 {"-D", "-r"}, 378 {"--config", "/tmp"}, 379 } 380 381 // `docker daemon -l info --selinux-enabled` 382 // should NOT error out 383 for _, f := range flags { 384 d := NewDaemon(c) 385 args := append(f[common], f[daemon]...) 386 if err := d.Start(args...); err != nil { 387 c.Fatalf("Daemon should have started successfully with %v: %v", args, err) 388 } 389 d.Stop() 390 } 391 392 // `docker -l info daemon --selinux-enabled` 393 // should error out 394 for _, f := range flags { 395 d := NewDaemon(c) 396 d.GlobalFlags = f[common] 397 if err := d.Start(f[daemon]...); err == nil { 398 d.Stop() 399 c.Fatalf("Daemon should have failed to start with docker %v daemon %v", d.GlobalFlags, f[daemon]) 400 } 401 } 402 403 for _, f := range invalidGlobalFlags { 404 cmd := exec.Command(dockerBinary, append(f, "daemon")...) 405 errch := make(chan error) 406 var err error 407 go func() { 408 errch <- cmd.Run() 409 }() 410 select { 411 case <-time.After(time.Second): 412 cmd.Process.Kill() 413 case err = <-errch: 414 } 415 if err == nil { 416 c.Fatalf("Daemon should have failed to start with docker %v daemon", f) 417 } 418 } 419 } 420 421 func (s *DockerDaemonSuite) TestDaemonLogLevelDebug(c *check.C) { 422 if err := s.d.Start("--log-level=debug"); err != nil { 423 c.Fatal(err) 424 } 425 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 426 if !strings.Contains(string(content), `level=debug`) { 427 c.Fatalf(`Missing level="debug" in log file:\n%s`, string(content)) 428 } 429 } 430 431 func (s *DockerDaemonSuite) TestDaemonLogLevelFatal(c *check.C) { 432 // we creating new daemons to create new logFile 433 if err := s.d.Start("--log-level=fatal"); err != nil { 434 c.Fatal(err) 435 } 436 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 437 if strings.Contains(string(content), `level=debug`) { 438 c.Fatalf(`Should not have level="debug" in log file:\n%s`, string(content)) 439 } 440 } 441 442 func (s *DockerDaemonSuite) TestDaemonFlagD(c *check.C) { 443 if err := s.d.Start("-D"); err != nil { 444 c.Fatal(err) 445 } 446 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 447 if !strings.Contains(string(content), `level=debug`) { 448 c.Fatalf(`Should have level="debug" in log file using -D:\n%s`, string(content)) 449 } 450 } 451 452 func (s *DockerDaemonSuite) TestDaemonFlagDebug(c *check.C) { 453 if err := s.d.Start("--debug"); err != nil { 454 c.Fatal(err) 455 } 456 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 457 if !strings.Contains(string(content), `level=debug`) { 458 c.Fatalf(`Should have level="debug" in log file using --debug:\n%s`, string(content)) 459 } 460 } 461 462 func (s *DockerDaemonSuite) TestDaemonFlagDebugLogLevelFatal(c *check.C) { 463 if err := s.d.Start("--debug", "--log-level=fatal"); err != nil { 464 c.Fatal(err) 465 } 466 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 467 if !strings.Contains(string(content), `level=debug`) { 468 c.Fatalf(`Should have level="debug" in log file when using both --debug and --log-level=fatal:\n%s`, string(content)) 469 } 470 } 471 472 func (s *DockerDaemonSuite) TestDaemonAllocatesListeningPort(c *check.C) { 473 listeningPorts := [][]string{ 474 {"0.0.0.0", "0.0.0.0", "5678"}, 475 {"127.0.0.1", "127.0.0.1", "1234"}, 476 {"localhost", "127.0.0.1", "1235"}, 477 } 478 479 cmdArgs := make([]string, 0, len(listeningPorts)*2) 480 for _, hostDirective := range listeningPorts { 481 cmdArgs = append(cmdArgs, "--host", fmt.Sprintf("tcp://%s:%s", hostDirective[0], hostDirective[2])) 482 } 483 484 if err := s.d.StartWithBusybox(cmdArgs...); err != nil { 485 c.Fatalf("Could not start daemon with busybox: %v", err) 486 } 487 488 for _, hostDirective := range listeningPorts { 489 output, err := s.d.Cmd("run", "-p", fmt.Sprintf("%s:%s:80", hostDirective[1], hostDirective[2]), "busybox", "true") 490 if err == nil { 491 c.Fatalf("Container should not start, expected port already allocated error: %q", output) 492 } else if !strings.Contains(output, "port is already allocated") { 493 c.Fatalf("Expected port is already allocated error: %q", output) 494 } 495 } 496 } 497 498 func (s *DockerDaemonSuite) TestDaemonKeyGeneration(c *check.C) { 499 // TODO: skip or update for Windows daemon 500 os.Remove("/etc/docker/key.json") 501 if err := s.d.Start(); err != nil { 502 c.Fatalf("Could not start daemon: %v", err) 503 } 504 s.d.Stop() 505 506 k, err := libtrust.LoadKeyFile("/etc/docker/key.json") 507 if err != nil { 508 c.Fatalf("Error opening key file") 509 } 510 kid := k.KeyID() 511 // Test Key ID is a valid fingerprint (e.g. QQXN:JY5W:TBXI:MK3X:GX6P:PD5D:F56N:NHCS:LVRZ:JA46:R24J:XEFF) 512 if len(kid) != 59 { 513 c.Fatalf("Bad key ID: %s", kid) 514 } 515 } 516 517 func (s *DockerDaemonSuite) TestDaemonKeyMigration(c *check.C) { 518 // TODO: skip or update for Windows daemon 519 os.Remove("/etc/docker/key.json") 520 k1, err := libtrust.GenerateECP256PrivateKey() 521 if err != nil { 522 c.Fatalf("Error generating private key: %s", err) 523 } 524 if err := os.MkdirAll(filepath.Join(os.Getenv("HOME"), ".docker"), 0755); err != nil { 525 c.Fatalf("Error creating .docker directory: %s", err) 526 } 527 if err := libtrust.SaveKey(filepath.Join(os.Getenv("HOME"), ".docker", "key.json"), k1); err != nil { 528 c.Fatalf("Error saving private key: %s", err) 529 } 530 531 if err := s.d.Start(); err != nil { 532 c.Fatalf("Could not start daemon: %v", err) 533 } 534 s.d.Stop() 535 536 k2, err := libtrust.LoadKeyFile("/etc/docker/key.json") 537 if err != nil { 538 c.Fatalf("Error opening key file") 539 } 540 if k1.KeyID() != k2.KeyID() { 541 c.Fatalf("Key not migrated") 542 } 543 } 544 545 // GH#11320 - verify that the daemon exits on failure properly 546 // Note that this explicitly tests the conflict of {-b,--bridge} and {--bip} options as the means 547 // to get a daemon init failure; no other tests for -b/--bip conflict are therefore required 548 func (s *DockerDaemonSuite) TestDaemonExitOnFailure(c *check.C) { 549 //attempt to start daemon with incorrect flags (we know -b and --bip conflict) 550 if err := s.d.Start("--bridge", "nosuchbridge", "--bip", "1.1.1.1"); err != nil { 551 //verify we got the right error 552 if !strings.Contains(err.Error(), "Daemon exited and never started") { 553 c.Fatalf("Expected daemon not to start, got %v", err) 554 } 555 // look in the log and make sure we got the message that daemon is shutting down 556 runCmd := exec.Command("grep", "Error starting daemon", s.d.LogfileName()) 557 if out, _, err := runCommandWithOutput(runCmd); err != nil { 558 c.Fatalf("Expected 'Error starting daemon' message; but doesn't exist in log: %q, err: %v", out, err) 559 } 560 } else { 561 //if we didn't get an error and the daemon is running, this is a failure 562 c.Fatal("Conflicting options should cause the daemon to error out with a failure") 563 } 564 } 565 566 func (s *DockerDaemonSuite) TestDaemonBridgeExternal(c *check.C) { 567 d := s.d 568 err := d.Start("--bridge", "nosuchbridge") 569 c.Assert(err, check.NotNil, check.Commentf("--bridge option with an invalid bridge should cause the daemon to fail")) 570 defer d.Restart() 571 572 bridgeName := "external-bridge" 573 bridgeIP := "192.169.1.1/24" 574 _, bridgeIPNet, _ := net.ParseCIDR(bridgeIP) 575 576 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 577 c.Assert(err, check.IsNil, check.Commentf(out)) 578 defer deleteInterface(c, bridgeName) 579 580 err = d.StartWithBusybox("--bridge", bridgeName) 581 c.Assert(err, check.IsNil) 582 583 ipTablesSearchString := bridgeIPNet.String() 584 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 585 out, _, err = runCommandWithOutput(ipTablesCmd) 586 c.Assert(err, check.IsNil) 587 588 c.Assert(strings.Contains(out, ipTablesSearchString), check.Equals, true, 589 check.Commentf("iptables output should have contained %q, but was %q", 590 ipTablesSearchString, out)) 591 592 _, err = d.Cmd("run", "-d", "--name", "ExtContainer", "busybox", "top") 593 c.Assert(err, check.IsNil) 594 595 containerIP := d.findContainerIP("ExtContainer") 596 ip := net.ParseIP(containerIP) 597 c.Assert(bridgeIPNet.Contains(ip), check.Equals, true, 598 check.Commentf("Container IP-Address must be in the same subnet range : %s", 599 containerIP)) 600 } 601 602 func createInterface(c *check.C, ifType string, ifName string, ipNet string) (string, error) { 603 args := []string{"link", "add", "name", ifName, "type", ifType} 604 ipLinkCmd := exec.Command("ip", args...) 605 out, _, err := runCommandWithOutput(ipLinkCmd) 606 if err != nil { 607 return out, err 608 } 609 610 ifCfgCmd := exec.Command("ifconfig", ifName, ipNet, "up") 611 out, _, err = runCommandWithOutput(ifCfgCmd) 612 return out, err 613 } 614 615 func deleteInterface(c *check.C, ifName string) { 616 ifCmd := exec.Command("ip", "link", "delete", ifName) 617 out, _, err := runCommandWithOutput(ifCmd) 618 c.Assert(err, check.IsNil, check.Commentf(out)) 619 620 flushCmd := exec.Command("iptables", "-t", "nat", "--flush") 621 out, _, err = runCommandWithOutput(flushCmd) 622 c.Assert(err, check.IsNil, check.Commentf(out)) 623 624 flushCmd = exec.Command("iptables", "--flush") 625 out, _, err = runCommandWithOutput(flushCmd) 626 c.Assert(err, check.IsNil, check.Commentf(out)) 627 } 628 629 func (s *DockerDaemonSuite) TestDaemonBridgeIP(c *check.C) { 630 // TestDaemonBridgeIP Steps 631 // 1. Delete the existing docker0 Bridge 632 // 2. Set --bip daemon configuration and start the new Docker Daemon 633 // 3. Check if the bip config has taken effect using ifconfig and iptables commands 634 // 4. Launch a Container and make sure the IP-Address is in the expected subnet 635 // 5. Delete the docker0 Bridge 636 // 6. Restart the Docker Daemon (via defered action) 637 // This Restart takes care of bringing docker0 interface back to auto-assigned IP 638 639 defaultNetworkBridge := "docker0" 640 deleteInterface(c, defaultNetworkBridge) 641 642 d := s.d 643 644 bridgeIP := "192.169.1.1/24" 645 ip, bridgeIPNet, _ := net.ParseCIDR(bridgeIP) 646 647 err := d.StartWithBusybox("--bip", bridgeIP) 648 c.Assert(err, check.IsNil) 649 defer d.Restart() 650 651 ifconfigSearchString := ip.String() 652 ifconfigCmd := exec.Command("ifconfig", defaultNetworkBridge) 653 out, _, _, err := runCommandWithStdoutStderr(ifconfigCmd) 654 c.Assert(err, check.IsNil) 655 656 c.Assert(strings.Contains(out, ifconfigSearchString), check.Equals, true, 657 check.Commentf("ifconfig output should have contained %q, but was %q", 658 ifconfigSearchString, out)) 659 660 ipTablesSearchString := bridgeIPNet.String() 661 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 662 out, _, err = runCommandWithOutput(ipTablesCmd) 663 c.Assert(err, check.IsNil) 664 665 c.Assert(strings.Contains(out, ipTablesSearchString), check.Equals, true, 666 check.Commentf("iptables output should have contained %q, but was %q", 667 ipTablesSearchString, out)) 668 669 out, err = d.Cmd("run", "-d", "--name", "test", "busybox", "top") 670 c.Assert(err, check.IsNil) 671 672 containerIP := d.findContainerIP("test") 673 ip = net.ParseIP(containerIP) 674 c.Assert(bridgeIPNet.Contains(ip), check.Equals, true, 675 check.Commentf("Container IP-Address must be in the same subnet range : %s", 676 containerIP)) 677 deleteInterface(c, defaultNetworkBridge) 678 } 679 680 func (s *DockerDaemonSuite) TestDaemonRestartWithBridgeIPChange(c *check.C) { 681 if err := s.d.Start(); err != nil { 682 c.Fatalf("Could not start daemon: %v", err) 683 } 684 defer s.d.Restart() 685 if err := s.d.Stop(); err != nil { 686 c.Fatalf("Could not stop daemon: %v", err) 687 } 688 689 // now we will change the docker0's IP and then try starting the daemon 690 bridgeIP := "192.169.100.1/24" 691 _, bridgeIPNet, _ := net.ParseCIDR(bridgeIP) 692 693 ipCmd := exec.Command("ifconfig", "docker0", bridgeIP) 694 stdout, stderr, _, err := runCommandWithStdoutStderr(ipCmd) 695 if err != nil { 696 c.Fatalf("failed to change docker0's IP association: %v, stdout: %q, stderr: %q", err, stdout, stderr) 697 } 698 699 if err := s.d.Start("--bip", bridgeIP); err != nil { 700 c.Fatalf("Could not start daemon: %v", err) 701 } 702 703 //check if the iptables contains new bridgeIP MASQUERADE rule 704 ipTablesSearchString := bridgeIPNet.String() 705 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 706 out, _, err := runCommandWithOutput(ipTablesCmd) 707 if err != nil { 708 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 709 } 710 if !strings.Contains(out, ipTablesSearchString) { 711 c.Fatalf("iptables output should have contained new MASQUERADE rule with IP %q, but was %q", ipTablesSearchString, out) 712 } 713 } 714 715 func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr(c *check.C) { 716 d := s.d 717 718 bridgeName := "external-bridge" 719 bridgeIP := "192.169.1.1/24" 720 721 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 722 c.Assert(err, check.IsNil, check.Commentf(out)) 723 defer deleteInterface(c, bridgeName) 724 725 args := []string{"--bridge", bridgeName, "--fixed-cidr", "192.169.1.0/30"} 726 err = d.StartWithBusybox(args...) 727 c.Assert(err, check.IsNil) 728 defer d.Restart() 729 730 for i := 0; i < 4; i++ { 731 cName := "Container" + strconv.Itoa(i) 732 out, err := d.Cmd("run", "-d", "--name", cName, "busybox", "top") 733 if err != nil { 734 c.Assert(strings.Contains(out, "no available ip addresses"), check.Equals, true, 735 check.Commentf("Could not run a Container : %s %s", err.Error(), out)) 736 } 737 } 738 } 739 740 func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4Implicit(c *check.C) { 741 defaultNetworkBridge := "docker0" 742 deleteInterface(c, defaultNetworkBridge) 743 744 d := s.d 745 746 bridgeIP := "192.169.1.1" 747 bridgeIPNet := fmt.Sprintf("%s/24", bridgeIP) 748 749 err := d.StartWithBusybox("--bip", bridgeIPNet) 750 c.Assert(err, check.IsNil) 751 defer d.Restart() 752 753 expectedMessage := fmt.Sprintf("default via %s dev", bridgeIP) 754 out, err := d.Cmd("run", "busybox", "ip", "-4", "route", "list", "0/0") 755 c.Assert(strings.Contains(out, expectedMessage), check.Equals, true, 756 check.Commentf("Implicit default gateway should be bridge IP %s, but default route was '%s'", 757 bridgeIP, strings.TrimSpace(out))) 758 deleteInterface(c, defaultNetworkBridge) 759 } 760 761 func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4Explicit(c *check.C) { 762 defaultNetworkBridge := "docker0" 763 deleteInterface(c, defaultNetworkBridge) 764 765 d := s.d 766 767 bridgeIP := "192.169.1.1" 768 bridgeIPNet := fmt.Sprintf("%s/24", bridgeIP) 769 gatewayIP := "192.169.1.254" 770 771 err := d.StartWithBusybox("--bip", bridgeIPNet, "--default-gateway", gatewayIP) 772 c.Assert(err, check.IsNil) 773 defer d.Restart() 774 775 expectedMessage := fmt.Sprintf("default via %s dev", gatewayIP) 776 out, err := d.Cmd("run", "busybox", "ip", "-4", "route", "list", "0/0") 777 c.Assert(strings.Contains(out, expectedMessage), check.Equals, true, 778 check.Commentf("Explicit default gateway should be %s, but default route was '%s'", 779 gatewayIP, strings.TrimSpace(out))) 780 deleteInterface(c, defaultNetworkBridge) 781 } 782 783 func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4ExplicitOutsideContainerSubnet(c *check.C) { 784 defaultNetworkBridge := "docker0" 785 deleteInterface(c, defaultNetworkBridge) 786 787 // Program a custom default gateway outside of the container subnet, daemon should accept it and start 788 err := s.d.StartWithBusybox("--bip", "172.16.0.10/16", "--fixed-cidr", "172.16.1.0/24", "--default-gateway", "172.16.0.254") 789 c.Assert(err, check.IsNil) 790 791 deleteInterface(c, defaultNetworkBridge) 792 s.d.Restart() 793 } 794 795 func (s *DockerDaemonSuite) TestDaemonIP(c *check.C) { 796 d := s.d 797 798 ipStr := "192.170.1.1/24" 799 ip, _, _ := net.ParseCIDR(ipStr) 800 args := []string{"--ip", ip.String()} 801 err := d.StartWithBusybox(args...) 802 c.Assert(err, check.IsNil) 803 defer d.Restart() 804 805 out, err := d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top") 806 c.Assert(err, check.NotNil, 807 check.Commentf("Running a container must fail with an invalid --ip option")) 808 c.Assert(strings.Contains(out, "Error starting userland proxy"), check.Equals, true) 809 810 ifName := "dummy" 811 out, err = createInterface(c, "dummy", ifName, ipStr) 812 c.Assert(err, check.IsNil, check.Commentf(out)) 813 defer deleteInterface(c, ifName) 814 815 _, err = d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top") 816 c.Assert(err, check.IsNil) 817 818 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 819 out, _, err = runCommandWithOutput(ipTablesCmd) 820 c.Assert(err, check.IsNil) 821 822 regex := fmt.Sprintf("DNAT.*%s.*dpt:8000", ip.String()) 823 matched, _ := regexp.MatchString(regex, out) 824 c.Assert(matched, check.Equals, true, 825 check.Commentf("iptables output should have contained %q, but was %q", regex, out)) 826 } 827 828 func (s *DockerDaemonSuite) TestDaemonICCPing(c *check.C) { 829 d := s.d 830 831 bridgeName := "external-bridge" 832 bridgeIP := "192.169.1.1/24" 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 args := []string{"--bridge", bridgeName, "--icc=false"} 839 err = d.StartWithBusybox(args...) 840 c.Assert(err, check.IsNil) 841 defer d.Restart() 842 843 ipTablesCmd := exec.Command("iptables", "-nvL", "FORWARD") 844 out, _, err = runCommandWithOutput(ipTablesCmd) 845 c.Assert(err, check.IsNil) 846 847 regex := fmt.Sprintf("DROP.*all.*%s.*%s", bridgeName, bridgeName) 848 matched, _ := regexp.MatchString(regex, out) 849 c.Assert(matched, check.Equals, true, 850 check.Commentf("iptables output should have contained %q, but was %q", regex, out)) 851 852 // Pinging another container must fail with --icc=false 853 pingContainers(c, d, true) 854 855 ipStr := "192.171.1.1/24" 856 ip, _, _ := net.ParseCIDR(ipStr) 857 ifName := "icc-dummy" 858 859 createInterface(c, "dummy", ifName, ipStr) 860 861 // But, Pinging external or a Host interface must succeed 862 pingCmd := fmt.Sprintf("ping -c 1 %s -W 1", ip.String()) 863 runArgs := []string{"--rm", "busybox", "sh", "-c", pingCmd} 864 _, err = d.Cmd("run", runArgs...) 865 c.Assert(err, check.IsNil) 866 } 867 868 func (s *DockerDaemonSuite) TestDaemonICCLinkExpose(c *check.C) { 869 d := s.d 870 871 bridgeName := "external-bridge" 872 bridgeIP := "192.169.1.1/24" 873 874 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 875 c.Assert(err, check.IsNil, check.Commentf(out)) 876 defer deleteInterface(c, bridgeName) 877 878 args := []string{"--bridge", bridgeName, "--icc=false"} 879 err = d.StartWithBusybox(args...) 880 c.Assert(err, check.IsNil) 881 defer d.Restart() 882 883 ipTablesCmd := exec.Command("iptables", "-nvL", "FORWARD") 884 out, _, err = runCommandWithOutput(ipTablesCmd) 885 c.Assert(err, check.IsNil) 886 887 regex := fmt.Sprintf("DROP.*all.*%s.*%s", bridgeName, bridgeName) 888 matched, _ := regexp.MatchString(regex, out) 889 c.Assert(matched, check.Equals, true, 890 check.Commentf("iptables output should have contained %q, but was %q", regex, out)) 891 892 out, err = d.Cmd("run", "-d", "--expose", "4567", "--name", "icc1", "busybox", "nc", "-l", "-p", "4567") 893 c.Assert(err, check.IsNil, check.Commentf(out)) 894 895 out, err = d.Cmd("run", "--link", "icc1:icc1", "busybox", "nc", "icc1", "4567") 896 c.Assert(err, check.IsNil, check.Commentf(out)) 897 } 898 899 func (s *DockerDaemonSuite) TestDaemonLinksIpTablesRulesWhenLinkAndUnlink(c *check.C) { 900 bridgeName := "external-bridge" 901 bridgeIP := "192.169.1.1/24" 902 903 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 904 c.Assert(err, check.IsNil, check.Commentf(out)) 905 defer deleteInterface(c, bridgeName) 906 907 err = s.d.StartWithBusybox("--bridge", bridgeName, "--icc=false") 908 c.Assert(err, check.IsNil) 909 defer s.d.Restart() 910 911 _, err = s.d.Cmd("run", "-d", "--name", "child", "--publish", "8080:80", "busybox", "top") 912 c.Assert(err, check.IsNil) 913 _, err = s.d.Cmd("run", "-d", "--name", "parent", "--link", "child:http", "busybox", "top") 914 c.Assert(err, check.IsNil) 915 916 childIP := s.d.findContainerIP("child") 917 parentIP := s.d.findContainerIP("parent") 918 919 sourceRule := []string{"-i", bridgeName, "-o", bridgeName, "-p", "tcp", "-s", childIP, "--sport", "80", "-d", parentIP, "-j", "ACCEPT"} 920 destinationRule := []string{"-i", bridgeName, "-o", bridgeName, "-p", "tcp", "-s", parentIP, "--dport", "80", "-d", childIP, "-j", "ACCEPT"} 921 if !iptables.Exists("filter", "DOCKER", sourceRule...) || !iptables.Exists("filter", "DOCKER", destinationRule...) { 922 c.Fatal("Iptables rules not found") 923 } 924 925 s.d.Cmd("rm", "--link", "parent/http") 926 if iptables.Exists("filter", "DOCKER", sourceRule...) || iptables.Exists("filter", "DOCKER", destinationRule...) { 927 c.Fatal("Iptables rules should be removed when unlink") 928 } 929 930 s.d.Cmd("kill", "child") 931 s.d.Cmd("kill", "parent") 932 } 933 934 func (s *DockerDaemonSuite) TestDaemonUlimitDefaults(c *check.C) { 935 testRequires(c, NativeExecDriver) 936 937 if err := s.d.StartWithBusybox("--default-ulimit", "nofile=42:42", "--default-ulimit", "nproc=1024:1024"); err != nil { 938 c.Fatal(err) 939 } 940 941 out, err := s.d.Cmd("run", "--ulimit", "nproc=2048", "--name=test", "busybox", "/bin/sh", "-c", "echo $(ulimit -n); echo $(ulimit -p)") 942 if err != nil { 943 c.Fatal(out, err) 944 } 945 946 outArr := strings.Split(out, "\n") 947 if len(outArr) < 2 { 948 c.Fatalf("got unexpected output: %s", out) 949 } 950 nofile := strings.TrimSpace(outArr[0]) 951 nproc := strings.TrimSpace(outArr[1]) 952 953 if nofile != "42" { 954 c.Fatalf("expected `ulimit -n` to be `42`, got: %s", nofile) 955 } 956 if nproc != "2048" { 957 c.Fatalf("exepcted `ulimit -p` to be 2048, got: %s", nproc) 958 } 959 960 // Now restart daemon with a new default 961 if err := s.d.Restart("--default-ulimit", "nofile=43"); err != nil { 962 c.Fatal(err) 963 } 964 965 out, err = s.d.Cmd("start", "-a", "test") 966 if err != nil { 967 c.Fatal(err) 968 } 969 970 outArr = strings.Split(out, "\n") 971 if len(outArr) < 2 { 972 c.Fatalf("got unexpected output: %s", out) 973 } 974 nofile = strings.TrimSpace(outArr[0]) 975 nproc = strings.TrimSpace(outArr[1]) 976 977 if nofile != "43" { 978 c.Fatalf("expected `ulimit -n` to be `43`, got: %s", nofile) 979 } 980 if nproc != "2048" { 981 c.Fatalf("exepcted `ulimit -p` to be 2048, got: %s", nproc) 982 } 983 } 984 985 // #11315 986 func (s *DockerDaemonSuite) TestDaemonRestartRenameContainer(c *check.C) { 987 if err := s.d.StartWithBusybox(); err != nil { 988 c.Fatal(err) 989 } 990 991 if out, err := s.d.Cmd("run", "--name=test", "busybox"); err != nil { 992 c.Fatal(err, out) 993 } 994 995 if out, err := s.d.Cmd("rename", "test", "test2"); err != nil { 996 c.Fatal(err, out) 997 } 998 999 if err := s.d.Restart(); err != nil { 1000 c.Fatal(err) 1001 } 1002 1003 if out, err := s.d.Cmd("start", "test2"); err != nil { 1004 c.Fatal(err, out) 1005 } 1006 } 1007 1008 func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefault(c *check.C) { 1009 if err := s.d.StartWithBusybox(); err != nil { 1010 c.Fatal(err) 1011 } 1012 1013 out, err := s.d.Cmd("run", "-d", "busybox", "echo", "testline") 1014 if err != nil { 1015 c.Fatal(out, err) 1016 } 1017 id := strings.TrimSpace(out) 1018 1019 if out, err := s.d.Cmd("wait", id); err != nil { 1020 c.Fatal(out, err) 1021 } 1022 logPath := filepath.Join(s.d.folder, "graph", "containers", id, id+"-json.log") 1023 1024 if _, err := os.Stat(logPath); err != nil { 1025 c.Fatal(err) 1026 } 1027 f, err := os.Open(logPath) 1028 if err != nil { 1029 c.Fatal(err) 1030 } 1031 var res struct { 1032 Log string `json:"log"` 1033 Stream string `json:"stream"` 1034 Time time.Time `json:"time"` 1035 } 1036 if err := json.NewDecoder(f).Decode(&res); err != nil { 1037 c.Fatal(err) 1038 } 1039 if res.Log != "testline\n" { 1040 c.Fatalf("Unexpected log line: %q, expected: %q", res.Log, "testline\n") 1041 } 1042 if res.Stream != "stdout" { 1043 c.Fatalf("Unexpected stream: %q, expected: %q", res.Stream, "stdout") 1044 } 1045 if !time.Now().After(res.Time) { 1046 c.Fatalf("Log time %v in future", res.Time) 1047 } 1048 } 1049 1050 func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefaultOverride(c *check.C) { 1051 if err := s.d.StartWithBusybox(); err != nil { 1052 c.Fatal(err) 1053 } 1054 1055 out, err := s.d.Cmd("run", "-d", "--log-driver=none", "busybox", "echo", "testline") 1056 if err != nil { 1057 c.Fatal(out, err) 1058 } 1059 id := strings.TrimSpace(out) 1060 1061 if out, err := s.d.Cmd("wait", id); err != nil { 1062 c.Fatal(out, err) 1063 } 1064 logPath := filepath.Join(s.d.folder, "graph", "containers", id, id+"-json.log") 1065 1066 if _, err := os.Stat(logPath); err == nil || !os.IsNotExist(err) { 1067 c.Fatalf("%s shouldn't exits, error on Stat: %s", logPath, err) 1068 } 1069 } 1070 1071 func (s *DockerDaemonSuite) TestDaemonLoggingDriverNone(c *check.C) { 1072 if err := s.d.StartWithBusybox("--log-driver=none"); err != nil { 1073 c.Fatal(err) 1074 } 1075 1076 out, err := s.d.Cmd("run", "-d", "busybox", "echo", "testline") 1077 if err != nil { 1078 c.Fatal(out, err) 1079 } 1080 id := strings.TrimSpace(out) 1081 if out, err := s.d.Cmd("wait", id); err != nil { 1082 c.Fatal(out, err) 1083 } 1084 1085 logPath := filepath.Join(s.d.folder, "graph", "containers", id, id+"-json.log") 1086 1087 if _, err := os.Stat(logPath); err == nil || !os.IsNotExist(err) { 1088 c.Fatalf("%s shouldn't exits, error on Stat: %s", logPath, err) 1089 } 1090 } 1091 1092 func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneOverride(c *check.C) { 1093 if err := s.d.StartWithBusybox("--log-driver=none"); err != nil { 1094 c.Fatal(err) 1095 } 1096 1097 out, err := s.d.Cmd("run", "-d", "--log-driver=json-file", "busybox", "echo", "testline") 1098 if err != nil { 1099 c.Fatal(out, err) 1100 } 1101 id := strings.TrimSpace(out) 1102 1103 if out, err := s.d.Cmd("wait", id); err != nil { 1104 c.Fatal(out, err) 1105 } 1106 logPath := filepath.Join(s.d.folder, "graph", "containers", id, id+"-json.log") 1107 1108 if _, err := os.Stat(logPath); err != nil { 1109 c.Fatal(err) 1110 } 1111 f, err := os.Open(logPath) 1112 if err != nil { 1113 c.Fatal(err) 1114 } 1115 var res struct { 1116 Log string `json:"log"` 1117 Stream string `json:"stream"` 1118 Time time.Time `json:"time"` 1119 } 1120 if err := json.NewDecoder(f).Decode(&res); err != nil { 1121 c.Fatal(err) 1122 } 1123 if res.Log != "testline\n" { 1124 c.Fatalf("Unexpected log line: %q, expected: %q", res.Log, "testline\n") 1125 } 1126 if res.Stream != "stdout" { 1127 c.Fatalf("Unexpected stream: %q, expected: %q", res.Stream, "stdout") 1128 } 1129 if !time.Now().After(res.Time) { 1130 c.Fatalf("Log time %v in future", res.Time) 1131 } 1132 } 1133 1134 func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneLogsError(c *check.C) { 1135 if err := s.d.StartWithBusybox("--log-driver=none"); err != nil { 1136 c.Fatal(err) 1137 } 1138 1139 out, err := s.d.Cmd("run", "-d", "busybox", "echo", "testline") 1140 if err != nil { 1141 c.Fatal(out, err) 1142 } 1143 id := strings.TrimSpace(out) 1144 out, err = s.d.Cmd("logs", id) 1145 if err == nil { 1146 c.Fatalf("Logs should fail with \"none\" driver") 1147 } 1148 if !strings.Contains(out, `"logs" command is supported only for "json-file" logging driver`) { 1149 c.Fatalf("There should be error about non-json-file driver, got: %s", out) 1150 } 1151 } 1152 1153 func (s *DockerDaemonSuite) TestDaemonDots(c *check.C) { 1154 if err := s.d.StartWithBusybox(); err != nil { 1155 c.Fatal(err) 1156 } 1157 1158 // Now create 4 containers 1159 if _, err := s.d.Cmd("create", "busybox"); err != nil { 1160 c.Fatalf("Error creating container: %q", err) 1161 } 1162 if _, err := s.d.Cmd("create", "busybox"); err != nil { 1163 c.Fatalf("Error creating container: %q", err) 1164 } 1165 if _, err := s.d.Cmd("create", "busybox"); err != nil { 1166 c.Fatalf("Error creating container: %q", err) 1167 } 1168 if _, err := s.d.Cmd("create", "busybox"); err != nil { 1169 c.Fatalf("Error creating container: %q", err) 1170 } 1171 1172 s.d.Stop() 1173 1174 s.d.Start("--log-level=debug") 1175 s.d.Stop() 1176 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 1177 if strings.Contains(string(content), "....") { 1178 c.Fatalf("Debug level should not have ....\n%s", string(content)) 1179 } 1180 1181 s.d.Start("--log-level=error") 1182 s.d.Stop() 1183 content, _ = ioutil.ReadFile(s.d.logFile.Name()) 1184 if strings.Contains(string(content), "....") { 1185 c.Fatalf("Error level should not have ....\n%s", string(content)) 1186 } 1187 1188 s.d.Start("--log-level=info") 1189 s.d.Stop() 1190 content, _ = ioutil.ReadFile(s.d.logFile.Name()) 1191 if !strings.Contains(string(content), "....") { 1192 c.Fatalf("Info level should have ....\n%s", string(content)) 1193 } 1194 } 1195 1196 func (s *DockerDaemonSuite) TestDaemonUnixSockCleanedUp(c *check.C) { 1197 dir, err := ioutil.TempDir("", "socket-cleanup-test") 1198 if err != nil { 1199 c.Fatal(err) 1200 } 1201 defer os.RemoveAll(dir) 1202 1203 sockPath := filepath.Join(dir, "docker.sock") 1204 if err := s.d.Start("--host", "unix://"+sockPath); err != nil { 1205 c.Fatal(err) 1206 } 1207 1208 if _, err := os.Stat(sockPath); err != nil { 1209 c.Fatal("socket does not exist") 1210 } 1211 1212 if err := s.d.Stop(); err != nil { 1213 c.Fatal(err) 1214 } 1215 1216 if _, err := os.Stat(sockPath); err == nil || !os.IsNotExist(err) { 1217 c.Fatal("unix socket is not cleaned up") 1218 } 1219 } 1220 1221 func (s *DockerDaemonSuite) TestDaemonWithWrongkey(c *check.C) { 1222 type Config struct { 1223 Crv string `json:"crv"` 1224 D string `json:"d"` 1225 Kid string `json:"kid"` 1226 Kty string `json:"kty"` 1227 X string `json:"x"` 1228 Y string `json:"y"` 1229 } 1230 1231 os.Remove("/etc/docker/key.json") 1232 if err := s.d.Start(); err != nil { 1233 c.Fatalf("Failed to start daemon: %v", err) 1234 } 1235 1236 if err := s.d.Stop(); err != nil { 1237 c.Fatalf("Could not stop daemon: %v", err) 1238 } 1239 1240 config := &Config{} 1241 bytes, err := ioutil.ReadFile("/etc/docker/key.json") 1242 if err != nil { 1243 c.Fatalf("Error reading key.json file: %s", err) 1244 } 1245 1246 // byte[] to Data-Struct 1247 if err := json.Unmarshal(bytes, &config); err != nil { 1248 c.Fatalf("Error Unmarshal: %s", err) 1249 } 1250 1251 //replace config.Kid with the fake value 1252 config.Kid = "VSAJ:FUYR:X3H2:B2VZ:KZ6U:CJD5:K7BX:ZXHY:UZXT:P4FT:MJWG:HRJ4" 1253 1254 // NEW Data-Struct to byte[] 1255 newBytes, err := json.Marshal(&config) 1256 if err != nil { 1257 c.Fatalf("Error Marshal: %s", err) 1258 } 1259 1260 // write back 1261 if err := ioutil.WriteFile("/etc/docker/key.json", newBytes, 0400); err != nil { 1262 c.Fatalf("Error ioutil.WriteFile: %s", err) 1263 } 1264 1265 defer os.Remove("/etc/docker/key.json") 1266 1267 if err := s.d.Start(); err == nil { 1268 c.Fatalf("It should not be successful to start daemon with wrong key: %v", err) 1269 } 1270 1271 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 1272 1273 if !strings.Contains(string(content), "Public Key ID does not match") { 1274 c.Fatal("Missing KeyID message from daemon logs") 1275 } 1276 } 1277 1278 func (s *DockerDaemonSuite) TestDaemonRestartKillWait(c *check.C) { 1279 if err := s.d.StartWithBusybox(); err != nil { 1280 c.Fatalf("Could not start daemon with busybox: %v", err) 1281 } 1282 1283 out, err := s.d.Cmd("run", "-id", "busybox", "/bin/cat") 1284 if err != nil { 1285 c.Fatalf("Could not run /bin/cat: err=%v\n%s", err, out) 1286 } 1287 containerID := strings.TrimSpace(out) 1288 1289 if out, err := s.d.Cmd("kill", containerID); err != nil { 1290 c.Fatalf("Could not kill %s: err=%v\n%s", containerID, err, out) 1291 } 1292 1293 if err := s.d.Restart(); err != nil { 1294 c.Fatalf("Could not restart daemon: %v", err) 1295 } 1296 1297 errchan := make(chan error) 1298 go func() { 1299 if out, err := s.d.Cmd("wait", containerID); err != nil { 1300 errchan <- fmt.Errorf("%v:\n%s", err, out) 1301 } 1302 close(errchan) 1303 }() 1304 1305 select { 1306 case <-time.After(5 * time.Second): 1307 c.Fatal("Waiting on a stopped (killed) container timed out") 1308 case err := <-errchan: 1309 if err != nil { 1310 c.Fatal(err) 1311 } 1312 } 1313 } 1314 1315 // TestHttpsInfo connects via two-way authenticated HTTPS to the info endpoint 1316 func (s *DockerDaemonSuite) TestHttpsInfo(c *check.C) { 1317 const ( 1318 testDaemonHTTPSAddr = "tcp://localhost:4271" 1319 ) 1320 1321 if err := s.d.Start("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-cert.pem", 1322 "--tlskey", "fixtures/https/server-key.pem", "-H", testDaemonHTTPSAddr); err != nil { 1323 c.Fatalf("Could not start daemon with busybox: %v", err) 1324 } 1325 1326 daemonArgs := []string{"--host", testDaemonHTTPSAddr, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/client-cert.pem", "--tlskey", "fixtures/https/client-key.pem"} 1327 out, err := s.d.CmdWithArgs(daemonArgs, "info") 1328 if err != nil { 1329 c.Fatalf("Error Occurred: %s and output: %s", err, out) 1330 } 1331 } 1332 1333 // TestHttpsInfoRogueCert connects via two-way authenticated HTTPS to the info endpoint 1334 // by using a rogue client certificate and checks that it fails with the expected error. 1335 func (s *DockerDaemonSuite) TestHttpsInfoRogueCert(c *check.C) { 1336 const ( 1337 errBadCertificate = "remote error: bad certificate" 1338 testDaemonHTTPSAddr = "tcp://localhost:4271" 1339 ) 1340 1341 if err := s.d.Start("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-cert.pem", 1342 "--tlskey", "fixtures/https/server-key.pem", "-H", testDaemonHTTPSAddr); err != nil { 1343 c.Fatalf("Could not start daemon with busybox: %v", err) 1344 } 1345 1346 daemonArgs := []string{"--host", testDaemonHTTPSAddr, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/client-rogue-cert.pem", "--tlskey", "fixtures/https/client-rogue-key.pem"} 1347 out, err := s.d.CmdWithArgs(daemonArgs, "info") 1348 if err == nil || !strings.Contains(out, errBadCertificate) { 1349 c.Fatalf("Expected err: %s, got instead: %s and output: %s", errBadCertificate, err, out) 1350 } 1351 } 1352 1353 // TestHttpsInfoRogueServerCert connects via two-way authenticated HTTPS to the info endpoint 1354 // which provides a rogue server certificate and checks that it fails with the expected error 1355 func (s *DockerDaemonSuite) TestHttpsInfoRogueServerCert(c *check.C) { 1356 const ( 1357 errCaUnknown = "x509: certificate signed by unknown authority" 1358 testDaemonRogueHTTPSAddr = "tcp://localhost:4272" 1359 ) 1360 if err := s.d.Start("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-rogue-cert.pem", 1361 "--tlskey", "fixtures/https/server-rogue-key.pem", "-H", testDaemonRogueHTTPSAddr); err != nil { 1362 c.Fatalf("Could not start daemon with busybox: %v", err) 1363 } 1364 1365 daemonArgs := []string{"--host", testDaemonRogueHTTPSAddr, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/client-rogue-cert.pem", "--tlskey", "fixtures/https/client-rogue-key.pem"} 1366 out, err := s.d.CmdWithArgs(daemonArgs, "info") 1367 if err == nil || !strings.Contains(out, errCaUnknown) { 1368 c.Fatalf("Expected err: %s, got instead: %s and output: %s", errCaUnknown, err, out) 1369 } 1370 } 1371 1372 func pingContainers(c *check.C, d *Daemon, expectFailure bool) { 1373 var dargs []string 1374 if d != nil { 1375 dargs = []string{"--host", d.sock()} 1376 } 1377 1378 args := append(dargs, "run", "-d", "--name", "container1", "busybox", "top") 1379 dockerCmd(c, args...) 1380 1381 args = append(dargs, "run", "--rm", "--link", "container1:alias1", "busybox", "sh", "-c") 1382 pingCmd := "ping -c 1 %s -W 1" 1383 args = append(args, fmt.Sprintf(pingCmd, "alias1")) 1384 _, _, err := dockerCmdWithError(c, args...) 1385 1386 if expectFailure { 1387 c.Assert(err, check.NotNil) 1388 } else { 1389 c.Assert(err, check.IsNil) 1390 } 1391 1392 args = append(dargs, "rm", "-f", "container1") 1393 dockerCmd(c, args...) 1394 } 1395 1396 func (s *DockerDaemonSuite) TestDaemonRestartWithSocketAsVolume(c *check.C) { 1397 c.Assert(s.d.StartWithBusybox(), check.IsNil) 1398 1399 socket := filepath.Join(s.d.folder, "docker.sock") 1400 1401 out, err := s.d.Cmd("run", "-d", "-v", socket+":/sock", "busybox") 1402 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1403 c.Assert(s.d.Restart(), check.IsNil) 1404 } 1405 1406 func (s *DockerDaemonSuite) TestCleanupMountsAfterCrash(c *check.C) { 1407 c.Assert(s.d.StartWithBusybox(), check.IsNil) 1408 1409 out, err := s.d.Cmd("run", "-d", "busybox", "top") 1410 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1411 id := strings.TrimSpace(out) 1412 c.Assert(s.d.cmd.Process.Signal(os.Kill), check.IsNil) 1413 c.Assert(s.d.Start(), check.IsNil) 1414 mountOut, err := exec.Command("mount").CombinedOutput() 1415 c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut)) 1416 c.Assert(strings.Contains(string(mountOut), id), check.Equals, false, check.Commentf("Something mounted from older daemon start: %s", mountOut)) 1417 } 1418 1419 func (s *DockerDaemonSuite) TestRunContainerWithBridgeNone(c *check.C) { 1420 testRequires(c, NativeExecDriver) 1421 c.Assert(s.d.StartWithBusybox("-b", "none"), check.IsNil) 1422 1423 out, err := s.d.Cmd("run", "--rm", "busybox", "ip", "l") 1424 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1425 c.Assert(strings.Contains(out, "eth0"), check.Equals, false, 1426 check.Commentf("There shouldn't be eth0 in container in default(bridge) mode when bridge network is disabled: %s", out)) 1427 1428 out, err = s.d.Cmd("run", "--rm", "--net=bridge", "busybox", "ip", "l") 1429 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1430 c.Assert(strings.Contains(out, "eth0"), check.Equals, false, 1431 check.Commentf("There shouldn't be eth0 in container in bridge mode when bridge network is disabled: %s", out)) 1432 1433 out, err = s.d.Cmd("run", "--rm", "--net=host", "busybox", "ip", "l") 1434 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1435 c.Assert(strings.Contains(out, "eth0"), check.Equals, true, 1436 check.Commentf("There should be eth0 in container when --net=host when bridge network is disabled: %s", out)) 1437 } 1438 1439 func (s *DockerDaemonSuite) TestDaemonRestartWithContainerRunning(t *check.C) { 1440 if err := s.d.StartWithBusybox(); err != nil { 1441 t.Fatal(err) 1442 } 1443 if out, err := s.d.Cmd("run", "-ti", "-d", "--name", "test", "busybox"); err != nil { 1444 t.Fatal(out, err) 1445 } 1446 1447 if err := s.d.Restart(); err != nil { 1448 t.Fatal(err) 1449 } 1450 // Container 'test' should be removed without error 1451 if out, err := s.d.Cmd("rm", "test"); err != nil { 1452 t.Fatal(out, err) 1453 } 1454 } 1455 1456 func (s *DockerDaemonSuite) TestDaemonRestartCleanupNetns(c *check.C) { 1457 if err := s.d.StartWithBusybox(); err != nil { 1458 c.Fatal(err) 1459 } 1460 out, err := s.d.Cmd("run", "--name", "netns", "-d", "busybox", "top") 1461 if err != nil { 1462 c.Fatal(out, err) 1463 } 1464 if out, err := s.d.Cmd("stop", "netns"); err != nil { 1465 c.Fatal(out, err) 1466 } 1467 1468 // Construct netns file name from container id 1469 out = strings.TrimSpace(out) 1470 nsFile := out[:12] 1471 1472 // Test if the file still exists 1473 out, _, err = runCommandWithOutput(exec.Command("stat", "-c", "%n", "/var/run/docker/netns/"+nsFile)) 1474 out = strings.TrimSpace(out) 1475 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1476 c.Assert(out, check.Equals, "/var/run/docker/netns/"+nsFile, check.Commentf("Output: %s", out)) 1477 1478 // Remove the container and restart the daemon 1479 if out, err := s.d.Cmd("rm", "netns"); err != nil { 1480 c.Fatal(out, err) 1481 } 1482 1483 if err := s.d.Restart(); err != nil { 1484 c.Fatal(err) 1485 } 1486 1487 // Test again and see now the netns file does not exist 1488 out, _, err = runCommandWithOutput(exec.Command("stat", "-c", "%n", "/var/run/docker/netns/"+nsFile)) 1489 out = strings.TrimSpace(out) 1490 c.Assert(err, check.Not(check.IsNil), check.Commentf("Output: %s", out)) 1491 // c.Assert(out, check.Equals, "", check.Commentf("Output: %s", out)) 1492 } 1493 1494 // tests regression detailed in #13964 where DOCKER_TLS_VERIFY env is ignored 1495 func (s *DockerDaemonSuite) TestDaemonNoTlsCliTlsVerifyWithEnv(c *check.C) { 1496 host := "tcp://localhost:4271" 1497 c.Assert(s.d.Start("-H", host), check.IsNil) 1498 cmd := exec.Command(dockerBinary, "-H", host, "info") 1499 cmd.Env = []string{"DOCKER_TLS_VERIFY=1", "DOCKER_CERT_PATH=fixtures/https"} 1500 out, _, err := runCommandWithOutput(cmd) 1501 c.Assert(err, check.Not(check.IsNil), check.Commentf("%s", out)) 1502 c.Assert(strings.Contains(out, "error occurred trying to connect"), check.Equals, true) 1503 1504 } 1505 1506 func setupV6() error { 1507 // Hack to get the right IPv6 address on docker0, which has already been created 1508 err := exec.Command("ip", "addr", "add", "fe80::1/64", "dev", "docker0").Run() 1509 if err != nil { 1510 return err 1511 } 1512 return nil 1513 } 1514 1515 func teardownV6() error { 1516 err := exec.Command("ip", "addr", "del", "fe80::1/64", "dev", "docker0").Run() 1517 if err != nil { 1518 return err 1519 } 1520 return nil 1521 }