github.com/jwhonce/docker@v0.6.7-0.20190327063223-da823cf3a5a3/integration-cli/docker_cli_daemon_test.go (about) 1 // +build linux 2 3 package main 4 5 import ( 6 "bufio" 7 "bytes" 8 "context" 9 "crypto/tls" 10 "crypto/x509" 11 "encoding/json" 12 "fmt" 13 "io" 14 "io/ioutil" 15 "net" 16 "os" 17 "os/exec" 18 "path" 19 "path/filepath" 20 "regexp" 21 "strconv" 22 "strings" 23 "sync" 24 "time" 25 26 "github.com/cloudflare/cfssl/helpers" 27 "github.com/docker/docker/api/types" 28 moby_daemon "github.com/docker/docker/daemon" 29 "github.com/docker/docker/integration-cli/checker" 30 "github.com/docker/docker/integration-cli/cli" 31 "github.com/docker/docker/integration-cli/cli/build" 32 "github.com/docker/docker/integration-cli/daemon" 33 testdaemon "github.com/docker/docker/internal/test/daemon" 34 "github.com/docker/docker/opts" 35 "github.com/docker/docker/pkg/mount" 36 "github.com/docker/go-units" 37 "github.com/docker/libnetwork/iptables" 38 "github.com/go-check/check" 39 "github.com/kr/pty" 40 "golang.org/x/sys/unix" 41 "gotest.tools/icmd" 42 ) 43 44 const containerdSocket = "/var/run/docker/containerd/containerd.sock" 45 46 // TestLegacyDaemonCommand test starting docker daemon using "deprecated" docker daemon 47 // command. Remove this test when we remove this. 48 func (s *DockerDaemonSuite) TestLegacyDaemonCommand(c *check.C) { 49 cmd := exec.Command(dockerBinary, "daemon", "--storage-driver=vfs", "--debug") 50 err := cmd.Start() 51 go cmd.Wait() 52 c.Assert(err, checker.IsNil, check.Commentf("could not start daemon using 'docker daemon'")) 53 54 c.Assert(cmd.Process.Kill(), checker.IsNil) 55 } 56 57 func (s *DockerDaemonSuite) TestDaemonRestartWithRunningContainersPorts(c *check.C) { 58 s.d.StartWithBusybox(c) 59 60 cli.Docker( 61 cli.Args("run", "-d", "--name", "top1", "-p", "1234:80", "--restart", "always", "busybox:latest", "top"), 62 cli.Daemon(s.d), 63 ).Assert(c, icmd.Success) 64 65 cli.Docker( 66 cli.Args("run", "-d", "--name", "top2", "-p", "80", "busybox:latest", "top"), 67 cli.Daemon(s.d), 68 ).Assert(c, icmd.Success) 69 70 testRun := func(m map[string]bool, prefix string) { 71 var format string 72 for cont, shouldRun := range m { 73 out := cli.Docker(cli.Args("ps"), cli.Daemon(s.d)).Assert(c, icmd.Success).Combined() 74 if shouldRun { 75 format = "%scontainer %q is not running" 76 } else { 77 format = "%scontainer %q is running" 78 } 79 if shouldRun != strings.Contains(out, cont) { 80 c.Fatalf(format, prefix, cont) 81 } 82 } 83 } 84 85 testRun(map[string]bool{"top1": true, "top2": true}, "") 86 87 s.d.Restart(c) 88 testRun(map[string]bool{"top1": true, "top2": false}, "After daemon restart: ") 89 } 90 91 func (s *DockerDaemonSuite) TestDaemonRestartWithVolumesRefs(c *check.C) { 92 s.d.StartWithBusybox(c) 93 94 if out, err := s.d.Cmd("run", "--name", "volrestarttest1", "-v", "/foo", "busybox"); err != nil { 95 c.Fatal(err, out) 96 } 97 98 s.d.Restart(c) 99 100 if out, err := s.d.Cmd("run", "-d", "--volumes-from", "volrestarttest1", "--name", "volrestarttest2", "busybox", "top"); err != nil { 101 c.Fatal(err, out) 102 } 103 104 if out, err := s.d.Cmd("rm", "-fv", "volrestarttest2"); err != nil { 105 c.Fatal(err, out) 106 } 107 108 out, err := s.d.Cmd("inspect", "-f", "{{json .Mounts}}", "volrestarttest1") 109 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 110 111 if _, err := inspectMountPointJSON(out, "/foo"); err != nil { 112 c.Fatalf("Expected volume to exist: /foo, error: %v\n", err) 113 } 114 } 115 116 // #11008 117 func (s *DockerDaemonSuite) TestDaemonRestartUnlessStopped(c *check.C) { 118 s.d.StartWithBusybox(c) 119 120 out, err := s.d.Cmd("run", "-d", "--name", "top1", "--restart", "always", "busybox:latest", "top") 121 c.Assert(err, check.IsNil, check.Commentf("run top1: %v", out)) 122 123 out, err = s.d.Cmd("run", "-d", "--name", "top2", "--restart", "unless-stopped", "busybox:latest", "top") 124 c.Assert(err, check.IsNil, check.Commentf("run top2: %v", out)) 125 126 out, err = s.d.Cmd("run", "-d", "--name", "exit", "--restart", "unless-stopped", "busybox:latest", "false") 127 c.Assert(err, check.IsNil, check.Commentf("run exit: %v", out)) 128 129 testRun := func(m map[string]bool, prefix string) { 130 var format string 131 for name, shouldRun := range m { 132 out, err := s.d.Cmd("ps") 133 c.Assert(err, check.IsNil, check.Commentf("run ps: %v", out)) 134 if shouldRun { 135 format = "%scontainer %q is not running" 136 } else { 137 format = "%scontainer %q is running" 138 } 139 c.Assert(strings.Contains(out, name), check.Equals, shouldRun, check.Commentf(format, prefix, name)) 140 } 141 } 142 143 // both running 144 testRun(map[string]bool{"top1": true, "top2": true, "exit": true}, "") 145 146 out, err = s.d.Cmd("stop", "exit") 147 c.Assert(err, check.IsNil, check.Commentf(out)) 148 149 out, err = s.d.Cmd("stop", "top1") 150 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 151 152 out, err = s.d.Cmd("stop", "top2") 153 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 154 155 // both stopped 156 testRun(map[string]bool{"top1": false, "top2": false, "exit": false}, "") 157 158 s.d.Restart(c) 159 160 // restart=always running 161 testRun(map[string]bool{"top1": true, "top2": false, "exit": false}, "After daemon restart: ") 162 163 out, err = s.d.Cmd("start", "top2") 164 c.Assert(err, check.IsNil, check.Commentf("start top2: %v", out)) 165 166 out, err = s.d.Cmd("start", "exit") 167 c.Assert(err, check.IsNil, check.Commentf("start exit: %v", out)) 168 169 s.d.Restart(c) 170 171 // both running 172 testRun(map[string]bool{"top1": true, "top2": true, "exit": true}, "After second daemon restart: ") 173 174 } 175 176 func (s *DockerDaemonSuite) TestDaemonRestartOnFailure(c *check.C) { 177 s.d.StartWithBusybox(c) 178 179 out, err := s.d.Cmd("run", "-d", "--name", "test1", "--restart", "on-failure:3", "busybox:latest", "false") 180 c.Assert(err, check.IsNil, check.Commentf("run top1: %v", out)) 181 182 // wait test1 to stop 183 hostArgs := []string{"--host", s.d.Sock()} 184 err = waitInspectWithArgs("test1", "{{.State.Running}} {{.State.Restarting}}", "false false", 10*time.Second, hostArgs...) 185 c.Assert(err, checker.IsNil, check.Commentf("test1 should exit but not")) 186 187 // record last start time 188 out, err = s.d.Cmd("inspect", "-f={{.State.StartedAt}}", "test1") 189 c.Assert(err, checker.IsNil, check.Commentf("out: %v", out)) 190 lastStartTime := out 191 192 s.d.Restart(c) 193 194 // test1 shouldn't restart at all 195 err = waitInspectWithArgs("test1", "{{.State.Running}} {{.State.Restarting}}", "false false", 0, hostArgs...) 196 c.Assert(err, checker.IsNil, check.Commentf("test1 should exit but not")) 197 198 // make sure test1 isn't restarted when daemon restart 199 // if "StartAt" time updates, means test1 was once restarted. 200 out, err = s.d.Cmd("inspect", "-f={{.State.StartedAt}}", "test1") 201 c.Assert(err, checker.IsNil, check.Commentf("out: %v", out)) 202 c.Assert(out, checker.Equals, lastStartTime, check.Commentf("test1 shouldn't start after daemon restarts")) 203 } 204 205 func (s *DockerDaemonSuite) TestDaemonStartIptablesFalse(c *check.C) { 206 s.d.Start(c, "--iptables=false") 207 } 208 209 // Make sure we cannot shrink base device at daemon restart. 210 func (s *DockerDaemonSuite) TestDaemonRestartWithInvalidBasesize(c *check.C) { 211 testRequires(c, Devicemapper) 212 s.d.Start(c) 213 214 oldBasesizeBytes := getBaseDeviceSize(c, s.d) 215 var newBasesizeBytes int64 = 1073741824 //1GB in bytes 216 217 if newBasesizeBytes < oldBasesizeBytes { 218 err := s.d.RestartWithError("--storage-opt", fmt.Sprintf("dm.basesize=%d", newBasesizeBytes)) 219 c.Assert(err, check.NotNil, check.Commentf("daemon should not have started as new base device size is less than existing base device size: %v", err)) 220 // 'err != nil' is expected behaviour, no new daemon started, 221 // so no need to stop daemon. 222 if err != nil { 223 return 224 } 225 } 226 s.d.Stop(c) 227 } 228 229 // Make sure we can grow base device at daemon restart. 230 func (s *DockerDaemonSuite) TestDaemonRestartWithIncreasedBasesize(c *check.C) { 231 testRequires(c, Devicemapper) 232 s.d.Start(c) 233 234 oldBasesizeBytes := getBaseDeviceSize(c, s.d) 235 236 var newBasesizeBytes int64 = 53687091200 //50GB in bytes 237 238 if newBasesizeBytes < oldBasesizeBytes { 239 c.Skip(fmt.Sprintf("New base device size (%v) must be greater than (%s)", units.HumanSize(float64(newBasesizeBytes)), units.HumanSize(float64(oldBasesizeBytes)))) 240 } 241 242 err := s.d.RestartWithError("--storage-opt", fmt.Sprintf("dm.basesize=%d", newBasesizeBytes)) 243 c.Assert(err, check.IsNil, check.Commentf("we should have been able to start the daemon with increased base device size: %v", err)) 244 245 basesizeAfterRestart := getBaseDeviceSize(c, s.d) 246 newBasesize, err := convertBasesize(newBasesizeBytes) 247 c.Assert(err, check.IsNil, check.Commentf("Error in converting base device size: %v", err)) 248 c.Assert(newBasesize, check.Equals, basesizeAfterRestart, check.Commentf("Basesize passed is not equal to Basesize set")) 249 s.d.Stop(c) 250 } 251 252 func getBaseDeviceSize(c *check.C, d *daemon.Daemon) int64 { 253 info := d.Info(c) 254 for _, statusLine := range info.DriverStatus { 255 key, value := statusLine[0], statusLine[1] 256 if key == "Base Device Size" { 257 return parseDeviceSize(c, value) 258 } 259 } 260 c.Fatal("failed to parse Base Device Size from info") 261 return int64(0) 262 } 263 264 func parseDeviceSize(c *check.C, raw string) int64 { 265 size, err := units.RAMInBytes(strings.TrimSpace(raw)) 266 c.Assert(err, check.IsNil) 267 return size 268 } 269 270 func convertBasesize(basesizeBytes int64) (int64, error) { 271 basesize := units.HumanSize(float64(basesizeBytes)) 272 basesize = strings.Trim(basesize, " ")[:len(basesize)-3] 273 basesizeFloat, err := strconv.ParseFloat(strings.Trim(basesize, " "), 64) 274 if err != nil { 275 return 0, err 276 } 277 return int64(basesizeFloat) * 1024 * 1024 * 1024, nil 278 } 279 280 // Issue #8444: If docker0 bridge is modified (intentionally or unintentionally) and 281 // no longer has an IP associated, we should gracefully handle that case and associate 282 // an IP with it rather than fail daemon start 283 func (s *DockerDaemonSuite) TestDaemonStartBridgeWithoutIPAssociation(c *check.C) { 284 // rather than depending on brctl commands to verify docker0 is created and up 285 // let's start the daemon and stop it, and then make a modification to run the 286 // actual test 287 s.d.Start(c) 288 s.d.Stop(c) 289 290 // now we will remove the ip from docker0 and then try starting the daemon 291 icmd.RunCommand("ip", "addr", "flush", "dev", "docker0").Assert(c, icmd.Success) 292 293 if err := s.d.StartWithError(); err != nil { 294 warning := "**WARNING: Docker bridge network in bad state--delete docker0 bridge interface to fix" 295 c.Fatalf("Could not start daemon when docker0 has no IP address: %v\n%s", err, warning) 296 } 297 } 298 299 func (s *DockerDaemonSuite) TestDaemonIptablesClean(c *check.C) { 300 s.d.StartWithBusybox(c) 301 302 if out, err := s.d.Cmd("run", "-d", "--name", "top", "-p", "80", "busybox:latest", "top"); err != nil { 303 c.Fatalf("Could not run top: %s, %v", out, err) 304 } 305 306 ipTablesSearchString := "tcp dpt:80" 307 308 // get output from iptables with container running 309 verifyIPTablesContains(c, ipTablesSearchString) 310 311 s.d.Stop(c) 312 313 // get output from iptables after restart 314 verifyIPTablesDoesNotContains(c, ipTablesSearchString) 315 } 316 317 func (s *DockerDaemonSuite) TestDaemonIptablesCreate(c *check.C) { 318 s.d.StartWithBusybox(c) 319 320 if out, err := s.d.Cmd("run", "-d", "--name", "top", "--restart=always", "-p", "80", "busybox:latest", "top"); err != nil { 321 c.Fatalf("Could not run top: %s, %v", out, err) 322 } 323 324 // get output from iptables with container running 325 ipTablesSearchString := "tcp dpt:80" 326 verifyIPTablesContains(c, ipTablesSearchString) 327 328 s.d.Restart(c) 329 330 // make sure the container is not running 331 runningOut, err := s.d.Cmd("inspect", "--format={{.State.Running}}", "top") 332 if err != nil { 333 c.Fatalf("Could not inspect on container: %s, %v", runningOut, err) 334 } 335 if strings.TrimSpace(runningOut) != "true" { 336 c.Fatalf("Container should have been restarted after daemon restart. Status running should have been true but was: %q", strings.TrimSpace(runningOut)) 337 } 338 339 // get output from iptables after restart 340 verifyIPTablesContains(c, ipTablesSearchString) 341 } 342 343 func verifyIPTablesContains(c *check.C, ipTablesSearchString string) { 344 result := icmd.RunCommand("iptables", "-nvL") 345 result.Assert(c, icmd.Success) 346 if !strings.Contains(result.Combined(), ipTablesSearchString) { 347 c.Fatalf("iptables output should have contained %q, but was %q", ipTablesSearchString, result.Combined()) 348 } 349 } 350 351 func verifyIPTablesDoesNotContains(c *check.C, ipTablesSearchString string) { 352 result := icmd.RunCommand("iptables", "-nvL") 353 result.Assert(c, icmd.Success) 354 if strings.Contains(result.Combined(), ipTablesSearchString) { 355 c.Fatalf("iptables output should not have contained %q, but was %q", ipTablesSearchString, result.Combined()) 356 } 357 } 358 359 // TestDaemonIPv6Enabled checks that when the daemon is started with --ipv6=true that the docker0 bridge 360 // has the fe80::1 address and that a container is assigned a link-local address 361 func (s *DockerDaemonSuite) TestDaemonIPv6Enabled(c *check.C) { 362 testRequires(c, IPv6) 363 364 setupV6(c) 365 defer teardownV6(c) 366 367 s.d.StartWithBusybox(c, "--ipv6") 368 369 iface, err := net.InterfaceByName("docker0") 370 if err != nil { 371 c.Fatalf("Error getting docker0 interface: %v", err) 372 } 373 374 addrs, err := iface.Addrs() 375 if err != nil { 376 c.Fatalf("Error getting addresses for docker0 interface: %v", err) 377 } 378 379 var found bool 380 expected := "fe80::1/64" 381 382 for i := range addrs { 383 if addrs[i].String() == expected { 384 found = true 385 break 386 } 387 } 388 389 if !found { 390 c.Fatalf("Bridge does not have an IPv6 Address") 391 } 392 393 if out, err := s.d.Cmd("run", "-itd", "--name=ipv6test", "busybox:latest"); err != nil { 394 c.Fatalf("Could not run container: %s, %v", out, err) 395 } 396 397 out, err := s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.LinkLocalIPv6Address}}'", "ipv6test") 398 if err != nil { 399 c.Fatalf("Error inspecting container: %s, %v", out, err) 400 } 401 out = strings.Trim(out, " \r\n'") 402 403 if ip := net.ParseIP(out); ip == nil { 404 c.Fatalf("Container should have a link-local IPv6 address") 405 } 406 407 out, err = s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.GlobalIPv6Address}}'", "ipv6test") 408 if err != nil { 409 c.Fatalf("Error inspecting container: %s, %v", out, err) 410 } 411 out = strings.Trim(out, " \r\n'") 412 413 if ip := net.ParseIP(out); ip != nil { 414 c.Fatalf("Container should not have a global IPv6 address: %v", out) 415 } 416 } 417 418 // TestDaemonIPv6FixedCIDR checks that when the daemon is started with --ipv6=true and a fixed CIDR 419 // that running containers are given a link-local and global IPv6 address 420 func (s *DockerDaemonSuite) TestDaemonIPv6FixedCIDR(c *check.C) { 421 // IPv6 setup is messing with local bridge address. 422 testRequires(c, testEnv.IsLocalDaemon) 423 // Delete the docker0 bridge if its left around from previous daemon. It has to be recreated with 424 // ipv6 enabled 425 deleteInterface(c, "docker0") 426 427 s.d.StartWithBusybox(c, "--ipv6", "--fixed-cidr-v6=2001:db8:2::/64", "--default-gateway-v6=2001:db8:2::100") 428 429 out, err := s.d.Cmd("run", "-itd", "--name=ipv6test", "busybox:latest") 430 c.Assert(err, checker.IsNil, check.Commentf("Could not run container: %s, %v", out, err)) 431 432 out, err = s.d.Cmd("inspect", "--format", "{{.NetworkSettings.Networks.bridge.GlobalIPv6Address}}", "ipv6test") 433 c.Assert(err, checker.IsNil, check.Commentf("%s", out)) 434 out = strings.Trim(out, " \r\n'") 435 436 ip := net.ParseIP(out) 437 c.Assert(ip, checker.NotNil, check.Commentf("Container should have a global IPv6 address")) 438 439 out, err = s.d.Cmd("inspect", "--format", "{{.NetworkSettings.Networks.bridge.IPv6Gateway}}", "ipv6test") 440 c.Assert(err, checker.IsNil, check.Commentf("%s", out)) 441 442 c.Assert(strings.Trim(out, " \r\n'"), checker.Equals, "2001:db8:2::100", check.Commentf("Container should have a global IPv6 gateway")) 443 } 444 445 // TestDaemonIPv6FixedCIDRAndMac checks that when the daemon is started with ipv6 fixed CIDR 446 // the running containers are given an IPv6 address derived from the MAC address and the ipv6 fixed CIDR 447 func (s *DockerDaemonSuite) TestDaemonIPv6FixedCIDRAndMac(c *check.C) { 448 // IPv6 setup is messing with local bridge address. 449 testRequires(c, testEnv.IsLocalDaemon) 450 // Delete the docker0 bridge if its left around from previous daemon. It has to be recreated with 451 // ipv6 enabled 452 deleteInterface(c, "docker0") 453 454 s.d.StartWithBusybox(c, "--ipv6", "--fixed-cidr-v6=2001:db8:1::/64") 455 456 out, err := s.d.Cmd("run", "-itd", "--name=ipv6test", "--mac-address", "AA:BB:CC:DD:EE:FF", "busybox") 457 c.Assert(err, checker.IsNil, check.Commentf("%s", out)) 458 459 out, err = s.d.Cmd("inspect", "--format", "{{.NetworkSettings.Networks.bridge.GlobalIPv6Address}}", "ipv6test") 460 c.Assert(err, checker.IsNil, check.Commentf("%s", out)) 461 c.Assert(strings.Trim(out, " \r\n'"), checker.Equals, "2001:db8:1::aabb:ccdd:eeff") 462 } 463 464 // TestDaemonIPv6HostMode checks that when the running a container with 465 // network=host the host ipv6 addresses are not removed 466 func (s *DockerDaemonSuite) TestDaemonIPv6HostMode(c *check.C) { 467 testRequires(c, testEnv.IsLocalDaemon) 468 deleteInterface(c, "docker0") 469 470 s.d.StartWithBusybox(c, "--ipv6", "--fixed-cidr-v6=2001:db8:2::/64") 471 out, err := s.d.Cmd("run", "-itd", "--name=hostcnt", "--network=host", "busybox:latest") 472 c.Assert(err, checker.IsNil, check.Commentf("Could not run container: %s, %v", out, err)) 473 474 out, err = s.d.Cmd("exec", "hostcnt", "ip", "-6", "addr", "show", "docker0") 475 c.Assert(err, checker.IsNil, check.Commentf("%s", out)) 476 c.Assert(strings.Trim(out, " \r\n'"), checker.Contains, "2001:db8:2::1") 477 } 478 479 func (s *DockerDaemonSuite) TestDaemonLogLevelWrong(c *check.C) { 480 c.Assert(s.d.StartWithError("--log-level=bogus"), check.NotNil, check.Commentf("Daemon shouldn't start with wrong log level")) 481 } 482 483 func (s *DockerDaemonSuite) TestDaemonLogLevelDebug(c *check.C) { 484 s.d.Start(c, "--log-level=debug") 485 content, err := s.d.ReadLogFile() 486 c.Assert(err, checker.IsNil) 487 if !strings.Contains(string(content), `level=debug`) { 488 c.Fatalf(`Missing level="debug" in log file:\n%s`, string(content)) 489 } 490 } 491 492 func (s *DockerDaemonSuite) TestDaemonLogLevelFatal(c *check.C) { 493 // we creating new daemons to create new logFile 494 s.d.Start(c, "--log-level=fatal") 495 content, err := s.d.ReadLogFile() 496 c.Assert(err, checker.IsNil) 497 if strings.Contains(string(content), `level=debug`) { 498 c.Fatalf(`Should not have level="debug" in log file:\n%s`, string(content)) 499 } 500 } 501 502 func (s *DockerDaemonSuite) TestDaemonFlagD(c *check.C) { 503 s.d.Start(c, "-D") 504 content, err := s.d.ReadLogFile() 505 c.Assert(err, checker.IsNil) 506 if !strings.Contains(string(content), `level=debug`) { 507 c.Fatalf(`Should have level="debug" in log file using -D:\n%s`, string(content)) 508 } 509 } 510 511 func (s *DockerDaemonSuite) TestDaemonFlagDebug(c *check.C) { 512 s.d.Start(c, "--debug") 513 content, err := s.d.ReadLogFile() 514 c.Assert(err, checker.IsNil) 515 if !strings.Contains(string(content), `level=debug`) { 516 c.Fatalf(`Should have level="debug" in log file using --debug:\n%s`, string(content)) 517 } 518 } 519 520 func (s *DockerDaemonSuite) TestDaemonFlagDebugLogLevelFatal(c *check.C) { 521 s.d.Start(c, "--debug", "--log-level=fatal") 522 content, err := s.d.ReadLogFile() 523 c.Assert(err, checker.IsNil) 524 if !strings.Contains(string(content), `level=debug`) { 525 c.Fatalf(`Should have level="debug" in log file when using both --debug and --log-level=fatal:\n%s`, string(content)) 526 } 527 } 528 529 func (s *DockerDaemonSuite) TestDaemonAllocatesListeningPort(c *check.C) { 530 listeningPorts := [][]string{ 531 {"0.0.0.0", "0.0.0.0", "5678"}, 532 {"127.0.0.1", "127.0.0.1", "1234"}, 533 {"localhost", "127.0.0.1", "1235"}, 534 } 535 536 cmdArgs := make([]string, 0, len(listeningPorts)*2) 537 for _, hostDirective := range listeningPorts { 538 cmdArgs = append(cmdArgs, "--host", fmt.Sprintf("tcp://%s:%s", hostDirective[0], hostDirective[2])) 539 } 540 541 s.d.StartWithBusybox(c, cmdArgs...) 542 543 for _, hostDirective := range listeningPorts { 544 output, err := s.d.Cmd("run", "-p", fmt.Sprintf("%s:%s:80", hostDirective[1], hostDirective[2]), "busybox", "true") 545 if err == nil { 546 c.Fatalf("Container should not start, expected port already allocated error: %q", output) 547 } else if !strings.Contains(output, "port is already allocated") { 548 c.Fatalf("Expected port is already allocated error: %q", output) 549 } 550 } 551 } 552 553 // GH#11320 - verify that the daemon exits on failure properly 554 // Note that this explicitly tests the conflict of {-b,--bridge} and {--bip} options as the means 555 // to get a daemon init failure; no other tests for -b/--bip conflict are therefore required 556 func (s *DockerDaemonSuite) TestDaemonExitOnFailure(c *check.C) { 557 //attempt to start daemon with incorrect flags (we know -b and --bip conflict) 558 if err := s.d.StartWithError("--bridge", "nosuchbridge", "--bip", "1.1.1.1"); err != nil { 559 //verify we got the right error 560 if !strings.Contains(err.Error(), "Daemon exited") { 561 c.Fatalf("Expected daemon not to start, got %v", err) 562 } 563 // look in the log and make sure we got the message that daemon is shutting down 564 icmd.RunCommand("grep", "failed to start daemon", s.d.LogFileName()).Assert(c, icmd.Success) 565 } else { 566 //if we didn't get an error and the daemon is running, this is a failure 567 c.Fatal("Conflicting options should cause the daemon to error out with a failure") 568 } 569 } 570 571 func (s *DockerDaemonSuite) TestDaemonBridgeExternal(c *check.C) { 572 d := s.d 573 err := d.StartWithError("--bridge", "nosuchbridge") 574 c.Assert(err, check.NotNil, check.Commentf("--bridge option with an invalid bridge should cause the daemon to fail")) 575 defer d.Restart(c) 576 577 bridgeName := "external-bridge" 578 bridgeIP := "192.169.1.1/24" 579 _, bridgeIPNet, _ := net.ParseCIDR(bridgeIP) 580 581 createInterface(c, "bridge", bridgeName, bridgeIP) 582 defer deleteInterface(c, bridgeName) 583 584 d.StartWithBusybox(c, "--bridge", bridgeName) 585 586 ipTablesSearchString := bridgeIPNet.String() 587 icmd.RunCommand("iptables", "-t", "nat", "-nvL").Assert(c, icmd.Expected{ 588 Out: ipTablesSearchString, 589 }) 590 591 out, err := d.Cmd("run", "-d", "--name", "ExtContainer", "busybox", "top") 592 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 593 594 containerIP := d.FindContainerIP(c, "ExtContainer") 595 ip := net.ParseIP(containerIP) 596 c.Assert(bridgeIPNet.Contains(ip), check.Equals, true, 597 check.Commentf("Container IP-Address must be in the same subnet range : %s", 598 containerIP)) 599 } 600 601 func (s *DockerDaemonSuite) TestDaemonBridgeNone(c *check.C) { 602 // start with bridge none 603 d := s.d 604 d.StartWithBusybox(c, "--bridge", "none") 605 defer d.Restart(c) 606 607 // verify docker0 iface is not there 608 icmd.RunCommand("ifconfig", "docker0").Assert(c, icmd.Expected{ 609 ExitCode: 1, 610 Error: "exit status 1", 611 Err: "Device not found", 612 }) 613 614 // verify default "bridge" network is not there 615 out, err := d.Cmd("network", "inspect", "bridge") 616 c.Assert(err, check.NotNil, check.Commentf("\"bridge\" network should not be present if daemon started with --bridge=none")) 617 c.Assert(strings.Contains(out, "No such network"), check.Equals, true) 618 } 619 620 func createInterface(c *check.C, ifType string, ifName string, ipNet string) { 621 icmd.RunCommand("ip", "link", "add", "name", ifName, "type", ifType).Assert(c, icmd.Success) 622 icmd.RunCommand("ifconfig", ifName, ipNet, "up").Assert(c, icmd.Success) 623 } 624 625 func deleteInterface(c *check.C, ifName string) { 626 icmd.RunCommand("ip", "link", "delete", ifName).Assert(c, icmd.Success) 627 icmd.RunCommand("iptables", "-t", "nat", "--flush").Assert(c, icmd.Success) 628 icmd.RunCommand("iptables", "--flush").Assert(c, icmd.Success) 629 } 630 631 func (s *DockerDaemonSuite) TestDaemonBridgeIP(c *check.C) { 632 // TestDaemonBridgeIP Steps 633 // 1. Delete the existing docker0 Bridge 634 // 2. Set --bip daemon configuration and start the new Docker Daemon 635 // 3. Check if the bip config has taken effect using ifconfig and iptables commands 636 // 4. Launch a Container and make sure the IP-Address is in the expected subnet 637 // 5. Delete the docker0 Bridge 638 // 6. Restart the Docker Daemon (via deferred action) 639 // This Restart takes care of bringing docker0 interface back to auto-assigned IP 640 641 defaultNetworkBridge := "docker0" 642 deleteInterface(c, defaultNetworkBridge) 643 644 d := s.d 645 646 bridgeIP := "192.169.1.1/24" 647 ip, bridgeIPNet, _ := net.ParseCIDR(bridgeIP) 648 649 d.StartWithBusybox(c, "--bip", bridgeIP) 650 defer d.Restart(c) 651 652 ifconfigSearchString := ip.String() 653 icmd.RunCommand("ifconfig", defaultNetworkBridge).Assert(c, icmd.Expected{ 654 Out: ifconfigSearchString, 655 }) 656 657 ipTablesSearchString := bridgeIPNet.String() 658 icmd.RunCommand("iptables", "-t", "nat", "-nvL").Assert(c, icmd.Expected{ 659 Out: ipTablesSearchString, 660 }) 661 662 out, err := d.Cmd("run", "-d", "--name", "test", "busybox", "top") 663 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 664 665 containerIP := d.FindContainerIP(c, "test") 666 ip = net.ParseIP(containerIP) 667 c.Assert(bridgeIPNet.Contains(ip), check.Equals, true, 668 check.Commentf("Container IP-Address must be in the same subnet range : %s", 669 containerIP)) 670 deleteInterface(c, defaultNetworkBridge) 671 } 672 673 func (s *DockerDaemonSuite) TestDaemonRestartWithBridgeIPChange(c *check.C) { 674 s.d.Start(c) 675 defer s.d.Restart(c) 676 s.d.Stop(c) 677 678 // now we will change the docker0's IP and then try starting the daemon 679 bridgeIP := "192.169.100.1/24" 680 _, bridgeIPNet, _ := net.ParseCIDR(bridgeIP) 681 682 icmd.RunCommand("ifconfig", "docker0", bridgeIP).Assert(c, icmd.Success) 683 684 s.d.Start(c, "--bip", bridgeIP) 685 686 //check if the iptables contains new bridgeIP MASQUERADE rule 687 ipTablesSearchString := bridgeIPNet.String() 688 icmd.RunCommand("iptables", "-t", "nat", "-nvL").Assert(c, icmd.Expected{ 689 Out: ipTablesSearchString, 690 }) 691 } 692 693 func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr(c *check.C) { 694 d := s.d 695 696 bridgeName := "external-bridge" 697 bridgeIP := "192.169.1.1/24" 698 699 createInterface(c, "bridge", bridgeName, bridgeIP) 700 defer deleteInterface(c, bridgeName) 701 702 args := []string{"--bridge", bridgeName, "--fixed-cidr", "192.169.1.0/30"} 703 d.StartWithBusybox(c, args...) 704 defer d.Restart(c) 705 706 for i := 0; i < 4; i++ { 707 cName := "Container" + strconv.Itoa(i) 708 out, err := d.Cmd("run", "-d", "--name", cName, "busybox", "top") 709 if err != nil { 710 c.Assert(strings.Contains(out, "no available IPv4 addresses"), check.Equals, true, 711 check.Commentf("Could not run a Container : %s %s", err.Error(), out)) 712 } 713 } 714 } 715 716 func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr2(c *check.C) { 717 d := s.d 718 719 bridgeName := "external-bridge" 720 bridgeIP := "10.2.2.1/16" 721 722 createInterface(c, "bridge", bridgeName, bridgeIP) 723 defer deleteInterface(c, bridgeName) 724 725 d.StartWithBusybox(c, "--bip", bridgeIP, "--fixed-cidr", "10.2.2.0/24") 726 defer s.d.Restart(c) 727 728 out, err := d.Cmd("run", "-d", "--name", "bb", "busybox", "top") 729 c.Assert(err, checker.IsNil, check.Commentf("%s", out)) 730 defer d.Cmd("stop", "bb") 731 732 out, err = d.Cmd("exec", "bb", "/bin/sh", "-c", "ifconfig eth0 | awk '/inet addr/{print substr($2,6)}'") 733 c.Assert(err, check.IsNil) 734 c.Assert(out, checker.Equals, "10.2.2.0\n") 735 736 out, err = d.Cmd("run", "--rm", "busybox", "/bin/sh", "-c", "ifconfig eth0 | awk '/inet addr/{print substr($2,6)}'") 737 c.Assert(err, checker.IsNil, check.Commentf("%s", out)) 738 c.Assert(out, checker.Equals, "10.2.2.2\n") 739 } 740 741 func (s *DockerDaemonSuite) TestDaemonBridgeFixedCIDREqualBridgeNetwork(c *check.C) { 742 d := s.d 743 744 bridgeName := "external-bridge" 745 bridgeIP := "172.27.42.1/16" 746 747 createInterface(c, "bridge", bridgeName, bridgeIP) 748 defer deleteInterface(c, bridgeName) 749 750 d.StartWithBusybox(c, "--bridge", bridgeName, "--fixed-cidr", bridgeIP) 751 defer s.d.Restart(c) 752 753 out, err := d.Cmd("run", "-d", "busybox", "top") 754 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 755 cid1 := strings.TrimSpace(out) 756 defer d.Cmd("stop", cid1) 757 } 758 759 func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4Implicit(c *check.C) { 760 defaultNetworkBridge := "docker0" 761 deleteInterface(c, defaultNetworkBridge) 762 763 d := s.d 764 765 bridgeIP := "192.169.1.1" 766 bridgeIPNet := fmt.Sprintf("%s/24", bridgeIP) 767 768 d.StartWithBusybox(c, "--bip", bridgeIPNet) 769 defer d.Restart(c) 770 771 expectedMessage := fmt.Sprintf("default via %s dev", bridgeIP) 772 out, err := d.Cmd("run", "busybox", "ip", "-4", "route", "list", "0/0") 773 c.Assert(err, checker.IsNil, check.Commentf("%s", out)) 774 c.Assert(strings.Contains(out, expectedMessage), check.Equals, true, 775 check.Commentf("Implicit default gateway should be bridge IP %s, but default route was '%s'", 776 bridgeIP, strings.TrimSpace(out))) 777 deleteInterface(c, defaultNetworkBridge) 778 } 779 780 func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4Explicit(c *check.C) { 781 defaultNetworkBridge := "docker0" 782 deleteInterface(c, defaultNetworkBridge) 783 784 d := s.d 785 786 bridgeIP := "192.169.1.1" 787 bridgeIPNet := fmt.Sprintf("%s/24", bridgeIP) 788 gatewayIP := "192.169.1.254" 789 790 d.StartWithBusybox(c, "--bip", bridgeIPNet, "--default-gateway", gatewayIP) 791 defer d.Restart(c) 792 793 expectedMessage := fmt.Sprintf("default via %s dev", gatewayIP) 794 out, err := d.Cmd("run", "busybox", "ip", "-4", "route", "list", "0/0") 795 c.Assert(err, checker.IsNil, check.Commentf("%s", out)) 796 c.Assert(strings.Contains(out, expectedMessage), check.Equals, true, 797 check.Commentf("Explicit default gateway should be %s, but default route was '%s'", 798 gatewayIP, strings.TrimSpace(out))) 799 deleteInterface(c, defaultNetworkBridge) 800 } 801 802 func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4ExplicitOutsideContainerSubnet(c *check.C) { 803 defaultNetworkBridge := "docker0" 804 deleteInterface(c, defaultNetworkBridge) 805 806 // Program a custom default gateway outside of the container subnet, daemon should accept it and start 807 s.d.StartWithBusybox(c, "--bip", "172.16.0.10/16", "--fixed-cidr", "172.16.1.0/24", "--default-gateway", "172.16.0.254") 808 809 deleteInterface(c, defaultNetworkBridge) 810 s.d.Restart(c) 811 } 812 813 func (s *DockerDaemonSuite) TestDaemonDefaultNetworkInvalidClusterConfig(c *check.C) { 814 testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) 815 816 // Start daemon without docker0 bridge 817 defaultNetworkBridge := "docker0" 818 deleteInterface(c, defaultNetworkBridge) 819 820 discoveryBackend := "consul://consuladdr:consulport/some/path" 821 s.d.Start(c, fmt.Sprintf("--cluster-store=%s", discoveryBackend)) 822 823 // Start daemon with docker0 bridge 824 result := icmd.RunCommand("ifconfig", defaultNetworkBridge) 825 result.Assert(c, icmd.Success) 826 827 s.d.Restart(c, fmt.Sprintf("--cluster-store=%s", discoveryBackend)) 828 } 829 830 func (s *DockerDaemonSuite) TestDaemonIP(c *check.C) { 831 d := s.d 832 833 ipStr := "192.170.1.1/24" 834 ip, _, _ := net.ParseCIDR(ipStr) 835 args := []string{"--ip", ip.String()} 836 d.StartWithBusybox(c, args...) 837 defer d.Restart(c) 838 839 out, err := d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top") 840 c.Assert(err, check.NotNil, 841 check.Commentf("Running a container must fail with an invalid --ip option")) 842 c.Assert(strings.Contains(out, "Error starting userland proxy"), check.Equals, true) 843 844 ifName := "dummy" 845 createInterface(c, "dummy", ifName, ipStr) 846 defer deleteInterface(c, ifName) 847 848 _, err = d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top") 849 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 850 851 result := icmd.RunCommand("iptables", "-t", "nat", "-nvL") 852 result.Assert(c, icmd.Success) 853 regex := fmt.Sprintf("DNAT.*%s.*dpt:8000", ip.String()) 854 matched, _ := regexp.MatchString(regex, result.Combined()) 855 c.Assert(matched, check.Equals, true, 856 check.Commentf("iptables output should have contained %q, but was %q", regex, result.Combined())) 857 } 858 859 func (s *DockerDaemonSuite) TestDaemonICCPing(c *check.C) { 860 testRequires(c, bridgeNfIptables) 861 d := s.d 862 863 bridgeName := "external-bridge" 864 bridgeIP := "192.169.1.1/24" 865 866 createInterface(c, "bridge", bridgeName, bridgeIP) 867 defer deleteInterface(c, bridgeName) 868 869 d.StartWithBusybox(c, "--bridge", bridgeName, "--icc=false") 870 defer d.Restart(c) 871 872 result := icmd.RunCommand("iptables", "-nvL", "FORWARD") 873 result.Assert(c, icmd.Success) 874 regex := fmt.Sprintf("DROP.*all.*%s.*%s", bridgeName, bridgeName) 875 matched, _ := regexp.MatchString(regex, result.Combined()) 876 c.Assert(matched, check.Equals, true, 877 check.Commentf("iptables output should have contained %q, but was %q", regex, result.Combined())) 878 879 // Pinging another container must fail with --icc=false 880 pingContainers(c, d, true) 881 882 ipStr := "192.171.1.1/24" 883 ip, _, _ := net.ParseCIDR(ipStr) 884 ifName := "icc-dummy" 885 886 createInterface(c, "dummy", ifName, ipStr) 887 888 // But, Pinging external or a Host interface must succeed 889 pingCmd := fmt.Sprintf("ping -c 1 %s -W 1", ip.String()) 890 runArgs := []string{"run", "--rm", "busybox", "sh", "-c", pingCmd} 891 out, err := d.Cmd(runArgs...) 892 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 893 } 894 895 func (s *DockerDaemonSuite) TestDaemonICCLinkExpose(c *check.C) { 896 d := s.d 897 898 bridgeName := "external-bridge" 899 bridgeIP := "192.169.1.1/24" 900 901 createInterface(c, "bridge", bridgeName, bridgeIP) 902 defer deleteInterface(c, bridgeName) 903 904 d.StartWithBusybox(c, "--bridge", bridgeName, "--icc=false") 905 defer d.Restart(c) 906 907 result := icmd.RunCommand("iptables", "-nvL", "FORWARD") 908 result.Assert(c, icmd.Success) 909 regex := fmt.Sprintf("DROP.*all.*%s.*%s", bridgeName, bridgeName) 910 matched, _ := regexp.MatchString(regex, result.Combined()) 911 c.Assert(matched, check.Equals, true, 912 check.Commentf("iptables output should have contained %q, but was %q", regex, result.Combined())) 913 914 out, err := d.Cmd("run", "-d", "--expose", "4567", "--name", "icc1", "busybox", "nc", "-l", "-p", "4567") 915 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 916 917 out, err = d.Cmd("run", "--link", "icc1:icc1", "busybox", "nc", "icc1", "4567") 918 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 919 } 920 921 func (s *DockerDaemonSuite) TestDaemonLinksIpTablesRulesWhenLinkAndUnlink(c *check.C) { 922 bridgeName := "external-bridge" 923 bridgeIP := "192.169.1.1/24" 924 925 createInterface(c, "bridge", bridgeName, bridgeIP) 926 defer deleteInterface(c, bridgeName) 927 928 s.d.StartWithBusybox(c, "--bridge", bridgeName, "--icc=false") 929 defer s.d.Restart(c) 930 931 out, err := s.d.Cmd("run", "-d", "--name", "child", "--publish", "8080:80", "busybox", "top") 932 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 933 out, err = s.d.Cmd("run", "-d", "--name", "parent", "--link", "child:http", "busybox", "top") 934 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 935 936 childIP := s.d.FindContainerIP(c, "child") 937 parentIP := s.d.FindContainerIP(c, "parent") 938 939 sourceRule := []string{"-i", bridgeName, "-o", bridgeName, "-p", "tcp", "-s", childIP, "--sport", "80", "-d", parentIP, "-j", "ACCEPT"} 940 destinationRule := []string{"-i", bridgeName, "-o", bridgeName, "-p", "tcp", "-s", parentIP, "--dport", "80", "-d", childIP, "-j", "ACCEPT"} 941 if !iptables.Exists("filter", "DOCKER", sourceRule...) || !iptables.Exists("filter", "DOCKER", destinationRule...) { 942 c.Fatal("Iptables rules not found") 943 } 944 945 s.d.Cmd("rm", "--link", "parent/http") 946 if iptables.Exists("filter", "DOCKER", sourceRule...) || iptables.Exists("filter", "DOCKER", destinationRule...) { 947 c.Fatal("Iptables rules should be removed when unlink") 948 } 949 950 s.d.Cmd("kill", "child") 951 s.d.Cmd("kill", "parent") 952 } 953 954 func (s *DockerDaemonSuite) TestDaemonUlimitDefaults(c *check.C) { 955 testRequires(c, DaemonIsLinux) 956 957 s.d.StartWithBusybox(c, "--default-ulimit", "nofile=42:42", "--default-ulimit", "nproc=1024:1024") 958 959 out, err := s.d.Cmd("run", "--ulimit", "nproc=2048", "--name=test", "busybox", "/bin/sh", "-c", "echo $(ulimit -n); echo $(ulimit -p)") 960 if err != nil { 961 c.Fatal(err, out) 962 } 963 964 outArr := strings.Split(out, "\n") 965 if len(outArr) < 2 { 966 c.Fatalf("got unexpected output: %s", out) 967 } 968 nofile := strings.TrimSpace(outArr[0]) 969 nproc := strings.TrimSpace(outArr[1]) 970 971 if nofile != "42" { 972 c.Fatalf("expected `ulimit -n` to be `42`, got: %s", nofile) 973 } 974 if nproc != "2048" { 975 c.Fatalf("expected `ulimit -p` to be 2048, got: %s", nproc) 976 } 977 978 // Now restart daemon with a new default 979 s.d.Restart(c, "--default-ulimit", "nofile=43") 980 981 out, err = s.d.Cmd("start", "-a", "test") 982 if err != nil { 983 c.Fatal(err, out) 984 } 985 986 outArr = strings.Split(out, "\n") 987 if len(outArr) < 2 { 988 c.Fatalf("got unexpected output: %s", out) 989 } 990 nofile = strings.TrimSpace(outArr[0]) 991 nproc = strings.TrimSpace(outArr[1]) 992 993 if nofile != "43" { 994 c.Fatalf("expected `ulimit -n` to be `43`, got: %s", nofile) 995 } 996 if nproc != "2048" { 997 c.Fatalf("expected `ulimit -p` to be 2048, got: %s", nproc) 998 } 999 } 1000 1001 // #11315 1002 func (s *DockerDaemonSuite) TestDaemonRestartRenameContainer(c *check.C) { 1003 s.d.StartWithBusybox(c) 1004 1005 if out, err := s.d.Cmd("run", "--name=test", "busybox"); err != nil { 1006 c.Fatal(err, out) 1007 } 1008 1009 if out, err := s.d.Cmd("rename", "test", "test2"); err != nil { 1010 c.Fatal(err, out) 1011 } 1012 1013 s.d.Restart(c) 1014 1015 if out, err := s.d.Cmd("start", "test2"); err != nil { 1016 c.Fatal(err, out) 1017 } 1018 } 1019 1020 func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefault(c *check.C) { 1021 s.d.StartWithBusybox(c) 1022 1023 out, err := s.d.Cmd("run", "--name=test", "busybox", "echo", "testline") 1024 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 1025 id, err := s.d.GetIDByName("test") 1026 c.Assert(err, check.IsNil) 1027 1028 logPath := filepath.Join(s.d.Root, "containers", id, id+"-json.log") 1029 1030 if _, err := os.Stat(logPath); err != nil { 1031 c.Fatal(err) 1032 } 1033 f, err := os.Open(logPath) 1034 if err != nil { 1035 c.Fatal(err) 1036 } 1037 defer f.Close() 1038 1039 var res struct { 1040 Log string `json:"log"` 1041 Stream string `json:"stream"` 1042 Time time.Time `json:"time"` 1043 } 1044 if err := json.NewDecoder(f).Decode(&res); err != nil { 1045 c.Fatal(err) 1046 } 1047 if res.Log != "testline\n" { 1048 c.Fatalf("Unexpected log line: %q, expected: %q", res.Log, "testline\n") 1049 } 1050 if res.Stream != "stdout" { 1051 c.Fatalf("Unexpected stream: %q, expected: %q", res.Stream, "stdout") 1052 } 1053 if !time.Now().After(res.Time) { 1054 c.Fatalf("Log time %v in future", res.Time) 1055 } 1056 } 1057 1058 func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefaultOverride(c *check.C) { 1059 s.d.StartWithBusybox(c) 1060 1061 out, err := s.d.Cmd("run", "--name=test", "--log-driver=none", "busybox", "echo", "testline") 1062 if err != nil { 1063 c.Fatal(out, err) 1064 } 1065 id, err := s.d.GetIDByName("test") 1066 c.Assert(err, check.IsNil) 1067 1068 logPath := filepath.Join(s.d.Root, "containers", id, id+"-json.log") 1069 1070 if _, err := os.Stat(logPath); err == nil || !os.IsNotExist(err) { 1071 c.Fatalf("%s shouldn't exits, error on Stat: %s", logPath, err) 1072 } 1073 } 1074 1075 func (s *DockerDaemonSuite) TestDaemonLoggingDriverNone(c *check.C) { 1076 s.d.StartWithBusybox(c, "--log-driver=none") 1077 1078 out, err := s.d.Cmd("run", "--name=test", "busybox", "echo", "testline") 1079 if err != nil { 1080 c.Fatal(out, err) 1081 } 1082 id, err := s.d.GetIDByName("test") 1083 c.Assert(err, check.IsNil) 1084 1085 logPath := filepath.Join(s.d.Root, "containers", id, id+"-json.log") 1086 1087 if _, err := os.Stat(logPath); err == nil || !os.IsNotExist(err) { 1088 c.Fatalf("%s shouldn't exits, error on Stat: %s", logPath, err) 1089 } 1090 } 1091 1092 func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneOverride(c *check.C) { 1093 s.d.StartWithBusybox(c, "--log-driver=none") 1094 1095 out, err := s.d.Cmd("run", "--name=test", "--log-driver=json-file", "busybox", "echo", "testline") 1096 if err != nil { 1097 c.Fatal(out, err) 1098 } 1099 id, err := s.d.GetIDByName("test") 1100 c.Assert(err, check.IsNil) 1101 1102 logPath := filepath.Join(s.d.Root, "containers", id, id+"-json.log") 1103 1104 if _, err := os.Stat(logPath); err != nil { 1105 c.Fatal(err) 1106 } 1107 f, err := os.Open(logPath) 1108 if err != nil { 1109 c.Fatal(err) 1110 } 1111 defer f.Close() 1112 1113 var res struct { 1114 Log string `json:"log"` 1115 Stream string `json:"stream"` 1116 Time time.Time `json:"time"` 1117 } 1118 if err := json.NewDecoder(f).Decode(&res); err != nil { 1119 c.Fatal(err) 1120 } 1121 if res.Log != "testline\n" { 1122 c.Fatalf("Unexpected log line: %q, expected: %q", res.Log, "testline\n") 1123 } 1124 if res.Stream != "stdout" { 1125 c.Fatalf("Unexpected stream: %q, expected: %q", res.Stream, "stdout") 1126 } 1127 if !time.Now().After(res.Time) { 1128 c.Fatalf("Log time %v in future", res.Time) 1129 } 1130 } 1131 1132 func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneLogsError(c *check.C) { 1133 s.d.StartWithBusybox(c, "--log-driver=none") 1134 1135 out, err := s.d.Cmd("run", "--name=test", "busybox", "echo", "testline") 1136 c.Assert(err, checker.IsNil, check.Commentf("%s", out)) 1137 1138 out, err = s.d.Cmd("logs", "test") 1139 c.Assert(err, check.NotNil, check.Commentf("Logs should fail with 'none' driver")) 1140 expected := `configured logging driver does not support reading` 1141 c.Assert(out, checker.Contains, expected) 1142 } 1143 1144 func (s *DockerDaemonSuite) TestDaemonLoggingDriverShouldBeIgnoredForBuild(c *check.C) { 1145 s.d.StartWithBusybox(c, "--log-driver=splunk") 1146 1147 result := cli.BuildCmd(c, "busyboxs", cli.Daemon(s.d), 1148 build.WithDockerfile(` 1149 FROM busybox 1150 RUN echo foo`), 1151 build.WithoutCache, 1152 ) 1153 comment := check.Commentf("Failed to build image. output %s, exitCode %d, err %v", result.Combined(), result.ExitCode, result.Error) 1154 c.Assert(result.Error, check.IsNil, comment) 1155 c.Assert(result.ExitCode, check.Equals, 0, comment) 1156 c.Assert(result.Combined(), checker.Contains, "foo", comment) 1157 } 1158 1159 func (s *DockerDaemonSuite) TestDaemonUnixSockCleanedUp(c *check.C) { 1160 dir, err := ioutil.TempDir("", "socket-cleanup-test") 1161 if err != nil { 1162 c.Fatal(err) 1163 } 1164 defer os.RemoveAll(dir) 1165 1166 sockPath := filepath.Join(dir, "docker.sock") 1167 s.d.Start(c, "--host", "unix://"+sockPath) 1168 1169 if _, err := os.Stat(sockPath); err != nil { 1170 c.Fatal("socket does not exist") 1171 } 1172 1173 s.d.Stop(c) 1174 1175 if _, err := os.Stat(sockPath); err == nil || !os.IsNotExist(err) { 1176 c.Fatal("unix socket is not cleaned up") 1177 } 1178 } 1179 1180 func (s *DockerDaemonSuite) TestDaemonRestartKillWait(c *check.C) { 1181 s.d.StartWithBusybox(c) 1182 1183 out, err := s.d.Cmd("run", "-id", "busybox", "/bin/cat") 1184 if err != nil { 1185 c.Fatalf("Could not run /bin/cat: err=%v\n%s", err, out) 1186 } 1187 containerID := strings.TrimSpace(out) 1188 1189 if out, err := s.d.Cmd("kill", containerID); err != nil { 1190 c.Fatalf("Could not kill %s: err=%v\n%s", containerID, err, out) 1191 } 1192 1193 s.d.Restart(c) 1194 1195 errchan := make(chan error) 1196 go func() { 1197 if out, err := s.d.Cmd("wait", containerID); err != nil { 1198 errchan <- fmt.Errorf("%v:\n%s", err, out) 1199 } 1200 close(errchan) 1201 }() 1202 1203 select { 1204 case <-time.After(5 * time.Second): 1205 c.Fatal("Waiting on a stopped (killed) container timed out") 1206 case err := <-errchan: 1207 if err != nil { 1208 c.Fatal(err) 1209 } 1210 } 1211 } 1212 1213 // TestHTTPSInfo connects via two-way authenticated HTTPS to the info endpoint 1214 func (s *DockerDaemonSuite) TestHTTPSInfo(c *check.C) { 1215 const ( 1216 testDaemonHTTPSAddr = "tcp://localhost:4271" 1217 ) 1218 1219 s.d.Start(c, 1220 "--tlsverify", 1221 "--tlscacert", "fixtures/https/ca.pem", 1222 "--tlscert", "fixtures/https/server-cert.pem", 1223 "--tlskey", "fixtures/https/server-key.pem", 1224 "-H", testDaemonHTTPSAddr) 1225 1226 args := []string{ 1227 "--host", testDaemonHTTPSAddr, 1228 "--tlsverify", 1229 "--tlscacert", "fixtures/https/ca.pem", 1230 "--tlscert", "fixtures/https/client-cert.pem", 1231 "--tlskey", "fixtures/https/client-key.pem", 1232 "info", 1233 } 1234 out, err := s.d.Cmd(args...) 1235 if err != nil { 1236 c.Fatalf("Error Occurred: %s and output: %s", err, out) 1237 } 1238 } 1239 1240 // TestHTTPSRun connects via two-way authenticated HTTPS to the create, attach, start, and wait endpoints. 1241 // https://github.com/docker/docker/issues/19280 1242 func (s *DockerDaemonSuite) TestHTTPSRun(c *check.C) { 1243 const ( 1244 testDaemonHTTPSAddr = "tcp://localhost:4271" 1245 ) 1246 1247 s.d.StartWithBusybox(c, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-cert.pem", 1248 "--tlskey", "fixtures/https/server-key.pem", "-H", testDaemonHTTPSAddr) 1249 1250 args := []string{ 1251 "--host", testDaemonHTTPSAddr, 1252 "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", 1253 "--tlscert", "fixtures/https/client-cert.pem", 1254 "--tlskey", "fixtures/https/client-key.pem", 1255 "run", "busybox", "echo", "TLS response", 1256 } 1257 out, err := s.d.Cmd(args...) 1258 if err != nil { 1259 c.Fatalf("Error Occurred: %s and output: %s", err, out) 1260 } 1261 1262 if !strings.Contains(out, "TLS response") { 1263 c.Fatalf("expected output to include `TLS response`, got %v", out) 1264 } 1265 } 1266 1267 // TestTLSVerify verifies that --tlsverify=false turns on tls 1268 func (s *DockerDaemonSuite) TestTLSVerify(c *check.C) { 1269 out, err := exec.Command(dockerdBinary, "--tlsverify=false").CombinedOutput() 1270 if err == nil || !strings.Contains(string(out), "Could not load X509 key pair") { 1271 c.Fatalf("Daemon should not have started due to missing certs: %v\n%s", err, string(out)) 1272 } 1273 } 1274 1275 // TestHTTPSInfoRogueCert connects via two-way authenticated HTTPS to the info endpoint 1276 // by using a rogue client certificate and checks that it fails with the expected error. 1277 func (s *DockerDaemonSuite) TestHTTPSInfoRogueCert(c *check.C) { 1278 const ( 1279 errBadCertificate = "bad certificate" 1280 testDaemonHTTPSAddr = "tcp://localhost:4271" 1281 ) 1282 1283 s.d.Start(c, 1284 "--tlsverify", 1285 "--tlscacert", "fixtures/https/ca.pem", 1286 "--tlscert", "fixtures/https/server-cert.pem", 1287 "--tlskey", "fixtures/https/server-key.pem", 1288 "-H", testDaemonHTTPSAddr) 1289 1290 args := []string{ 1291 "--host", testDaemonHTTPSAddr, 1292 "--tlsverify", 1293 "--tlscacert", "fixtures/https/ca.pem", 1294 "--tlscert", "fixtures/https/client-rogue-cert.pem", 1295 "--tlskey", "fixtures/https/client-rogue-key.pem", 1296 "info", 1297 } 1298 out, err := s.d.Cmd(args...) 1299 if err == nil || !strings.Contains(out, errBadCertificate) { 1300 c.Fatalf("Expected err: %s, got instead: %s and output: %s", errBadCertificate, err, out) 1301 } 1302 } 1303 1304 // TestHTTPSInfoRogueServerCert connects via two-way authenticated HTTPS to the info endpoint 1305 // which provides a rogue server certificate and checks that it fails with the expected error 1306 func (s *DockerDaemonSuite) TestHTTPSInfoRogueServerCert(c *check.C) { 1307 const ( 1308 errCaUnknown = "x509: certificate signed by unknown authority" 1309 testDaemonRogueHTTPSAddr = "tcp://localhost:4272" 1310 ) 1311 s.d.Start(c, 1312 "--tlsverify", 1313 "--tlscacert", "fixtures/https/ca.pem", 1314 "--tlscert", "fixtures/https/server-rogue-cert.pem", 1315 "--tlskey", "fixtures/https/server-rogue-key.pem", 1316 "-H", testDaemonRogueHTTPSAddr) 1317 1318 args := []string{ 1319 "--host", testDaemonRogueHTTPSAddr, 1320 "--tlsverify", 1321 "--tlscacert", "fixtures/https/ca.pem", 1322 "--tlscert", "fixtures/https/client-rogue-cert.pem", 1323 "--tlskey", "fixtures/https/client-rogue-key.pem", 1324 "info", 1325 } 1326 out, err := s.d.Cmd(args...) 1327 if err == nil || !strings.Contains(out, errCaUnknown) { 1328 c.Fatalf("Expected err: %s, got instead: %s and output: %s", errCaUnknown, err, out) 1329 } 1330 } 1331 1332 func pingContainers(c *check.C, d *daemon.Daemon, expectFailure bool) { 1333 var dargs []string 1334 if d != nil { 1335 dargs = []string{"--host", d.Sock()} 1336 } 1337 1338 args := append(dargs, "run", "-d", "--name", "container1", "busybox", "top") 1339 dockerCmd(c, args...) 1340 1341 args = append(dargs, "run", "--rm", "--link", "container1:alias1", "busybox", "sh", "-c") 1342 pingCmd := "ping -c 1 %s -W 1" 1343 args = append(args, fmt.Sprintf(pingCmd, "alias1")) 1344 _, _, err := dockerCmdWithError(args...) 1345 1346 if expectFailure { 1347 c.Assert(err, check.NotNil) 1348 } else { 1349 c.Assert(err, check.IsNil) 1350 } 1351 1352 args = append(dargs, "rm", "-f", "container1") 1353 dockerCmd(c, args...) 1354 } 1355 1356 func (s *DockerDaemonSuite) TestDaemonRestartWithSocketAsVolume(c *check.C) { 1357 s.d.StartWithBusybox(c) 1358 1359 socket := filepath.Join(s.d.Folder, "docker.sock") 1360 1361 out, err := s.d.Cmd("run", "--restart=always", "-v", socket+":/sock", "busybox") 1362 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1363 s.d.Restart(c) 1364 } 1365 1366 // os.Kill should kill daemon ungracefully, leaving behind container mounts. 1367 // A subsequent daemon restart should clean up said mounts. 1368 func (s *DockerDaemonSuite) TestCleanupMountsAfterDaemonAndContainerKill(c *check.C) { 1369 d := daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) 1370 d.StartWithBusybox(c) 1371 1372 out, err := d.Cmd("run", "-d", "busybox", "top") 1373 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1374 id := strings.TrimSpace(out) 1375 1376 // If there are no mounts with container id visible from the host 1377 // (as those are in container's own mount ns), there is nothing 1378 // to check here and the test should be skipped. 1379 mountOut, err := ioutil.ReadFile("/proc/self/mountinfo") 1380 c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut)) 1381 if !strings.Contains(string(mountOut), id) { 1382 d.Stop(c) 1383 c.Skip("no container mounts visible in host ns") 1384 } 1385 1386 // kill the daemon 1387 c.Assert(d.Kill(), check.IsNil) 1388 1389 // kill the container 1390 icmd.RunCommand(ctrBinary, "--address", containerdSocket, 1391 "--namespace", moby_daemon.ContainersNamespace, "tasks", "kill", id).Assert(c, icmd.Success) 1392 1393 // restart daemon. 1394 d.Restart(c) 1395 1396 // Now, container mounts should be gone. 1397 mountOut, err = ioutil.ReadFile("/proc/self/mountinfo") 1398 c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut)) 1399 comment := check.Commentf("%s is still mounted from older daemon start:\nDaemon root repository %s\n%s", id, d.Root, mountOut) 1400 c.Assert(strings.Contains(string(mountOut), id), check.Equals, false, comment) 1401 1402 d.Stop(c) 1403 } 1404 1405 // os.Interrupt should perform a graceful daemon shutdown and hence cleanup mounts. 1406 func (s *DockerDaemonSuite) TestCleanupMountsAfterGracefulShutdown(c *check.C) { 1407 d := daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) 1408 d.StartWithBusybox(c) 1409 1410 out, err := d.Cmd("run", "-d", "busybox", "top") 1411 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1412 id := strings.TrimSpace(out) 1413 1414 // Send SIGINT and daemon should clean up 1415 c.Assert(d.Signal(os.Interrupt), check.IsNil) 1416 // Wait for the daemon to stop. 1417 c.Assert(<-d.Wait, checker.IsNil) 1418 1419 mountOut, err := ioutil.ReadFile("/proc/self/mountinfo") 1420 c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut)) 1421 1422 comment := check.Commentf("%s is still mounted from older daemon start:\nDaemon root repository %s\n%s", id, d.Root, mountOut) 1423 c.Assert(strings.Contains(string(mountOut), id), check.Equals, false, comment) 1424 } 1425 1426 func (s *DockerDaemonSuite) TestDaemonRestartWithContainerRunning(t *check.C) { 1427 s.d.StartWithBusybox(t) 1428 if out, err := s.d.Cmd("run", "-d", "--name", "test", "busybox", "top"); err != nil { 1429 t.Fatal(out, err) 1430 } 1431 1432 s.d.Restart(t) 1433 // Container 'test' should be removed without error 1434 if out, err := s.d.Cmd("rm", "test"); err != nil { 1435 t.Fatal(out, err) 1436 } 1437 } 1438 1439 func (s *DockerDaemonSuite) TestDaemonRestartCleanupNetns(c *check.C) { 1440 s.d.StartWithBusybox(c) 1441 out, err := s.d.Cmd("run", "--name", "netns", "-d", "busybox", "top") 1442 if err != nil { 1443 c.Fatal(out, err) 1444 } 1445 1446 // Get sandbox key via inspect 1447 out, err = s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.SandboxKey}}'", "netns") 1448 if err != nil { 1449 c.Fatalf("Error inspecting container: %s, %v", out, err) 1450 } 1451 fileName := strings.Trim(out, " \r\n'") 1452 1453 if out, err := s.d.Cmd("stop", "netns"); err != nil { 1454 c.Fatal(out, err) 1455 } 1456 1457 // Test if the file still exists 1458 icmd.RunCommand("stat", "-c", "%n", fileName).Assert(c, icmd.Expected{ 1459 Out: fileName, 1460 }) 1461 1462 // Remove the container and restart the daemon 1463 if out, err := s.d.Cmd("rm", "netns"); err != nil { 1464 c.Fatal(out, err) 1465 } 1466 1467 s.d.Restart(c) 1468 1469 // Test again and see now the netns file does not exist 1470 icmd.RunCommand("stat", "-c", "%n", fileName).Assert(c, icmd.Expected{ 1471 Err: "No such file or directory", 1472 ExitCode: 1, 1473 }) 1474 } 1475 1476 // tests regression detailed in #13964 where DOCKER_TLS_VERIFY env is ignored 1477 func (s *DockerDaemonSuite) TestDaemonTLSVerifyIssue13964(c *check.C) { 1478 host := "tcp://localhost:4271" 1479 s.d.Start(c, "-H", host) 1480 icmd.RunCmd(icmd.Cmd{ 1481 Command: []string{dockerBinary, "-H", host, "info"}, 1482 Env: []string{"DOCKER_TLS_VERIFY=1", "DOCKER_CERT_PATH=fixtures/https"}, 1483 }).Assert(c, icmd.Expected{ 1484 ExitCode: 1, 1485 Err: "error during connect", 1486 }) 1487 } 1488 1489 func setupV6(c *check.C) { 1490 // Hack to get the right IPv6 address on docker0, which has already been created 1491 result := icmd.RunCommand("ip", "addr", "add", "fe80::1/64", "dev", "docker0") 1492 result.Assert(c, icmd.Success) 1493 } 1494 1495 func teardownV6(c *check.C) { 1496 result := icmd.RunCommand("ip", "addr", "del", "fe80::1/64", "dev", "docker0") 1497 result.Assert(c, icmd.Success) 1498 } 1499 1500 func (s *DockerDaemonSuite) TestDaemonRestartWithContainerWithRestartPolicyAlways(c *check.C) { 1501 s.d.StartWithBusybox(c) 1502 1503 out, err := s.d.Cmd("run", "-d", "--restart", "always", "busybox", "top") 1504 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 1505 id := strings.TrimSpace(out) 1506 1507 out, err = s.d.Cmd("stop", id) 1508 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 1509 out, err = s.d.Cmd("wait", id) 1510 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 1511 1512 out, err = s.d.Cmd("ps", "-q") 1513 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 1514 c.Assert(out, check.Equals, "") 1515 1516 s.d.Restart(c) 1517 1518 out, err = s.d.Cmd("ps", "-q") 1519 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 1520 c.Assert(strings.TrimSpace(out), check.Equals, id[:12]) 1521 } 1522 1523 func (s *DockerDaemonSuite) TestDaemonWideLogConfig(c *check.C) { 1524 s.d.StartWithBusybox(c, "--log-opt=max-size=1k") 1525 name := "logtest" 1526 out, err := s.d.Cmd("run", "-d", "--log-opt=max-file=5", "--name", name, "busybox", "top") 1527 c.Assert(err, check.IsNil, check.Commentf("Output: %s, err: %v", out, err)) 1528 1529 out, err = s.d.Cmd("inspect", "-f", "{{ .HostConfig.LogConfig.Config }}", name) 1530 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1531 c.Assert(out, checker.Contains, "max-size:1k") 1532 c.Assert(out, checker.Contains, "max-file:5") 1533 1534 out, err = s.d.Cmd("inspect", "-f", "{{ .HostConfig.LogConfig.Type }}", name) 1535 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1536 c.Assert(strings.TrimSpace(out), checker.Equals, "json-file") 1537 } 1538 1539 func (s *DockerDaemonSuite) TestDaemonRestartWithPausedContainer(c *check.C) { 1540 s.d.StartWithBusybox(c) 1541 if out, err := s.d.Cmd("run", "-i", "-d", "--name", "test", "busybox", "top"); err != nil { 1542 c.Fatal(err, out) 1543 } 1544 if out, err := s.d.Cmd("pause", "test"); err != nil { 1545 c.Fatal(err, out) 1546 } 1547 s.d.Restart(c) 1548 1549 errchan := make(chan error) 1550 go func() { 1551 out, err := s.d.Cmd("start", "test") 1552 if err != nil { 1553 errchan <- fmt.Errorf("%v:\n%s", err, out) 1554 } 1555 name := strings.TrimSpace(out) 1556 if name != "test" { 1557 errchan <- fmt.Errorf("Paused container start error on docker daemon restart, expected 'test' but got '%s'", name) 1558 } 1559 close(errchan) 1560 }() 1561 1562 select { 1563 case <-time.After(5 * time.Second): 1564 c.Fatal("Waiting on start a container timed out") 1565 case err := <-errchan: 1566 if err != nil { 1567 c.Fatal(err) 1568 } 1569 } 1570 } 1571 1572 func (s *DockerDaemonSuite) TestDaemonRestartRmVolumeInUse(c *check.C) { 1573 s.d.StartWithBusybox(c) 1574 1575 out, err := s.d.Cmd("create", "-v", "test:/foo", "busybox") 1576 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 1577 1578 s.d.Restart(c) 1579 1580 out, err = s.d.Cmd("volume", "rm", "test") 1581 c.Assert(err, check.NotNil, check.Commentf("should not be able to remove in use volume after daemon restart")) 1582 c.Assert(out, checker.Contains, "in use") 1583 } 1584 1585 func (s *DockerDaemonSuite) TestDaemonRestartLocalVolumes(c *check.C) { 1586 s.d.Start(c) 1587 1588 out, err := s.d.Cmd("volume", "create", "test") 1589 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 1590 s.d.Restart(c) 1591 1592 out, err = s.d.Cmd("volume", "inspect", "test") 1593 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 1594 } 1595 1596 // FIXME(vdemeester) should be a unit test 1597 func (s *DockerDaemonSuite) TestDaemonCorruptedLogDriverAddress(c *check.C) { 1598 d := daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) 1599 c.Assert(d.StartWithError("--log-driver=syslog", "--log-opt", "syslog-address=corrupted:42"), check.NotNil) 1600 expected := "syslog-address should be in form proto://address" 1601 icmd.RunCommand("grep", expected, d.LogFileName()).Assert(c, icmd.Success) 1602 } 1603 1604 // FIXME(vdemeester) should be a unit test 1605 func (s *DockerDaemonSuite) TestDaemonCorruptedFluentdAddress(c *check.C) { 1606 d := daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) 1607 c.Assert(d.StartWithError("--log-driver=fluentd", "--log-opt", "fluentd-address=corrupted:c"), check.NotNil) 1608 expected := "invalid fluentd-address corrupted:c: " 1609 icmd.RunCommand("grep", expected, d.LogFileName()).Assert(c, icmd.Success) 1610 } 1611 1612 // FIXME(vdemeester) Use a new daemon instance instead of the Suite one 1613 func (s *DockerDaemonSuite) TestDaemonStartWithoutHost(c *check.C) { 1614 s.d.UseDefaultHost = true 1615 defer func() { 1616 s.d.UseDefaultHost = false 1617 }() 1618 s.d.Start(c) 1619 } 1620 1621 // FIXME(vdemeester) Use a new daemon instance instead of the Suite one 1622 func (s *DockerDaemonSuite) TestDaemonStartWithDefaultTLSHost(c *check.C) { 1623 s.d.UseDefaultTLSHost = true 1624 defer func() { 1625 s.d.UseDefaultTLSHost = false 1626 }() 1627 s.d.Start(c, 1628 "--tlsverify", 1629 "--tlscacert", "fixtures/https/ca.pem", 1630 "--tlscert", "fixtures/https/server-cert.pem", 1631 "--tlskey", "fixtures/https/server-key.pem") 1632 1633 // The client with --tlsverify should also use default host localhost:2376 1634 tmpHost := os.Getenv("DOCKER_HOST") 1635 defer func() { 1636 os.Setenv("DOCKER_HOST", tmpHost) 1637 }() 1638 1639 os.Setenv("DOCKER_HOST", "") 1640 1641 out, _ := dockerCmd( 1642 c, 1643 "--tlsverify", 1644 "--tlscacert", "fixtures/https/ca.pem", 1645 "--tlscert", "fixtures/https/client-cert.pem", 1646 "--tlskey", "fixtures/https/client-key.pem", 1647 "version", 1648 ) 1649 if !strings.Contains(out, "Server") { 1650 c.Fatalf("docker version should return information of server side") 1651 } 1652 1653 // ensure when connecting to the server that only a single acceptable CA is requested 1654 contents, err := ioutil.ReadFile("fixtures/https/ca.pem") 1655 c.Assert(err, checker.IsNil) 1656 rootCert, err := helpers.ParseCertificatePEM(contents) 1657 c.Assert(err, checker.IsNil) 1658 rootPool := x509.NewCertPool() 1659 rootPool.AddCert(rootCert) 1660 1661 var certRequestInfo *tls.CertificateRequestInfo 1662 conn, err := tls.Dial("tcp", fmt.Sprintf("%s:%d", opts.DefaultHTTPHost, opts.DefaultTLSHTTPPort), &tls.Config{ 1663 RootCAs: rootPool, 1664 GetClientCertificate: func(cri *tls.CertificateRequestInfo) (*tls.Certificate, error) { 1665 certRequestInfo = cri 1666 cert, err := tls.LoadX509KeyPair("fixtures/https/client-cert.pem", "fixtures/https/client-key.pem") 1667 if err != nil { 1668 return nil, err 1669 } 1670 return &cert, nil 1671 }, 1672 }) 1673 c.Assert(err, checker.IsNil) 1674 conn.Close() 1675 1676 c.Assert(certRequestInfo, checker.NotNil) 1677 c.Assert(certRequestInfo.AcceptableCAs, checker.HasLen, 1) 1678 c.Assert(certRequestInfo.AcceptableCAs[0], checker.DeepEquals, rootCert.RawSubject) 1679 } 1680 1681 func (s *DockerDaemonSuite) TestBridgeIPIsExcludedFromAllocatorPool(c *check.C) { 1682 defaultNetworkBridge := "docker0" 1683 deleteInterface(c, defaultNetworkBridge) 1684 1685 bridgeIP := "192.169.1.1" 1686 bridgeRange := bridgeIP + "/30" 1687 1688 s.d.StartWithBusybox(c, "--bip", bridgeRange) 1689 defer s.d.Restart(c) 1690 1691 var cont int 1692 for { 1693 contName := fmt.Sprintf("container%d", cont) 1694 _, err := s.d.Cmd("run", "--name", contName, "-d", "busybox", "/bin/sleep", "2") 1695 if err != nil { 1696 // pool exhausted 1697 break 1698 } 1699 ip, err := s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.IPAddress}}'", contName) 1700 c.Assert(err, check.IsNil, check.Commentf("%s", ip)) 1701 1702 c.Assert(ip, check.Not(check.Equals), bridgeIP) 1703 cont++ 1704 } 1705 } 1706 1707 // Test daemon for no space left on device error 1708 func (s *DockerDaemonSuite) TestDaemonNoSpaceLeftOnDeviceError(c *check.C) { 1709 testRequires(c, testEnv.IsLocalDaemon, DaemonIsLinux, Network) 1710 1711 testDir, err := ioutil.TempDir("", "no-space-left-on-device-test") 1712 c.Assert(err, checker.IsNil) 1713 defer os.RemoveAll(testDir) 1714 c.Assert(mount.MakeRShared(testDir), checker.IsNil) 1715 defer mount.Unmount(testDir) 1716 1717 // create a 3MiB image (with a 2MiB ext4 fs) and mount it as graph root 1718 // Why in a container? Because `mount` sometimes behaves weirdly and often fails outright on this test in debian:jessie (which is what the test suite runs under if run from the Makefile) 1719 dockerCmd(c, "run", "--rm", "-v", testDir+":/test", "busybox", "sh", "-c", "dd of=/test/testfs.img bs=1M seek=3 count=0") 1720 icmd.RunCommand("mkfs.ext4", "-F", filepath.Join(testDir, "testfs.img")).Assert(c, icmd.Success) 1721 1722 dockerCmd(c, "run", "--privileged", "--rm", "-v", testDir+":/test:shared", "busybox", "sh", "-c", "mkdir -p /test/test-mount/vfs && mount -n /test/testfs.img /test/test-mount/vfs") 1723 defer mount.Unmount(filepath.Join(testDir, "test-mount")) 1724 1725 s.d.Start(c, "--storage-driver", "vfs", "--data-root", filepath.Join(testDir, "test-mount")) 1726 defer s.d.Stop(c) 1727 1728 // pull a repository large enough to overfill the mounted filesystem 1729 pullOut, err := s.d.Cmd("pull", "debian:stretch") 1730 c.Assert(err, checker.NotNil, check.Commentf("%s", pullOut)) 1731 c.Assert(pullOut, checker.Contains, "no space left on device") 1732 } 1733 1734 // Test daemon restart with container links + auto restart 1735 func (s *DockerDaemonSuite) TestDaemonRestartContainerLinksRestart(c *check.C) { 1736 s.d.StartWithBusybox(c) 1737 1738 var parent1Args []string 1739 var parent2Args []string 1740 wg := sync.WaitGroup{} 1741 maxChildren := 10 1742 chErr := make(chan error, maxChildren) 1743 1744 for i := 0; i < maxChildren; i++ { 1745 wg.Add(1) 1746 name := fmt.Sprintf("test%d", i) 1747 1748 if i < maxChildren/2 { 1749 parent1Args = append(parent1Args, []string{"--link", name}...) 1750 } else { 1751 parent2Args = append(parent2Args, []string{"--link", name}...) 1752 } 1753 1754 go func() { 1755 _, err := s.d.Cmd("run", "-d", "--name", name, "--restart=always", "busybox", "top") 1756 chErr <- err 1757 wg.Done() 1758 }() 1759 } 1760 1761 wg.Wait() 1762 close(chErr) 1763 for err := range chErr { 1764 c.Assert(err, check.IsNil) 1765 } 1766 1767 parent1Args = append([]string{"run", "-d"}, parent1Args...) 1768 parent1Args = append(parent1Args, []string{"--name=parent1", "--restart=always", "busybox", "top"}...) 1769 parent2Args = append([]string{"run", "-d"}, parent2Args...) 1770 parent2Args = append(parent2Args, []string{"--name=parent2", "--restart=always", "busybox", "top"}...) 1771 1772 _, err := s.d.Cmd(parent1Args...) 1773 c.Assert(err, check.IsNil) 1774 _, err = s.d.Cmd(parent2Args...) 1775 c.Assert(err, check.IsNil) 1776 1777 s.d.Stop(c) 1778 // clear the log file -- we don't need any of it but may for the next part 1779 // can ignore the error here, this is just a cleanup 1780 os.Truncate(s.d.LogFileName(), 0) 1781 s.d.Start(c) 1782 1783 for _, num := range []string{"1", "2"} { 1784 out, err := s.d.Cmd("inspect", "-f", "{{ .State.Running }}", "parent"+num) 1785 c.Assert(err, check.IsNil) 1786 if strings.TrimSpace(out) != "true" { 1787 log, _ := ioutil.ReadFile(s.d.LogFileName()) 1788 c.Fatalf("parent container is not running\n%s", string(log)) 1789 } 1790 } 1791 } 1792 1793 func (s *DockerDaemonSuite) TestDaemonCgroupParent(c *check.C) { 1794 testRequires(c, DaemonIsLinux) 1795 1796 cgroupParent := "test" 1797 name := "cgroup-test" 1798 1799 s.d.StartWithBusybox(c, "--cgroup-parent", cgroupParent) 1800 defer s.d.Restart(c) 1801 1802 out, err := s.d.Cmd("run", "--name", name, "busybox", "cat", "/proc/self/cgroup") 1803 c.Assert(err, checker.IsNil) 1804 cgroupPaths := ParseCgroupPaths(string(out)) 1805 c.Assert(len(cgroupPaths), checker.Not(checker.Equals), 0, check.Commentf("unexpected output - %q", string(out))) 1806 out, err = s.d.Cmd("inspect", "-f", "{{.Id}}", name) 1807 c.Assert(err, checker.IsNil) 1808 id := strings.TrimSpace(string(out)) 1809 expectedCgroup := path.Join(cgroupParent, id) 1810 found := false 1811 for _, path := range cgroupPaths { 1812 if strings.HasSuffix(path, expectedCgroup) { 1813 found = true 1814 break 1815 } 1816 } 1817 c.Assert(found, checker.True, check.Commentf("Cgroup path for container (%s) doesn't found in cgroups file: %s", expectedCgroup, cgroupPaths)) 1818 } 1819 1820 func (s *DockerDaemonSuite) TestDaemonRestartWithLinks(c *check.C) { 1821 testRequires(c, DaemonIsLinux) // Windows does not support links 1822 s.d.StartWithBusybox(c) 1823 1824 out, err := s.d.Cmd("run", "-d", "--name=test", "busybox", "top") 1825 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 1826 1827 out, err = s.d.Cmd("run", "--name=test2", "--link", "test:abc", "busybox", "sh", "-c", "ping -c 1 -w 1 abc") 1828 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 1829 1830 s.d.Restart(c) 1831 1832 // should fail since test is not running yet 1833 out, err = s.d.Cmd("start", "test2") 1834 c.Assert(err, check.NotNil, check.Commentf("%s", out)) 1835 1836 out, err = s.d.Cmd("start", "test") 1837 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 1838 out, err = s.d.Cmd("start", "-a", "test2") 1839 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 1840 c.Assert(strings.Contains(out, "1 packets transmitted, 1 packets received"), check.Equals, true, check.Commentf("%s", out)) 1841 } 1842 1843 func (s *DockerDaemonSuite) TestDaemonRestartWithNames(c *check.C) { 1844 testRequires(c, DaemonIsLinux) // Windows does not support links 1845 s.d.StartWithBusybox(c) 1846 1847 out, err := s.d.Cmd("create", "--name=test", "busybox") 1848 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 1849 1850 out, err = s.d.Cmd("run", "-d", "--name=test2", "busybox", "top") 1851 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 1852 test2ID := strings.TrimSpace(out) 1853 1854 out, err = s.d.Cmd("run", "-d", "--name=test3", "--link", "test2:abc", "busybox", "top") 1855 c.Assert(err, check.IsNil) 1856 test3ID := strings.TrimSpace(out) 1857 1858 s.d.Restart(c) 1859 1860 _, err = s.d.Cmd("create", "--name=test", "busybox") 1861 c.Assert(err, check.NotNil, check.Commentf("expected error trying to create container with duplicate name")) 1862 // this one is no longer needed, removing simplifies the remainder of the test 1863 out, err = s.d.Cmd("rm", "-f", "test") 1864 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 1865 1866 out, err = s.d.Cmd("ps", "-a", "--no-trunc") 1867 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 1868 1869 lines := strings.Split(strings.TrimSpace(out), "\n")[1:] 1870 1871 test2validated := false 1872 test3validated := false 1873 for _, line := range lines { 1874 fields := strings.Fields(line) 1875 names := fields[len(fields)-1] 1876 switch fields[0] { 1877 case test2ID: 1878 c.Assert(names, check.Equals, "test2,test3/abc") 1879 test2validated = true 1880 case test3ID: 1881 c.Assert(names, check.Equals, "test3") 1882 test3validated = true 1883 } 1884 } 1885 1886 c.Assert(test2validated, check.Equals, true) 1887 c.Assert(test3validated, check.Equals, true) 1888 } 1889 1890 // TestDaemonRestartWithKilledRunningContainer requires live restore of running containers 1891 func (s *DockerDaemonSuite) TestDaemonRestartWithKilledRunningContainer(t *check.C) { 1892 testRequires(t, DaemonIsLinux) 1893 s.d.StartWithBusybox(t) 1894 1895 cid, err := s.d.Cmd("run", "-d", "--name", "test", "busybox", "top") 1896 defer s.d.Stop(t) 1897 if err != nil { 1898 t.Fatal(cid, err) 1899 } 1900 cid = strings.TrimSpace(cid) 1901 1902 pid, err := s.d.Cmd("inspect", "-f", "{{.State.Pid}}", cid) 1903 t.Assert(err, check.IsNil) 1904 pid = strings.TrimSpace(pid) 1905 1906 // Kill the daemon 1907 if err := s.d.Kill(); err != nil { 1908 t.Fatal(err) 1909 } 1910 1911 // kill the container 1912 icmd.RunCommand(ctrBinary, "--address", containerdSocket, 1913 "--namespace", moby_daemon.ContainersNamespace, "tasks", "kill", cid).Assert(t, icmd.Success) 1914 1915 // Give time to containerd to process the command if we don't 1916 // the exit event might be received after we do the inspect 1917 result := icmd.RunCommand("kill", "-0", pid) 1918 for result.ExitCode == 0 { 1919 time.Sleep(1 * time.Second) 1920 // FIXME(vdemeester) should we check it doesn't error out ? 1921 result = icmd.RunCommand("kill", "-0", pid) 1922 } 1923 1924 // restart the daemon 1925 s.d.Start(t) 1926 1927 // Check that we've got the correct exit code 1928 out, err := s.d.Cmd("inspect", "-f", "{{.State.ExitCode}}", cid) 1929 t.Assert(err, check.IsNil) 1930 1931 out = strings.TrimSpace(out) 1932 if out != "143" { 1933 t.Fatalf("Expected exit code '%s' got '%s' for container '%s'\n", "143", out, cid) 1934 } 1935 1936 } 1937 1938 // os.Kill should kill daemon ungracefully, leaving behind live containers. 1939 // The live containers should be known to the restarted daemon. Stopping 1940 // them now, should remove the mounts. 1941 func (s *DockerDaemonSuite) TestCleanupMountsAfterDaemonCrash(c *check.C) { 1942 testRequires(c, DaemonIsLinux) 1943 s.d.StartWithBusybox(c, "--live-restore") 1944 1945 out, err := s.d.Cmd("run", "-d", "busybox", "top") 1946 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1947 id := strings.TrimSpace(out) 1948 1949 // kill the daemon 1950 c.Assert(s.d.Kill(), check.IsNil) 1951 1952 // Check if there are mounts with container id visible from the host. 1953 // If not, those mounts exist in container's own mount ns, and so 1954 // the following check for mounts being cleared is pointless. 1955 skipMountCheck := false 1956 mountOut, err := ioutil.ReadFile("/proc/self/mountinfo") 1957 c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut)) 1958 if !strings.Contains(string(mountOut), id) { 1959 skipMountCheck = true 1960 } 1961 1962 // restart daemon. 1963 s.d.Start(c, "--live-restore") 1964 1965 // container should be running. 1966 out, err = s.d.Cmd("inspect", "--format={{.State.Running}}", id) 1967 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1968 out = strings.TrimSpace(out) 1969 if out != "true" { 1970 c.Fatalf("Container %s expected to stay alive after daemon restart", id) 1971 } 1972 1973 // 'docker stop' should work. 1974 out, err = s.d.Cmd("stop", id) 1975 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1976 1977 if skipMountCheck { 1978 return 1979 } 1980 // Now, container mounts should be gone. 1981 mountOut, err = ioutil.ReadFile("/proc/self/mountinfo") 1982 c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut)) 1983 comment := check.Commentf("%s is still mounted from older daemon start:\nDaemon root repository %s\n%s", id, s.d.Root, mountOut) 1984 c.Assert(strings.Contains(string(mountOut), id), check.Equals, false, comment) 1985 } 1986 1987 // TestDaemonRestartWithUnpausedRunningContainer requires live restore of running containers. 1988 func (s *DockerDaemonSuite) TestDaemonRestartWithUnpausedRunningContainer(t *check.C) { 1989 testRequires(t, DaemonIsLinux) 1990 s.d.StartWithBusybox(t, "--live-restore") 1991 1992 cid, err := s.d.Cmd("run", "-d", "--name", "test", "busybox", "top") 1993 defer s.d.Stop(t) 1994 if err != nil { 1995 t.Fatal(cid, err) 1996 } 1997 cid = strings.TrimSpace(cid) 1998 1999 pid, err := s.d.Cmd("inspect", "-f", "{{.State.Pid}}", cid) 2000 t.Assert(err, check.IsNil) 2001 2002 // pause the container 2003 if _, err := s.d.Cmd("pause", cid); err != nil { 2004 t.Fatal(cid, err) 2005 } 2006 2007 // Kill the daemon 2008 if err := s.d.Kill(); err != nil { 2009 t.Fatal(err) 2010 } 2011 2012 // resume the container 2013 result := icmd.RunCommand( 2014 ctrBinary, 2015 "--address", containerdSocket, 2016 "--namespace", moby_daemon.ContainersNamespace, 2017 "tasks", "resume", cid) 2018 result.Assert(t, icmd.Success) 2019 2020 // Give time to containerd to process the command if we don't 2021 // the resume event might be received after we do the inspect 2022 waitAndAssert(t, defaultReconciliationTimeout, func(*check.C) (interface{}, check.CommentInterface) { 2023 result := icmd.RunCommand("kill", "-0", strings.TrimSpace(pid)) 2024 return result.ExitCode, nil 2025 }, checker.Equals, 0) 2026 2027 // restart the daemon 2028 s.d.Start(t, "--live-restore") 2029 2030 // Check that we've got the correct status 2031 out, err := s.d.Cmd("inspect", "-f", "{{.State.Status}}", cid) 2032 t.Assert(err, check.IsNil) 2033 2034 out = strings.TrimSpace(out) 2035 if out != "running" { 2036 t.Fatalf("Expected exit code '%s' got '%s' for container '%s'\n", "running", out, cid) 2037 } 2038 if _, err := s.d.Cmd("kill", cid); err != nil { 2039 t.Fatal(err) 2040 } 2041 } 2042 2043 // TestRunLinksChanged checks that creating a new container with the same name does not update links 2044 // this ensures that the old, pre gh#16032 functionality continues on 2045 func (s *DockerDaemonSuite) TestRunLinksChanged(c *check.C) { 2046 testRequires(c, DaemonIsLinux) // Windows does not support links 2047 s.d.StartWithBusybox(c) 2048 2049 out, err := s.d.Cmd("run", "-d", "--name=test", "busybox", "top") 2050 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 2051 2052 out, err = s.d.Cmd("run", "--name=test2", "--link=test:abc", "busybox", "sh", "-c", "ping -c 1 abc") 2053 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 2054 c.Assert(out, checker.Contains, "1 packets transmitted, 1 packets received") 2055 2056 out, err = s.d.Cmd("rm", "-f", "test") 2057 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 2058 2059 out, err = s.d.Cmd("run", "-d", "--name=test", "busybox", "top") 2060 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 2061 out, err = s.d.Cmd("start", "-a", "test2") 2062 c.Assert(err, check.NotNil, check.Commentf("%s", out)) 2063 c.Assert(out, check.Not(checker.Contains), "1 packets transmitted, 1 packets received") 2064 2065 s.d.Restart(c) 2066 out, err = s.d.Cmd("start", "-a", "test2") 2067 c.Assert(err, check.NotNil, check.Commentf("%s", out)) 2068 c.Assert(out, check.Not(checker.Contains), "1 packets transmitted, 1 packets received") 2069 } 2070 2071 func (s *DockerDaemonSuite) TestDaemonStartWithoutColors(c *check.C) { 2072 testRequires(c, DaemonIsLinux) 2073 2074 infoLog := "\x1b[36mINFO\x1b" 2075 2076 b := bytes.NewBuffer(nil) 2077 done := make(chan bool) 2078 2079 p, tty, err := pty.Open() 2080 c.Assert(err, checker.IsNil) 2081 defer func() { 2082 tty.Close() 2083 p.Close() 2084 }() 2085 2086 go func() { 2087 io.Copy(b, p) 2088 done <- true 2089 }() 2090 2091 // Enable coloring explicitly 2092 s.d.StartWithLogFile(tty, "--raw-logs=false") 2093 s.d.Stop(c) 2094 // Wait for io.Copy() before checking output 2095 <-done 2096 c.Assert(b.String(), checker.Contains, infoLog) 2097 2098 b.Reset() 2099 2100 // "tty" is already closed in prev s.d.Stop(), 2101 // we have to close the other side "p" and open another pair of 2102 // pty for the next test. 2103 p.Close() 2104 p, tty, err = pty.Open() 2105 c.Assert(err, checker.IsNil) 2106 2107 go func() { 2108 io.Copy(b, p) 2109 done <- true 2110 }() 2111 2112 // Disable coloring explicitly 2113 s.d.StartWithLogFile(tty, "--raw-logs=true") 2114 s.d.Stop(c) 2115 // Wait for io.Copy() before checking output 2116 <-done 2117 c.Assert(b.String(), check.Not(check.Equals), "") 2118 c.Assert(b.String(), check.Not(checker.Contains), infoLog) 2119 } 2120 2121 func (s *DockerDaemonSuite) TestDaemonDebugLog(c *check.C) { 2122 testRequires(c, DaemonIsLinux) 2123 2124 debugLog := "\x1b[37mDEBU\x1b" 2125 2126 p, tty, err := pty.Open() 2127 c.Assert(err, checker.IsNil) 2128 defer func() { 2129 tty.Close() 2130 p.Close() 2131 }() 2132 2133 b := bytes.NewBuffer(nil) 2134 go io.Copy(b, p) 2135 2136 s.d.StartWithLogFile(tty, "--debug") 2137 s.d.Stop(c) 2138 c.Assert(b.String(), checker.Contains, debugLog) 2139 } 2140 2141 func (s *DockerDaemonSuite) TestDaemonDiscoveryBackendConfigReload(c *check.C) { 2142 testRequires(c, testEnv.IsLocalDaemon, DaemonIsLinux) 2143 2144 // daemon config file 2145 daemonConfig := `{ "debug" : false }` 2146 configFile, err := ioutil.TempFile("", "test-daemon-discovery-backend-config-reload-config") 2147 c.Assert(err, checker.IsNil, check.Commentf("could not create temp file for config reload")) 2148 configFilePath := configFile.Name() 2149 defer func() { 2150 configFile.Close() 2151 os.RemoveAll(configFile.Name()) 2152 }() 2153 2154 _, err = configFile.Write([]byte(daemonConfig)) 2155 c.Assert(err, checker.IsNil) 2156 2157 // --log-level needs to be set so that d.Start() doesn't add --debug causing 2158 // a conflict with the config 2159 s.d.Start(c, "--config-file", configFilePath, "--log-level=info") 2160 2161 // daemon config file 2162 daemonConfig = `{ 2163 "cluster-store": "consul://consuladdr:consulport/some/path", 2164 "cluster-advertise": "192.168.56.100:0", 2165 "debug" : false 2166 }` 2167 2168 err = configFile.Truncate(0) 2169 c.Assert(err, checker.IsNil) 2170 _, err = configFile.Seek(0, os.SEEK_SET) 2171 c.Assert(err, checker.IsNil) 2172 2173 _, err = configFile.Write([]byte(daemonConfig)) 2174 c.Assert(err, checker.IsNil) 2175 2176 err = s.d.ReloadConfig() 2177 c.Assert(err, checker.IsNil, check.Commentf("error reloading daemon config")) 2178 2179 out, err := s.d.Cmd("info") 2180 c.Assert(err, checker.IsNil) 2181 2182 c.Assert(out, checker.Contains, fmt.Sprintf("Cluster Store: consul://consuladdr:consulport/some/path")) 2183 c.Assert(out, checker.Contains, fmt.Sprintf("Cluster Advertise: 192.168.56.100:0")) 2184 } 2185 2186 // Test for #21956 2187 func (s *DockerDaemonSuite) TestDaemonLogOptions(c *check.C) { 2188 s.d.StartWithBusybox(c, "--log-driver=syslog", "--log-opt=syslog-address=udp://127.0.0.1:514") 2189 2190 out, err := s.d.Cmd("run", "-d", "--log-driver=json-file", "busybox", "top") 2191 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 2192 id := strings.TrimSpace(out) 2193 2194 out, err = s.d.Cmd("inspect", "--format='{{.HostConfig.LogConfig}}'", id) 2195 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 2196 c.Assert(out, checker.Contains, "{json-file map[]}") 2197 } 2198 2199 // Test case for #20936, #22443 2200 func (s *DockerDaemonSuite) TestDaemonMaxConcurrency(c *check.C) { 2201 s.d.Start(c, "--max-concurrent-uploads=6", "--max-concurrent-downloads=8") 2202 2203 expectedMaxConcurrentUploads := `level=debug msg="Max Concurrent Uploads: 6"` 2204 expectedMaxConcurrentDownloads := `level=debug msg="Max Concurrent Downloads: 8"` 2205 content, err := s.d.ReadLogFile() 2206 c.Assert(err, checker.IsNil) 2207 c.Assert(string(content), checker.Contains, expectedMaxConcurrentUploads) 2208 c.Assert(string(content), checker.Contains, expectedMaxConcurrentDownloads) 2209 } 2210 2211 // Test case for #20936, #22443 2212 func (s *DockerDaemonSuite) TestDaemonMaxConcurrencyWithConfigFile(c *check.C) { 2213 testRequires(c, testEnv.IsLocalDaemon, DaemonIsLinux) 2214 2215 // daemon config file 2216 configFilePath := "test.json" 2217 configFile, err := os.Create(configFilePath) 2218 c.Assert(err, checker.IsNil) 2219 defer os.Remove(configFilePath) 2220 2221 daemonConfig := `{ "max-concurrent-downloads" : 8 }` 2222 fmt.Fprintf(configFile, "%s", daemonConfig) 2223 configFile.Close() 2224 s.d.Start(c, fmt.Sprintf("--config-file=%s", configFilePath)) 2225 2226 expectedMaxConcurrentUploads := `level=debug msg="Max Concurrent Uploads: 5"` 2227 expectedMaxConcurrentDownloads := `level=debug msg="Max Concurrent Downloads: 8"` 2228 content, err := s.d.ReadLogFile() 2229 c.Assert(err, checker.IsNil) 2230 c.Assert(string(content), checker.Contains, expectedMaxConcurrentUploads) 2231 c.Assert(string(content), checker.Contains, expectedMaxConcurrentDownloads) 2232 2233 configFile, err = os.Create(configFilePath) 2234 c.Assert(err, checker.IsNil) 2235 daemonConfig = `{ "max-concurrent-uploads" : 7, "max-concurrent-downloads" : 9 }` 2236 fmt.Fprintf(configFile, "%s", daemonConfig) 2237 configFile.Close() 2238 2239 c.Assert(s.d.Signal(unix.SIGHUP), checker.IsNil) 2240 // unix.Kill(s.d.cmd.Process.Pid, unix.SIGHUP) 2241 2242 time.Sleep(3 * time.Second) 2243 2244 expectedMaxConcurrentUploads = `level=debug msg="Reset Max Concurrent Uploads: 7"` 2245 expectedMaxConcurrentDownloads = `level=debug msg="Reset Max Concurrent Downloads: 9"` 2246 content, err = s.d.ReadLogFile() 2247 c.Assert(err, checker.IsNil) 2248 c.Assert(string(content), checker.Contains, expectedMaxConcurrentUploads) 2249 c.Assert(string(content), checker.Contains, expectedMaxConcurrentDownloads) 2250 } 2251 2252 // Test case for #20936, #22443 2253 func (s *DockerDaemonSuite) TestDaemonMaxConcurrencyWithConfigFileReload(c *check.C) { 2254 testRequires(c, testEnv.IsLocalDaemon, DaemonIsLinux) 2255 2256 // daemon config file 2257 configFilePath := "test.json" 2258 configFile, err := os.Create(configFilePath) 2259 c.Assert(err, checker.IsNil) 2260 defer os.Remove(configFilePath) 2261 2262 daemonConfig := `{ "max-concurrent-uploads" : null }` 2263 fmt.Fprintf(configFile, "%s", daemonConfig) 2264 configFile.Close() 2265 s.d.Start(c, fmt.Sprintf("--config-file=%s", configFilePath)) 2266 2267 expectedMaxConcurrentUploads := `level=debug msg="Max Concurrent Uploads: 5"` 2268 expectedMaxConcurrentDownloads := `level=debug msg="Max Concurrent Downloads: 3"` 2269 content, err := s.d.ReadLogFile() 2270 c.Assert(err, checker.IsNil) 2271 c.Assert(string(content), checker.Contains, expectedMaxConcurrentUploads) 2272 c.Assert(string(content), checker.Contains, expectedMaxConcurrentDownloads) 2273 2274 configFile, err = os.Create(configFilePath) 2275 c.Assert(err, checker.IsNil) 2276 daemonConfig = `{ "max-concurrent-uploads" : 1, "max-concurrent-downloads" : null }` 2277 fmt.Fprintf(configFile, "%s", daemonConfig) 2278 configFile.Close() 2279 2280 c.Assert(s.d.Signal(unix.SIGHUP), checker.IsNil) 2281 // unix.Kill(s.d.cmd.Process.Pid, unix.SIGHUP) 2282 2283 time.Sleep(3 * time.Second) 2284 2285 expectedMaxConcurrentUploads = `level=debug msg="Reset Max Concurrent Uploads: 1"` 2286 expectedMaxConcurrentDownloads = `level=debug msg="Reset Max Concurrent Downloads: 3"` 2287 content, err = s.d.ReadLogFile() 2288 c.Assert(err, checker.IsNil) 2289 c.Assert(string(content), checker.Contains, expectedMaxConcurrentUploads) 2290 c.Assert(string(content), checker.Contains, expectedMaxConcurrentDownloads) 2291 2292 configFile, err = os.Create(configFilePath) 2293 c.Assert(err, checker.IsNil) 2294 daemonConfig = `{ "labels":["foo=bar"] }` 2295 fmt.Fprintf(configFile, "%s", daemonConfig) 2296 configFile.Close() 2297 2298 c.Assert(s.d.Signal(unix.SIGHUP), checker.IsNil) 2299 2300 time.Sleep(3 * time.Second) 2301 2302 expectedMaxConcurrentUploads = `level=debug msg="Reset Max Concurrent Uploads: 5"` 2303 expectedMaxConcurrentDownloads = `level=debug msg="Reset Max Concurrent Downloads: 3"` 2304 content, err = s.d.ReadLogFile() 2305 c.Assert(err, checker.IsNil) 2306 c.Assert(string(content), checker.Contains, expectedMaxConcurrentUploads) 2307 c.Assert(string(content), checker.Contains, expectedMaxConcurrentDownloads) 2308 } 2309 2310 func (s *DockerDaemonSuite) TestBuildOnDisabledBridgeNetworkDaemon(c *check.C) { 2311 s.d.StartWithBusybox(c, "-b=none", "--iptables=false") 2312 2313 result := cli.BuildCmd(c, "busyboxs", cli.Daemon(s.d), 2314 build.WithDockerfile(` 2315 FROM busybox 2316 RUN cat /etc/hosts`), 2317 build.WithoutCache, 2318 ) 2319 comment := check.Commentf("Failed to build image. output %s, exitCode %d, err %v", result.Combined(), result.ExitCode, result.Error) 2320 c.Assert(result.Error, check.IsNil, comment) 2321 c.Assert(result.ExitCode, check.Equals, 0, comment) 2322 } 2323 2324 // Test case for #21976 2325 func (s *DockerDaemonSuite) TestDaemonDNSFlagsInHostMode(c *check.C) { 2326 testRequires(c, testEnv.IsLocalDaemon, DaemonIsLinux) 2327 2328 s.d.StartWithBusybox(c, "--dns", "1.2.3.4", "--dns-search", "example.com", "--dns-opt", "timeout:3") 2329 2330 expectedOutput := "nameserver 1.2.3.4" 2331 out, _ := s.d.Cmd("run", "--net=host", "busybox", "cat", "/etc/resolv.conf") 2332 c.Assert(out, checker.Contains, expectedOutput, check.Commentf("Expected '%s', but got %q", expectedOutput, out)) 2333 expectedOutput = "search example.com" 2334 c.Assert(out, checker.Contains, expectedOutput, check.Commentf("Expected '%s', but got %q", expectedOutput, out)) 2335 expectedOutput = "options timeout:3" 2336 c.Assert(out, checker.Contains, expectedOutput, check.Commentf("Expected '%s', but got %q", expectedOutput, out)) 2337 } 2338 2339 func (s *DockerDaemonSuite) TestRunWithRuntimeFromConfigFile(c *check.C) { 2340 conf, err := ioutil.TempFile("", "config-file-") 2341 c.Assert(err, check.IsNil) 2342 configName := conf.Name() 2343 conf.Close() 2344 defer os.Remove(configName) 2345 2346 config := ` 2347 { 2348 "runtimes": { 2349 "oci": { 2350 "path": "runc" 2351 }, 2352 "vm": { 2353 "path": "/usr/local/bin/vm-manager", 2354 "runtimeArgs": [ 2355 "--debug" 2356 ] 2357 } 2358 } 2359 } 2360 ` 2361 ioutil.WriteFile(configName, []byte(config), 0644) 2362 s.d.StartWithBusybox(c, "--config-file", configName) 2363 2364 // Run with default runtime 2365 out, err := s.d.Cmd("run", "--rm", "busybox", "ls") 2366 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 2367 2368 // Run with default runtime explicitly 2369 out, err = s.d.Cmd("run", "--rm", "--runtime=runc", "busybox", "ls") 2370 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 2371 2372 // Run with oci (same path as default) but keep it around 2373 out, err = s.d.Cmd("run", "--name", "oci-runtime-ls", "--runtime=oci", "busybox", "ls") 2374 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 2375 2376 // Run with "vm" 2377 out, err = s.d.Cmd("run", "--rm", "--runtime=vm", "busybox", "ls") 2378 c.Assert(err, check.NotNil, check.Commentf("%s", out)) 2379 c.Assert(out, checker.Contains, "/usr/local/bin/vm-manager: no such file or directory") 2380 2381 // Reset config to only have the default 2382 config = ` 2383 { 2384 "runtimes": { 2385 } 2386 } 2387 ` 2388 ioutil.WriteFile(configName, []byte(config), 0644) 2389 c.Assert(s.d.Signal(unix.SIGHUP), checker.IsNil) 2390 // Give daemon time to reload config 2391 <-time.After(1 * time.Second) 2392 2393 // Run with default runtime 2394 out, err = s.d.Cmd("run", "--rm", "--runtime=runc", "busybox", "ls") 2395 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 2396 2397 // Run with "oci" 2398 out, err = s.d.Cmd("run", "--rm", "--runtime=oci", "busybox", "ls") 2399 c.Assert(err, check.NotNil, check.Commentf("%s", out)) 2400 c.Assert(out, checker.Contains, "Unknown runtime specified oci") 2401 2402 // Start previously created container with oci 2403 out, err = s.d.Cmd("start", "oci-runtime-ls") 2404 c.Assert(err, check.NotNil, check.Commentf("%s", out)) 2405 c.Assert(out, checker.Contains, "Unknown runtime specified oci") 2406 2407 // Check that we can't override the default runtime 2408 config = ` 2409 { 2410 "runtimes": { 2411 "runc": { 2412 "path": "my-runc" 2413 } 2414 } 2415 } 2416 ` 2417 ioutil.WriteFile(configName, []byte(config), 0644) 2418 c.Assert(s.d.Signal(unix.SIGHUP), checker.IsNil) 2419 // Give daemon time to reload config 2420 <-time.After(1 * time.Second) 2421 2422 content, err := s.d.ReadLogFile() 2423 c.Assert(err, checker.IsNil) 2424 c.Assert(string(content), checker.Contains, `file configuration validation failed: runtime name 'runc' is reserved`) 2425 2426 // Check that we can select a default runtime 2427 config = ` 2428 { 2429 "default-runtime": "vm", 2430 "runtimes": { 2431 "oci": { 2432 "path": "runc" 2433 }, 2434 "vm": { 2435 "path": "/usr/local/bin/vm-manager", 2436 "runtimeArgs": [ 2437 "--debug" 2438 ] 2439 } 2440 } 2441 } 2442 ` 2443 ioutil.WriteFile(configName, []byte(config), 0644) 2444 c.Assert(s.d.Signal(unix.SIGHUP), checker.IsNil) 2445 // Give daemon time to reload config 2446 <-time.After(1 * time.Second) 2447 2448 out, err = s.d.Cmd("run", "--rm", "busybox", "ls") 2449 c.Assert(err, check.NotNil, check.Commentf("%s", out)) 2450 c.Assert(out, checker.Contains, "/usr/local/bin/vm-manager: no such file or directory") 2451 2452 // Run with default runtime explicitly 2453 out, err = s.d.Cmd("run", "--rm", "--runtime=runc", "busybox", "ls") 2454 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 2455 } 2456 2457 func (s *DockerDaemonSuite) TestRunWithRuntimeFromCommandLine(c *check.C) { 2458 s.d.StartWithBusybox(c, "--add-runtime", "oci=runc", "--add-runtime", "vm=/usr/local/bin/vm-manager") 2459 2460 // Run with default runtime 2461 out, err := s.d.Cmd("run", "--rm", "busybox", "ls") 2462 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 2463 2464 // Run with default runtime explicitly 2465 out, err = s.d.Cmd("run", "--rm", "--runtime=runc", "busybox", "ls") 2466 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 2467 2468 // Run with oci (same path as default) but keep it around 2469 out, err = s.d.Cmd("run", "--name", "oci-runtime-ls", "--runtime=oci", "busybox", "ls") 2470 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 2471 2472 // Run with "vm" 2473 out, err = s.d.Cmd("run", "--rm", "--runtime=vm", "busybox", "ls") 2474 c.Assert(err, check.NotNil, check.Commentf("%s", out)) 2475 c.Assert(out, checker.Contains, "/usr/local/bin/vm-manager: no such file or directory") 2476 2477 // Start a daemon without any extra runtimes 2478 s.d.Stop(c) 2479 s.d.StartWithBusybox(c) 2480 2481 // Run with default runtime 2482 out, err = s.d.Cmd("run", "--rm", "--runtime=runc", "busybox", "ls") 2483 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 2484 2485 // Run with "oci" 2486 out, err = s.d.Cmd("run", "--rm", "--runtime=oci", "busybox", "ls") 2487 c.Assert(err, check.NotNil, check.Commentf("%s", out)) 2488 c.Assert(out, checker.Contains, "Unknown runtime specified oci") 2489 2490 // Start previously created container with oci 2491 out, err = s.d.Cmd("start", "oci-runtime-ls") 2492 c.Assert(err, check.NotNil, check.Commentf("%s", out)) 2493 c.Assert(out, checker.Contains, "Unknown runtime specified oci") 2494 2495 // Check that we can't override the default runtime 2496 s.d.Stop(c) 2497 c.Assert(s.d.StartWithError("--add-runtime", "runc=my-runc"), checker.NotNil) 2498 2499 content, err := s.d.ReadLogFile() 2500 c.Assert(err, checker.IsNil) 2501 c.Assert(string(content), checker.Contains, `runtime name 'runc' is reserved`) 2502 2503 // Check that we can select a default runtime 2504 s.d.Stop(c) 2505 s.d.StartWithBusybox(c, "--default-runtime=vm", "--add-runtime", "oci=runc", "--add-runtime", "vm=/usr/local/bin/vm-manager") 2506 2507 out, err = s.d.Cmd("run", "--rm", "busybox", "ls") 2508 c.Assert(err, check.NotNil, check.Commentf("%s", out)) 2509 c.Assert(out, checker.Contains, "/usr/local/bin/vm-manager: no such file or directory") 2510 2511 // Run with default runtime explicitly 2512 out, err = s.d.Cmd("run", "--rm", "--runtime=runc", "busybox", "ls") 2513 c.Assert(err, check.IsNil, check.Commentf("%s", out)) 2514 } 2515 2516 func (s *DockerDaemonSuite) TestDaemonRestartWithAutoRemoveContainer(c *check.C) { 2517 s.d.StartWithBusybox(c) 2518 2519 // top1 will exist after daemon restarts 2520 out, err := s.d.Cmd("run", "-d", "--name", "top1", "busybox:latest", "top") 2521 c.Assert(err, checker.IsNil, check.Commentf("run top1: %v", out)) 2522 // top2 will be removed after daemon restarts 2523 out, err = s.d.Cmd("run", "-d", "--rm", "--name", "top2", "busybox:latest", "top") 2524 c.Assert(err, checker.IsNil, check.Commentf("run top2: %v", out)) 2525 2526 out, err = s.d.Cmd("ps") 2527 c.Assert(err, checker.IsNil) 2528 c.Assert(out, checker.Contains, "top1", check.Commentf("top1 should be running")) 2529 c.Assert(out, checker.Contains, "top2", check.Commentf("top2 should be running")) 2530 2531 // now restart daemon gracefully 2532 s.d.Restart(c) 2533 2534 out, err = s.d.Cmd("ps", "-a") 2535 c.Assert(err, checker.IsNil, check.Commentf("out: %v", out)) 2536 c.Assert(out, checker.Contains, "top1", check.Commentf("top1 should exist after daemon restarts")) 2537 c.Assert(out, checker.Not(checker.Contains), "top2", check.Commentf("top2 should be removed after daemon restarts")) 2538 } 2539 2540 func (s *DockerDaemonSuite) TestDaemonRestartSaveContainerExitCode(c *check.C) { 2541 s.d.StartWithBusybox(c) 2542 2543 containerName := "error-values" 2544 // Make a container with both a non 0 exit code and an error message 2545 // We explicitly disable `--init` for this test, because `--init` is enabled by default 2546 // on "experimental". Enabling `--init` results in a different behavior; because the "init" 2547 // process itself is PID1, the container does not fail on _startup_ (i.e., `docker-init` starting), 2548 // but directly after. The exit code of the container is still 127, but the Error Message is not 2549 // captured, so `.State.Error` is empty. 2550 // See the discussion on https://github.com/docker/docker/pull/30227#issuecomment-274161426, 2551 // and https://github.com/docker/docker/pull/26061#r78054578 for more information. 2552 _, err := s.d.Cmd("run", "--name", containerName, "--init=false", "busybox", "toto") 2553 c.Assert(err, checker.NotNil) 2554 2555 // Check that those values were saved on disk 2556 out, err := s.d.Cmd("inspect", "-f", "{{.State.ExitCode}}", containerName) 2557 out = strings.TrimSpace(out) 2558 c.Assert(err, checker.IsNil) 2559 c.Assert(out, checker.Equals, "127") 2560 2561 errMsg1, err := s.d.Cmd("inspect", "-f", "{{.State.Error}}", containerName) 2562 errMsg1 = strings.TrimSpace(errMsg1) 2563 c.Assert(err, checker.IsNil) 2564 c.Assert(errMsg1, checker.Contains, "executable file not found") 2565 2566 // now restart daemon 2567 s.d.Restart(c) 2568 2569 // Check that those values are still around 2570 out, err = s.d.Cmd("inspect", "-f", "{{.State.ExitCode}}", containerName) 2571 out = strings.TrimSpace(out) 2572 c.Assert(err, checker.IsNil) 2573 c.Assert(out, checker.Equals, "127") 2574 2575 out, err = s.d.Cmd("inspect", "-f", "{{.State.Error}}", containerName) 2576 out = strings.TrimSpace(out) 2577 c.Assert(err, checker.IsNil) 2578 c.Assert(out, checker.Equals, errMsg1) 2579 } 2580 2581 func (s *DockerDaemonSuite) TestDaemonWithUserlandProxyPath(c *check.C) { 2582 testRequires(c, testEnv.IsLocalDaemon, DaemonIsLinux) 2583 2584 dockerProxyPath, err := exec.LookPath("docker-proxy") 2585 c.Assert(err, checker.IsNil) 2586 tmpDir, err := ioutil.TempDir("", "test-docker-proxy") 2587 c.Assert(err, checker.IsNil) 2588 2589 newProxyPath := filepath.Join(tmpDir, "docker-proxy") 2590 cmd := exec.Command("cp", dockerProxyPath, newProxyPath) 2591 c.Assert(cmd.Run(), checker.IsNil) 2592 2593 // custom one 2594 s.d.StartWithBusybox(c, "--userland-proxy-path", newProxyPath) 2595 out, err := s.d.Cmd("run", "-p", "5000:5000", "busybox:latest", "true") 2596 c.Assert(err, checker.IsNil, check.Commentf("%s", out)) 2597 2598 // try with the original one 2599 s.d.Restart(c, "--userland-proxy-path", dockerProxyPath) 2600 out, err = s.d.Cmd("run", "-p", "5000:5000", "busybox:latest", "true") 2601 c.Assert(err, checker.IsNil, check.Commentf("%s", out)) 2602 2603 // not exist 2604 s.d.Restart(c, "--userland-proxy-path", "/does/not/exist") 2605 out, err = s.d.Cmd("run", "-p", "5000:5000", "busybox:latest", "true") 2606 c.Assert(err, checker.NotNil, check.Commentf("%s", out)) 2607 c.Assert(out, checker.Contains, "driver failed programming external connectivity on endpoint") 2608 c.Assert(out, checker.Contains, "/does/not/exist: no such file or directory") 2609 } 2610 2611 // Test case for #22471 2612 func (s *DockerDaemonSuite) TestDaemonShutdownTimeout(c *check.C) { 2613 testRequires(c, testEnv.IsLocalDaemon) 2614 s.d.StartWithBusybox(c, "--shutdown-timeout=3") 2615 2616 _, err := s.d.Cmd("run", "-d", "busybox", "top") 2617 c.Assert(err, check.IsNil) 2618 2619 c.Assert(s.d.Signal(unix.SIGINT), checker.IsNil) 2620 2621 select { 2622 case <-s.d.Wait: 2623 case <-time.After(5 * time.Second): 2624 } 2625 2626 expectedMessage := `level=debug msg="daemon configured with a 3 seconds minimum shutdown timeout"` 2627 content, err := s.d.ReadLogFile() 2628 c.Assert(err, checker.IsNil) 2629 c.Assert(string(content), checker.Contains, expectedMessage) 2630 } 2631 2632 // Test case for #22471 2633 func (s *DockerDaemonSuite) TestDaemonShutdownTimeoutWithConfigFile(c *check.C) { 2634 testRequires(c, testEnv.IsLocalDaemon) 2635 2636 // daemon config file 2637 configFilePath := "test.json" 2638 configFile, err := os.Create(configFilePath) 2639 c.Assert(err, checker.IsNil) 2640 defer os.Remove(configFilePath) 2641 2642 daemonConfig := `{ "shutdown-timeout" : 8 }` 2643 fmt.Fprintf(configFile, "%s", daemonConfig) 2644 configFile.Close() 2645 s.d.Start(c, fmt.Sprintf("--config-file=%s", configFilePath)) 2646 2647 configFile, err = os.Create(configFilePath) 2648 c.Assert(err, checker.IsNil) 2649 daemonConfig = `{ "shutdown-timeout" : 5 }` 2650 fmt.Fprintf(configFile, "%s", daemonConfig) 2651 configFile.Close() 2652 2653 c.Assert(s.d.Signal(unix.SIGHUP), checker.IsNil) 2654 2655 select { 2656 case <-s.d.Wait: 2657 case <-time.After(3 * time.Second): 2658 } 2659 2660 expectedMessage := `level=debug msg="Reset Shutdown Timeout: 5"` 2661 content, err := s.d.ReadLogFile() 2662 c.Assert(err, checker.IsNil) 2663 c.Assert(string(content), checker.Contains, expectedMessage) 2664 } 2665 2666 // Test case for 29342 2667 func (s *DockerDaemonSuite) TestExecWithUserAfterLiveRestore(c *check.C) { 2668 testRequires(c, DaemonIsLinux) 2669 s.d.StartWithBusybox(c, "--live-restore") 2670 2671 out, err := s.d.Cmd("run", "-d", "--name=top", "busybox", "sh", "-c", "addgroup -S test && adduser -S -G test test -D -s /bin/sh && touch /adduser_end && top") 2672 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 2673 2674 s.d.WaitRun("top") 2675 2676 // Wait for shell command to be completed 2677 _, err = s.d.Cmd("exec", "top", "sh", "-c", `for i in $(seq 1 5); do if [ -e /adduser_end ]; then rm -f /adduser_end && break; else sleep 1 && false; fi; done`) 2678 c.Assert(err, check.IsNil, check.Commentf("Timeout waiting for shell command to be completed")) 2679 2680 out1, err := s.d.Cmd("exec", "-u", "test", "top", "id") 2681 // uid=100(test) gid=101(test) groups=101(test) 2682 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out1)) 2683 2684 // restart daemon. 2685 s.d.Restart(c, "--live-restore") 2686 2687 out2, err := s.d.Cmd("exec", "-u", "test", "top", "id") 2688 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out2)) 2689 c.Assert(out2, check.Equals, out1, check.Commentf("Output: before restart '%s', after restart '%s'", out1, out2)) 2690 2691 out, err = s.d.Cmd("stop", "top") 2692 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 2693 } 2694 2695 func (s *DockerDaemonSuite) TestRemoveContainerAfterLiveRestore(c *check.C) { 2696 testRequires(c, DaemonIsLinux, overlayFSSupported, testEnv.IsLocalDaemon) 2697 s.d.StartWithBusybox(c, "--live-restore", "--storage-driver", "overlay") 2698 out, err := s.d.Cmd("run", "-d", "--name=top", "busybox", "top") 2699 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 2700 2701 s.d.WaitRun("top") 2702 2703 // restart daemon. 2704 s.d.Restart(c, "--live-restore", "--storage-driver", "overlay") 2705 2706 out, err = s.d.Cmd("stop", "top") 2707 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 2708 2709 // test if the rootfs mountpoint still exist 2710 mountpoint, err := s.d.InspectField("top", ".GraphDriver.Data.MergedDir") 2711 c.Assert(err, check.IsNil) 2712 f, err := os.Open("/proc/self/mountinfo") 2713 c.Assert(err, check.IsNil) 2714 defer f.Close() 2715 sc := bufio.NewScanner(f) 2716 for sc.Scan() { 2717 line := sc.Text() 2718 if strings.Contains(line, mountpoint) { 2719 c.Fatalf("mountinfo should not include the mountpoint of stop container") 2720 } 2721 } 2722 2723 out, err = s.d.Cmd("rm", "top") 2724 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 2725 } 2726 2727 // #29598 2728 func (s *DockerDaemonSuite) TestRestartPolicyWithLiveRestore(c *check.C) { 2729 testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) 2730 s.d.StartWithBusybox(c, "--live-restore") 2731 2732 out, err := s.d.Cmd("run", "-d", "--restart", "always", "busybox", "top") 2733 c.Assert(err, check.IsNil, check.Commentf("output: %s", out)) 2734 id := strings.TrimSpace(out) 2735 2736 type state struct { 2737 Running bool 2738 StartedAt time.Time 2739 } 2740 out, err = s.d.Cmd("inspect", "-f", "{{json .State}}", id) 2741 c.Assert(err, checker.IsNil, check.Commentf("output: %s", out)) 2742 2743 var origState state 2744 err = json.Unmarshal([]byte(strings.TrimSpace(out)), &origState) 2745 c.Assert(err, checker.IsNil) 2746 2747 s.d.Restart(c, "--live-restore") 2748 2749 pid, err := s.d.Cmd("inspect", "-f", "{{.State.Pid}}", id) 2750 c.Assert(err, check.IsNil) 2751 pidint, err := strconv.Atoi(strings.TrimSpace(pid)) 2752 c.Assert(err, check.IsNil) 2753 c.Assert(pidint, checker.GreaterThan, 0) 2754 c.Assert(unix.Kill(pidint, unix.SIGKILL), check.IsNil) 2755 2756 ticker := time.NewTicker(50 * time.Millisecond) 2757 timeout := time.After(10 * time.Second) 2758 2759 for range ticker.C { 2760 select { 2761 case <-timeout: 2762 c.Fatal("timeout waiting for container restart") 2763 default: 2764 } 2765 2766 out, err := s.d.Cmd("inspect", "-f", "{{json .State}}", id) 2767 c.Assert(err, checker.IsNil, check.Commentf("output: %s", out)) 2768 2769 var newState state 2770 err = json.Unmarshal([]byte(strings.TrimSpace(out)), &newState) 2771 c.Assert(err, checker.IsNil) 2772 2773 if !newState.Running { 2774 continue 2775 } 2776 if newState.StartedAt.After(origState.StartedAt) { 2777 break 2778 } 2779 } 2780 2781 out, err = s.d.Cmd("stop", id) 2782 c.Assert(err, check.IsNil, check.Commentf("output: %s", out)) 2783 } 2784 2785 func (s *DockerDaemonSuite) TestShmSize(c *check.C) { 2786 testRequires(c, DaemonIsLinux) 2787 2788 size := 67108864 * 2 2789 pattern := regexp.MustCompile(fmt.Sprintf("shm on /dev/shm type tmpfs(.*)size=%dk", size/1024)) 2790 2791 s.d.StartWithBusybox(c, "--default-shm-size", fmt.Sprintf("%v", size)) 2792 2793 name := "shm1" 2794 out, err := s.d.Cmd("run", "--name", name, "busybox", "mount") 2795 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 2796 c.Assert(pattern.MatchString(out), checker.True) 2797 out, err = s.d.Cmd("inspect", "--format", "{{.HostConfig.ShmSize}}", name) 2798 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 2799 c.Assert(strings.TrimSpace(out), check.Equals, fmt.Sprintf("%v", size)) 2800 } 2801 2802 func (s *DockerDaemonSuite) TestShmSizeReload(c *check.C) { 2803 testRequires(c, DaemonIsLinux) 2804 2805 configPath, err := ioutil.TempDir("", "test-daemon-shm-size-reload-config") 2806 c.Assert(err, checker.IsNil, check.Commentf("could not create temp file for config reload")) 2807 defer os.RemoveAll(configPath) // clean up 2808 configFile := filepath.Join(configPath, "config.json") 2809 2810 size := 67108864 * 2 2811 configData := []byte(fmt.Sprintf(`{"default-shm-size": "%dM"}`, size/1024/1024)) 2812 c.Assert(ioutil.WriteFile(configFile, configData, 0666), checker.IsNil, check.Commentf("could not write temp file for config reload")) 2813 pattern := regexp.MustCompile(fmt.Sprintf("shm on /dev/shm type tmpfs(.*)size=%dk", size/1024)) 2814 2815 s.d.StartWithBusybox(c, "--config-file", configFile) 2816 2817 name := "shm1" 2818 out, err := s.d.Cmd("run", "--name", name, "busybox", "mount") 2819 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 2820 c.Assert(pattern.MatchString(out), checker.True) 2821 out, err = s.d.Cmd("inspect", "--format", "{{.HostConfig.ShmSize}}", name) 2822 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 2823 c.Assert(strings.TrimSpace(out), check.Equals, fmt.Sprintf("%v", size)) 2824 2825 size = 67108864 * 3 2826 configData = []byte(fmt.Sprintf(`{"default-shm-size": "%dM"}`, size/1024/1024)) 2827 c.Assert(ioutil.WriteFile(configFile, configData, 0666), checker.IsNil, check.Commentf("could not write temp file for config reload")) 2828 pattern = regexp.MustCompile(fmt.Sprintf("shm on /dev/shm type tmpfs(.*)size=%dk", size/1024)) 2829 2830 err = s.d.ReloadConfig() 2831 c.Assert(err, checker.IsNil, check.Commentf("error reloading daemon config")) 2832 2833 name = "shm2" 2834 out, err = s.d.Cmd("run", "--name", name, "busybox", "mount") 2835 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 2836 c.Assert(pattern.MatchString(out), checker.True) 2837 out, err = s.d.Cmd("inspect", "--format", "{{.HostConfig.ShmSize}}", name) 2838 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 2839 c.Assert(strings.TrimSpace(out), check.Equals, fmt.Sprintf("%v", size)) 2840 } 2841 2842 func testDaemonStartIpcMode(c *check.C, from, mode string, valid bool) { 2843 d := daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) 2844 c.Logf("Checking IpcMode %s set from %s\n", mode, from) 2845 var serr error 2846 switch from { 2847 case "config": 2848 f, err := ioutil.TempFile("", "test-daemon-ipc-config") 2849 c.Assert(err, checker.IsNil) 2850 defer os.Remove(f.Name()) 2851 config := `{"default-ipc-mode": "` + mode + `"}` 2852 _, err = f.WriteString(config) 2853 c.Assert(f.Close(), checker.IsNil) 2854 c.Assert(err, checker.IsNil) 2855 2856 serr = d.StartWithError("--config-file", f.Name()) 2857 case "cli": 2858 serr = d.StartWithError("--default-ipc-mode", mode) 2859 default: 2860 c.Fatalf("testDaemonStartIpcMode: invalid 'from' argument") 2861 } 2862 if serr == nil { 2863 d.Stop(c) 2864 } 2865 2866 if valid { 2867 c.Assert(serr, check.IsNil) 2868 } else { 2869 c.Assert(serr, check.NotNil) 2870 icmd.RunCommand("grep", "-E", "IPC .* is (invalid|not supported)", d.LogFileName()).Assert(c, icmd.Success) 2871 } 2872 } 2873 2874 // TestDaemonStartWithIpcModes checks that daemon starts fine given correct 2875 // arguments for default IPC mode, and bails out with incorrect ones. 2876 // Both CLI option (--default-ipc-mode) and config parameter are tested. 2877 func (s *DockerDaemonSuite) TestDaemonStartWithIpcModes(c *check.C) { 2878 testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) 2879 2880 ipcModes := []struct { 2881 mode string 2882 valid bool 2883 }{ 2884 {"private", true}, 2885 {"shareable", true}, 2886 2887 {"host", false}, 2888 {"container:123", false}, 2889 {"nosuchmode", false}, 2890 } 2891 2892 for _, from := range []string{"config", "cli"} { 2893 for _, m := range ipcModes { 2894 testDaemonStartIpcMode(c, from, m.mode, m.valid) 2895 } 2896 } 2897 } 2898 2899 // TestFailedPluginRemove makes sure that a failed plugin remove does not block 2900 // the daemon from starting 2901 func (s *DockerDaemonSuite) TestFailedPluginRemove(c *check.C) { 2902 testRequires(c, DaemonIsLinux, IsAmd64, testEnv.IsLocalDaemon) 2903 d := daemon.New(c, dockerBinary, dockerdBinary) 2904 d.Start(c) 2905 cli := d.NewClientT(c) 2906 2907 ctx, cancel := context.WithTimeout(context.Background(), 300*time.Second) 2908 defer cancel() 2909 2910 name := "test-plugin-rm-fail" 2911 out, err := cli.PluginInstall(ctx, name, types.PluginInstallOptions{ 2912 Disabled: true, 2913 AcceptAllPermissions: true, 2914 RemoteRef: "cpuguy83/docker-logdriver-test", 2915 }) 2916 c.Assert(err, checker.IsNil) 2917 defer out.Close() 2918 io.Copy(ioutil.Discard, out) 2919 2920 ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) 2921 defer cancel() 2922 p, _, err := cli.PluginInspectWithRaw(ctx, name) 2923 c.Assert(err, checker.IsNil) 2924 2925 // simulate a bad/partial removal by removing the plugin config. 2926 configPath := filepath.Join(d.Root, "plugins", p.ID, "config.json") 2927 c.Assert(os.Remove(configPath), checker.IsNil) 2928 2929 d.Restart(c) 2930 ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) 2931 defer cancel() 2932 _, err = cli.Ping(ctx) 2933 c.Assert(err, checker.IsNil) 2934 2935 _, _, err = cli.PluginInspectWithRaw(ctx, name) 2936 // plugin should be gone since the config.json is gone 2937 c.Assert(err, checker.NotNil) 2938 }