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