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