Browse Source

Allow extra lines in /etc/hosts

This adds a --add-host host:ip flag which appends lines to /etc/hosts.  This is needed in places where you want the container to get a different name resolution than it would through DNS.  This was submitted before as #5525, closed, and now I am re-opening.  It has come up 2 or 3 times in the last couple days.

Signed-off-by: Tim Hockin <thockin@google.com>
Tim Hockin 10 years ago
parent
commit
68e48b65a6

+ 5 - 0
daemon/container.go

@@ -422,6 +422,11 @@ func (container *Container) buildHostsFiles(IP string) error {
 		extraContent[alias] = child.NetworkSettings.IPAddress
 		extraContent[alias] = child.NetworkSettings.IPAddress
 	}
 	}
 
 
+	for _, extraHost := range container.hostConfig.ExtraHosts {
+		parts := strings.Split(extraHost, ":")
+		extraContent[parts[0]] = parts[1]
+	}
+
 	return etchosts.Build(container.HostsPath, IP, container.Config.Hostname, container.Config.Domainname, &extraContent)
 	return etchosts.Build(container.HostsPath, IP, container.Config.Hostname, container.Config.Domainname, &extraContent)
 }
 }
 
 

+ 5 - 0
docs/man/docker-run.1.md

@@ -7,6 +7,7 @@ docker-run - Run a command in a new container
 # SYNOPSIS
 # SYNOPSIS
 **docker run**
 **docker run**
 [**-a**|**--attach**[=*[]*]]
 [**-a**|**--attach**[=*[]*]]
+[**--add-host**[=*[]*]]
 [**-c**|**--cpu-shares**[=*0*]]
 [**-c**|**--cpu-shares**[=*0*]]
 [**--cap-add**[=*[]*]]
 [**--cap-add**[=*[]*]]
 [**--cap-drop**[=*[]*]]
 [**--cap-drop**[=*[]*]]
@@ -64,6 +65,10 @@ error. It can even pretend to be a TTY (this is what most commandline
 executables expect) and pass along signals. The **-a** option can be set for
 executables expect) and pass along signals. The **-a** option can be set for
 each of stdin, stdout, and stderr.
 each of stdin, stdout, and stderr.
 
 
+**--add-host**=*hostname*:*ip*
+   Add a line to /etc/hosts. The format is hostname:ip.  The **--add-host**
+option can be set multiple times.
+
 **-c**, **--cpu-shares**=0
 **-c**, **--cpu-shares**=0
    CPU shares in relative weight. You can increase the priority of a container
    CPU shares in relative weight. You can increase the priority of a container
 with the -c option. By default, all containers run at the same priority and get
 with the -c option. By default, all containers run at the same priority and get

+ 1 - 0
docs/sources/reference/commandline/cli.md

@@ -986,6 +986,7 @@ removed before the image is removed.
     Run a command in a new container
     Run a command in a new container
 
 
       -a, --attach=[]            Attach to STDIN, STDOUT or STDERR.
       -a, --attach=[]            Attach to STDIN, STDOUT or STDERR.
+      --add-host=[]              Add a custom host-to-IP mapping (host:ip)
       -c, --cpu-shares=0         CPU shares (relative weight)
       -c, --cpu-shares=0         CPU shares (relative weight)
       --cap-add=[]               Add Linux capabilities
       --cap-add=[]               Add Linux capabilities
       --cap-drop=[]              Drop Linux capabilities
       --cap-drop=[]              Drop Linux capabilities

+ 17 - 0
docs/sources/reference/run.md

@@ -139,6 +139,7 @@ example, `docker run ubuntu:14.04`.
                                  'none': no networking for this container
                                  'none': no networking for this container
                                  'container:<name|id>': reuses another container network stack
                                  'container:<name|id>': reuses another container network stack
                                  'host': use the host network stack inside the container
                                  'host': use the host network stack inside the container
+    --add-host=""   : Add a line to /etc/hosts (host:IP)
 
 
 By default, all containers have networking enabled and they can make any
 By default, all containers have networking enabled and they can make any
 outgoing connections. The operator can completely disable networking
 outgoing connections. The operator can completely disable networking
