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