Browse code

Add linked container's name and hostname as aliases to `/etc/hosts`

Currently when containers are linked the alias name (e.g. from `--link
name:alias`) is added to the parent container's `/etc/hosts` with a
reference to the IP of the linked container. Some software requires
using the official hostname or node name in operations that need to
match on those values, and it is therefore helpful if the parent
container can refer to the child/link using those same values and still
access the same IP.

Docker-DCO-1.1-Signed-off-by: Phil Estes <estesp@linux.vnet.ibm.com> (github: estesp)

Phil Estes authored on 2015/02/16 14:00:51
Showing 3 changed files
... ...
@@ -457,7 +457,13 @@ func (container *Container) buildHostsFiles(IP string) error {
457 457
 
458 458
 	for linkAlias, child := range children {
459 459
 		_, alias := path.Split(linkAlias)
460
-		extraContent = append(extraContent, etchosts.Record{Hosts: alias, IP: child.NetworkSettings.IPAddress})
460
+		// allow access to the linked container via the alias, real name, and container hostname
461
+		aliasList := alias + " " + child.Config.Hostname
462
+		// only add the name if alias isn't equal to the name
463
+		if alias != child.Name[1:] {
464
+			aliasList = aliasList + " " + child.Name[1:]
465
+		}
466
+		extraContent = append(extraContent, etchosts.Record{Hosts: aliasList, IP: child.NetworkSettings.IPAddress})
461 467
 	}
462 468
 
463 469
 	for _, extraHost := range container.hostConfig.ExtraHosts {
... ...
@@ -252,20 +252,23 @@ In addition to the environment variables, Docker adds a host entry for the
252 252
 source container to the `/etc/hosts` file. Here's an entry for the `web`
253 253
 container:
254 254
 
255
-    $ sudo docker run -t -i --rm --link db:db training/webapp /bin/bash
255
+    $ sudo docker run -t -i --rm --link db:webdb training/webapp /bin/bash
256 256
     root@aed84ee21bde:/opt/webapp# cat /etc/hosts
257 257
     172.17.0.7  aed84ee21bde
258 258
     . . .
259
-    172.17.0.5  db
259
+    172.17.0.5  webdb 6e5cdeb2d300 db
260 260
 
261 261
 You can see two relevant host entries. The first is an entry for the `web`
262 262
 container that uses the Container ID as a host name. The second entry uses the
263
-link alias to reference the IP address of the `db` container. You can ping
264
-that host now via this host name.
263
+link alias to reference the IP address of the `db` container. In addition to 
264
+the alias you provide, the linked container's name--if unique from the alias
265
+provided to the `--link` parameter--and the linked container's hostname will
266
+also be added in `/etc/hosts` for the linked container's IP address. You can ping
267
+that host now via any of these entries:
265 268
 
266 269
     root@aed84ee21bde:/opt/webapp# apt-get install -yqq inetutils-ping
267
-    root@aed84ee21bde:/opt/webapp# ping db
268
-    PING db (172.17.0.5): 48 data bytes
270
+    root@aed84ee21bde:/opt/webapp# ping webdb
271
+    PING webdb (172.17.0.5): 48 data bytes
269 272
     56 bytes from 172.17.0.5: icmp_seq=0 ttl=64 time=0.267 ms
270 273
     56 bytes from 172.17.0.5: icmp_seq=1 ttl=64 time=0.250 ms
271 274
     56 bytes from 172.17.0.5: icmp_seq=2 ttl=64 time=0.256 ms
... ...
@@ -65,16 +65,27 @@ func TestLinksPingUnlinkedContainers(t *testing.T) {
65 65
 }
66 66
 
67 67
 func TestLinksPingLinkedContainers(t *testing.T) {
68
-	var out string
69
-	out, _, _ = dockerCmd(t, "run", "-d", "--name", "container1", "busybox", "sleep", "10")
70
-	idA := stripTrailingCharacters(out)
71
-	out, _, _ = dockerCmd(t, "run", "-d", "--name", "container2", "busybox", "sleep", "10")
72
-	idB := stripTrailingCharacters(out)
73
-	dockerCmd(t, "run", "--rm", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "sh", "-c", "ping -c 1 alias1 -W 1 && ping -c 1 alias2 -W 1")
74
-	dockerCmd(t, "kill", idA)
75
-	dockerCmd(t, "kill", idB)
76
-	deleteAllContainers()
68
+	runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "container1", "--hostname", "fred", "busybox", "top")
69
+	if _, err := runCommand(runCmd); err != nil {
70
+		t.Fatal(err)
71
+	}
72
+	runCmd = exec.Command(dockerBinary, "run", "-d", "--name", "container2", "--hostname", "wilma", "busybox", "top")
73
+	if _, err := runCommand(runCmd); err != nil {
74
+		t.Fatal(err)
75
+	}
77 76
 
77
+	runArgs := []string{"run", "--rm", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "sh", "-c"}
78
+	pingCmd := "ping -c 1 %s -W 1 && ping -c 1 %s -W 1"
79
+
80
+	// test ping by alias, ping by name, and ping by hostname
81
+	// 1. Ping by alias
82
+	dockerCmd(t, append(runArgs, fmt.Sprintf(pingCmd, "alias1", "alias2"))...)
83
+	// 2. Ping by container name
84
+	dockerCmd(t, append(runArgs, fmt.Sprintf(pingCmd, "container1", "container2"))...)
85
+	// 3. Ping by hostname
86
+	dockerCmd(t, append(runArgs, fmt.Sprintf(pingCmd, "fred", "wilma"))...)
87
+
88
+	deleteAllContainers()
78 89
 	logDone("links - ping linked container")
79 90
 }
80 91