@@ -196,6 +197,22 @@ running the `redis-cli` command and connecting to the Redis server over the
     $ # use the redis container's network stack to access localhost
     $ # use the redis container's network stack to access localhost
     $ sudo docker run --rm -ti --net container:redis example/redis-cli -h 127.0.0.1
     $ sudo docker run --rm -ti --net container:redis example/redis-cli -h 127.0.0.1
 
 
+### Managing /etc/hosts
+
+Your container will have lines in `/etc/hosts` which define the hostname of the
+container itself as well as `localhost` and a few other common things.  The
+`--add-host` flag can be used to add additional lines to `/etc/hosts`.  
+
+    $ /docker run -ti --add-host db-static:86.75.30.9 ubuntu cat /etc/hosts
+    172.17.0.22     09d03f76bf2c
+    fe00::0         ip6-localnet
+    ff00::0         ip6-mcastprefix
+    ff02::1         ip6-allnodes
+    ff02::2         ip6-allrouters
+    127.0.0.1       localhost
+    ::1	            localhost ip6-localhost ip6-loopback
+    86.75.30.9      db-static
+
 ## Clean Up (–-rm)
 ## Clean Up (–-rm)
 
 
 By default a container's file system persists even after the container
 By default a container's file system persists even after the container

+ 17 - 0
integration-cli/docker_cli_run_test.go

@@ -1331,6 +1331,23 @@ func TestDnsOptionsBasedOnHostResolvConf(t *testing.T) {
 	logDone("run - dns options based on host resolv.conf")
 	logDone("run - dns options based on host resolv.conf")
 }
 }
 
 
