Bläddra i källkod

Merge pull request #5056 by Bryan Murphy <bmurphy1976@gmail.com>

"add linked containers to hosts file"
Solomon Hykes 11 år sedan
förälder
incheckning
95d81dada6

+ 14 - 1
daemon/container.go

@@ -357,7 +357,20 @@ func (container *Container) buildHostnameAndHostsFiles(IP string) error {
 	}
 
 	container.HostsPath = path.Join(container.root, "hosts")
-	return etchosts.Build(container.HostsPath, IP, container.Config.Hostname, container.Config.Domainname)
+
+	extraContent := make(map[string]string)
+
+	children, err := container.daemon.Children(container.Name)
+	if err != nil {
+		return err
+	}
+
+	for linkAlias, child := range children {
+		_, alias := path.Split(linkAlias)
+		extraContent[alias] = child.NetworkSettings.IPAddress
+	}
+
+	return etchosts.Build(container.HostsPath, IP, container.Config.Hostname, container.Config.Domainname, &extraContent)
 }
 
 func (container *Container) allocateNetwork() error {

+ 8 - 1
docs/sources/reference/run.md

@@ -1,4 +1,4 @@
-page_title: Docker Run Reference 
+page_title: Docker Run Reference
 page_description: Configure containers at runtime
 page_keywords: docker, run, configure, runtime
 
@@ -407,6 +407,13 @@ And we can use that information to connect from another container as a client:
     $ docker run -i -t --rm --link redis-name:redis_alias --entrypoint /bin/bash dockerfiles/redis -c '/redis-stable/src/redis-cli -h $REDIS_ALIAS_PORT_6379_TCP_ADDR -p $REDIS_ALIAS_PORT_6379_TCP_PORT'
     172.17.0.32:6379>
 
+Docker will also map the private IP address to the alias of a linked
+container by inserting an entry into `/etc/hosts`.  You can use this
+mechanism to communicate with a linked container by its alias:
+
+    $ docker run -d --name servicename busybox sleep 30
+    $ docker run -i -t --link servicename:servicealias busybox ping -c 1 servicealias
+
 ## VOLUME (Shared Filesystems)
 
     -v=[]: Create a bind mount with: [host-dir]:[container-dir]:[rw|ro].

+ 29 - 0
docs/sources/use/working_with_links_names.md

@@ -109,3 +109,32 @@ the Redis container.
     CONTAINER ID        IMAGE                        COMMAND                CREATED              STATUS              PORTS               NAMES
     4c01db0b339c        ubuntu:12.04                 bash                   17 seconds ago       Up 16 seconds                           webapp
     d7886598dbe2        crosbymichael/redis:latest   /redis-server --dir    33 minutes ago       Up 33 minutes       6379/tcp            redis,webapp/db
+
+## Resolving Links by Name
+
+New in version v0.11.
+
+Linked containers can be accessed by hostname.  Hostnames are mapped by
+appending entries to '/etc/hosts' using the linked container's alias.
+
+For example, linking a container using '--link redis:db' will generate the
+following '/etc/hosts' file:
+
+    root@6541a75d44a0:/# cat /etc/hosts
+    172.17.0.3  6541a75d44a0
+    172.17.0.2  db
+
+    127.0.0.1   localhost
+    ::1     localhost ip6-localhost ip6-loopback
+    fe00::0     ip6-localnet
+    ff00::0     ip6-mcastprefix
+    ff02::1     ip6-allnodes
+    ff02::2     ip6-allrouters
+    root@6541a75d44a0:/#
+
+Using this mechanism, you can communicate with the linked container by
+name:
+
+    root@6541a75d44a0:/# echo PING | redis-cli -h db
+    PONG
+    root@6541a75d44a0:/#

+ 30 - 0
integration-cli/docker_cli_links_test.go

@@ -0,0 +1,30 @@
+package main
+
+import (
+	"fmt"
+	"os/exec"
+	"testing"
+)
+
+func TestPingUnlinkedContainers(t *testing.T) {
+	runCmd := exec.Command(dockerBinary, "run", "--rm", "busybox", "sh", "-c", "ping -c 1 alias1 -W 1 && ping -c 1 alias2 -W 1")
+	exitCode, err := runCommand(runCmd)
+
+	if exitCode == 0 {
+		t.Fatal("run ping did not fail")
+	} else if exitCode != 1 {
+		errorOut(err, t, fmt.Sprintf("run ping failed with errors: %v", err))
+	}
+}
+
+func TestPingLinkedContainers(t *testing.T) {
+	var out string
+	out, _, _ = cmd(t, "run", "-d", "--name", "container1", "busybox", "sleep", "10")
+	idA := stripTrailingCharacters(out)
+	out, _, _ = cmd("run", "-d", "--name", "container2", "busybox", "sleep", "10")
+	idB := stripTrailingCharacters(out)
+	cmd("run", "--rm", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "sh", "-c", "ping -c 1 alias1 -W 1 && ping -c 1 alias2 -W 1")
+	cmd("kill", idA)
+	cmd("kill", idB)
+	deleteAllContainers()
+}

+ 10 - 1
pkg/networkfs/etchosts/etchosts.go

@@ -15,7 +15,7 @@ var defaultContent = map[string]string{
 	"ip6-allrouters":                       "ff02::2",
 }
 
-func Build(path, IP, hostname, domainname string) error {
+func Build(path, IP, hostname, domainname string, extraContent *map[string]string) error {
 	content := bytes.NewBuffer(nil)
 	if IP != "" {
 		if domainname != "" {
@@ -30,5 +30,14 @@ func Build(path, IP, hostname, domainname string) error {
 			return err
 		}
 	}
+
+	if extraContent != nil {
+		for hosts, ip := range *extraContent {
+			if _, err := content.WriteString(fmt.Sprintf("%s\t%s\n", ip, hosts)); err != nil {
+				return err
+			}
+		}
+	}
+
 	return ioutil.WriteFile(path, content.Bytes(), 0644)
 }