Browse code

The option --add-host and --net=host should not be mutually exclusive.

This fix tries to address the issue raised in #21976 and allows
the options of `--add-host` and `--net=host` to work at the same time.

The documentation has been updated and additional tests have been
added to cover this change.

This fix fixes #21976.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>

Yong Tang authored on 2016/05/25 10:49:11
Showing 5 changed files
... ...
@@ -47,7 +47,9 @@ func (daemon *Daemon) buildSandboxOptions(container *container.Container, n libn
47 47
 
48 48
 	if container.HostConfig.NetworkMode.IsHost() {
49 49
 		sboxOptions = append(sboxOptions, libnetwork.OptionUseDefaultSandbox())
50
-		sboxOptions = append(sboxOptions, libnetwork.OptionOriginHostsPath("/etc/hosts"))
50
+		if len(container.HostConfig.ExtraHosts) == 0 {
51
+			sboxOptions = append(sboxOptions, libnetwork.OptionOriginHostsPath("/etc/hosts"))
52
+		}
51 53
 		if len(container.HostConfig.DNS) == 0 && len(daemon.configStore.DNS) == 0 &&
52 54
 			len(container.HostConfig.DNSSearch) == 0 && len(daemon.configStore.DNSSearch) == 0 &&
53 55
 			len(container.HostConfig.DNSOptions) == 0 && len(daemon.configStore.DNSOptions) == 0 {
... ...
@@ -382,14 +382,14 @@ name, they must be linked.
382 382
 With the network set to `host` a container will share the host's
383 383
 network stack and all interfaces from the host will be available to the
384 384
 container.  The container's hostname will match the hostname on the host
385
-system.  Note that `--add-host` and `--mac-address` are invalid in `host` netmode. Even in `host`
385
+system. Note that `--mac-address` is invalid in `host` netmode. Even in `host`
386 386
 network mode a container has its own UTS namespace by default. As such
387 387
 `--hostname` is allowed in `host` network mode and will only change the
388 388
 hostname inside the container.
389
-Note also that `--dns`, `--dns-search` and `--dns-opt` are
390
-valid in `host` mode and `/etc/resolv.conf` will be updated accordingly. However, the
391
-update in `/etc/resolv.conf` only happens inside the container. No change will be
392
-made for `/etc/resolv.conf` in host.
389
+Similar to `--hostname`, the `--add-host`, `--dns`, `--dns-search`, and
390
+`--dns-opt` options can be used in `host` network mode. These options update
391
+`/etc/hosts` or `/etc/resolv.conf` inside the container. No change are made to
392
+`/etc/hosts` and `/etc/resolv.conf` on the host.
393 393
 
394 394
 Compared to the default `bridge` mode, the `host` mode gives *significantly*
395 395
 better networking performance since it uses the host's native networking stack
... ...
@@ -67,10 +67,7 @@ func (s *DockerSuite) TestConflictContainerNetworkHostAndLinks(c *check.C) {
67 67
 func (s *DockerSuite) TestConflictNetworkModeNetHostAndOptions(c *check.C) {
68 68
 	testRequires(c, DaemonIsLinux, NotUserNamespace)
69 69
 
70
-	out, _ := dockerCmdWithFail(c, "run", "--net=host", "--add-host=name:8.8.8.8", "busybox", "ps")
71
-	c.Assert(out, checker.Contains, runconfig.ErrConflictNetworkHosts.Error())
72
-
73
-	out, _ = dockerCmdWithFail(c, "run", "--net=host", "--mac-address=92:d0:c6:0a:29:33", "busybox", "ps")
70
+	out, _ := dockerCmdWithFail(c, "run", "--net=host", "--mac-address=92:d0:c6:0a:29:33", "busybox", "ps")
74 71
 	c.Assert(out, checker.Contains, runconfig.ErrConflictContainerNetworkAndMac.Error())
75 72
 }
76 73
 
... ...
@@ -4401,3 +4401,12 @@ func (s *DockerSuite) TestRunDnsInHostMode(c *check.C) {
4401 4401
 	c.Assert(out, checker.Contains, expectedOutput2, check.Commentf("Expected '%s', but got %q", expectedOutput2, out))
4402 4402
 	c.Assert(out, checker.Contains, expectedOutput3, check.Commentf("Expected '%s', but got %q", expectedOutput3, out))
4403 4403
 }
4404
+
4405
+// Test case for #21976
4406
+func (s *DockerSuite) TestRunAddHostInHostMode(c *check.C) {
4407
+	testRequires(c, DaemonIsLinux, NotUserNamespace)
4408
+
4409
+	expectedOutput := "1.2.3.4\textra"
4410
+	out, _ := dockerCmd(c, "run", "--add-host=extra:1.2.3.4", "--net=host", "busybox", "cat", "/etc/hosts")
4411
+	c.Assert(out, checker.Contains, expectedOutput, check.Commentf("Expected '%s', but got %q", expectedOutput, out))
4412
+}
... ...
@@ -56,7 +56,7 @@ func ValidateNetMode(c *container.Config, hc *container.HostConfig) error {
56 56
 		return ErrConflictNetworkAndDNS
57 57
 	}
58 58
 
59
-	if (hc.NetworkMode.IsContainer() || hc.NetworkMode.IsHost()) && len(hc.ExtraHosts) > 0 {
59
+	if hc.NetworkMode.IsContainer() && len(hc.ExtraHosts) > 0 {
60 60
 		return ErrConflictNetworkHosts
61 61
 	}
62 62