+func TestRunAddHost(t *testing.T) {
+	defer deleteAllContainers()
+	cmd := exec.Command(dockerBinary, "run", "--add-host=extra:86.75.30.9", "busybox", "grep", "extra", "/etc/hosts")
+
+	out, _, err := runCommandWithOutput(cmd)
+	if err != nil {
+		t.Fatal(err, out)
+	}
+
+	actual := strings.Trim(out, "\r\n")
+	if actual != "86.75.30.9\textra" {
+		t.Fatalf("expected '86.75.30.9\textra', but says: '%s'", actual)
+	}
+
+	logDone("run - add-host option")
+}
+
 // Regression test for #6983
 // Regression test for #6983
 func TestAttachStdErrOnlyTTYMode(t *testing.T) {
 func TestAttachStdErrOnlyTTYMode(t *testing.T) {
 	cmd := exec.Command(dockerBinary, "run", "-t", "-a", "stderr", "busybox", "true")
 	cmd := exec.Command(dockerBinary, "run", "-t", "-a", "stderr", "busybox", "true")

+ 11 - 0
opts/opts.go

@@ -199,6 +199,17 @@ func validateDomain(val string) (string, error) {
 	return "", fmt.Errorf("%s is not a valid domain", val)
 	return "", fmt.Errorf("%s is not a valid domain", val)
 }
 }
 
 
+func ValidateExtraHost(val string) (string, error) {
+	arr := strings.Split(val, ":")
+	if len(arr) != 2 || len(arr[0]) == 0 {
+		return "", fmt.Errorf("bad format for add-host: %s", val)
+	}
+	if _, err := ValidateIPAddress(arr[1]); err != nil {
+		return "", fmt.Errorf("bad format for add-host: %s", val)
+	}
+	return val, nil
+}
+
 // Validates an HTTP(S) registry mirror
 // Validates an HTTP(S) registry mirror
 func ValidateMirror(val string) (string, error) {
 func ValidateMirror(val string) (string, error) {
 	uri, err := url.Parse(val)
 	uri, err := url.Parse(val)

+ 4 - 0
runconfig/hostconfig.go

@@ -49,6 +49,7 @@ type HostConfig struct {
 	PublishAllPorts bool
 	PublishAllPorts bool
 	Dns             []string
 	Dns             []string
 	DnsSearch       []string
 	DnsSearch       []string
+	ExtraHosts      []string
 	VolumesFrom     []string
 	VolumesFrom     []string
 	Devices         []DeviceMapping
 	Devices         []DeviceMapping
 	NetworkMode     NetworkMode
 	NetworkMode     NetworkMode
@@ -81,6 +82,9 @@ func ContainerHostConfigFromJob(job *engine.Job) *HostConfig {
 	if DnsSearch := job.GetenvList("DnsSearch"); DnsSearch != nil {
 	if DnsSearch := job.GetenvList("DnsSearch"); DnsSearch != nil {
 		hostConfig.DnsSearch = DnsSearch
 		hostConfig.DnsSearch = DnsSearch
 	}
 	}
+	if ExtraHosts := job.GetenvList("ExtraHosts"); ExtraHosts != nil {
+		hostConfig.ExtraHosts = ExtraHosts
+	}
 	if VolumesFrom := job.GetenvList("VolumesFrom"); VolumesFrom != nil {
 	if VolumesFrom := job.GetenvList("VolumesFrom"); VolumesFrom != nil {
 		hostConfig.VolumesFrom = VolumesFrom
 		hostConfig.VolumesFrom = VolumesFrom
 	}
 	}

+ 3 - 0
runconfig/parse.go

@@ -54,6 +54,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
 		flExpose      = opts.NewListOpts(nil)
 		flExpose      = opts.NewListOpts(nil)
 		flDns         = opts.NewListOpts(opts.ValidateIPAddress)
 		flDns         = opts.NewListOpts(opts.ValidateIPAddress)
 		flDnsSearch   = opts.NewListOpts(opts.ValidateDnsSearch)
 		flDnsSearch   = opts.NewListOpts(opts.ValidateDnsSearch)
+		flExtraHosts  = opts.NewListOpts(opts.ValidateExtraHost)
 		flVolumesFrom = opts.NewListOpts(nil)
 		flVolumesFrom = opts.NewListOpts(nil)
 		flLxcOpts     = opts.NewListOpts(nil)
 		flLxcOpts     = opts.NewListOpts(nil)
 		flEnvFile     = opts.NewListOpts(nil)
 		flEnvFile     = opts.NewListOpts(nil)
@@ -93,6 +94,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
 	cmd.Var(&flExpose, []string{"#expose", "-expose"}, "Expose a port from the container without publishing it to your host")
 	cmd.Var(&flExpose, []string{"#expose", "-expose"}, "Expose a port from the container without publishing it to your host")
 	cmd.Var(&flDns, []string{"#dns", "-dns"}, "Set custom DNS servers")
 	cmd.Var(&flDns, []string{"#dns", "-dns"}, "Set custom DNS servers")
 	cmd.Var(&flDnsSearch, []string{"-dns-search"}, "Set custom DNS search domains")
 	cmd.Var(&flDnsSearch, []string{"-dns-search"}, "Set custom DNS search domains")
+	cmd.Var(&flExtraHosts, []string{"-add-host"}, "Add a custom host-to-IP mapping (host:ip)")
 	cmd.Var(&flVolumesFrom, []string{"#volumes-from", "-volumes-from"}, "Mount volumes from the specified container(s)")
 	cmd.Var(&flVolumesFrom, []string{"#volumes-from", "-volumes-from"}, "Mount volumes from the specified container(s)")
 	cmd.Var(&flLxcOpts, []string{"#lxc-conf", "-lxc-conf"}, "(lxc exec-driver only) Add custom lxc options --lxc-conf=\"lxc.cgroup.cpuset.cpus = 0,1\"")
 	cmd.Var(&flLxcOpts, []string{"#lxc-conf", "-lxc-conf"}, "(lxc exec-driver only) Add custom lxc options --lxc-conf=\"lxc.cgroup.cpuset.cpus = 0,1\"")
 
 
@@ -291,6 +293,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
 		PublishAllPorts: *flPublishAll,
 		PublishAllPorts: *flPublishAll,
 		Dns:             flDns.GetAll(),
 		Dns:             flDns.GetAll(),
 		DnsSearch:       flDnsSearch.GetAll(),
 		DnsSearch:       flDnsSearch.GetAll(),
+		ExtraHosts:      flExtraHosts.GetAll(),
 		VolumesFrom:     flVolumesFrom.GetAll(),
 		VolumesFrom:     flVolumesFrom.GetAll(),
 		NetworkMode:     netMode,
 		NetworkMode:     netMode,
 		Devices:         deviceMappings,
 		Devices:         deviceMappings,