Преглед на файлове

Add support for DNS options

Signed-off-by: Tim Hockin <thockin@google.com>
Tim Hockin преди 10 години
родител
ревизия
3d4685e258

+ 2 - 0
contrib/completion/bash/docker

@@ -533,6 +533,7 @@ _docker_daemon() {
 		--default-ulimit
 		--default-ulimit
 		--dns
 		--dns
 		--dns-search
 		--dns-search
+		--dns-opt
 		--exec-driver -e
 		--exec-driver -e
 		--exec-opt
 		--exec-opt
 		--exec-root
 		--exec-root
@@ -1124,6 +1125,7 @@ _docker_run() {
 		--cpu-shares -c
 		--cpu-shares -c
 		--device
 		--device
 		--dns
 		--dns
+		--dns-opt
 		--dns-search
 		--dns-search
 		--entrypoint
 		--entrypoint
 		--env -e
 		--env -e

+ 3 - 0
contrib/completion/fish/docker.fish

@@ -49,6 +49,7 @@ complete -c docker -f -n '__fish_docker_no_subcommand' -l bip -d "Use this CIDR
 complete -c docker -f -n '__fish_docker_no_subcommand' -s D -l debug -d 'Enable debug mode'
 complete -c docker -f -n '__fish_docker_no_subcommand' -s D -l debug -d 'Enable debug mode'
 complete -c docker -f -n '__fish_docker_no_subcommand' -s d -l daemon -d 'Enable daemon mode'
 complete -c docker -f -n '__fish_docker_no_subcommand' -s d -l daemon -d 'Enable daemon mode'
 complete -c docker -f -n '__fish_docker_no_subcommand' -l dns -d 'Force Docker to use specific DNS servers'
 complete -c docker -f -n '__fish_docker_no_subcommand' -l dns -d 'Force Docker to use specific DNS servers'
+complete -c docker -f -n '__fish_docker_no_subcommand' -l dns-opt -d 'Force Docker to use specific DNS options'
 complete -c docker -f -n '__fish_docker_no_subcommand' -l dns-search -d 'Force Docker to use specific DNS search domains'
 complete -c docker -f -n '__fish_docker_no_subcommand' -l dns-search -d 'Force Docker to use specific DNS search domains'
 complete -c docker -f -n '__fish_docker_no_subcommand' -s e -l exec-driver -d 'Force the Docker runtime to use a specific exec driver'
 complete -c docker -f -n '__fish_docker_no_subcommand' -s e -l exec-driver -d 'Force the Docker runtime to use a specific exec driver'
 complete -c docker -f -n '__fish_docker_no_subcommand' -l exec-opt -d 'Set exec driver options'
 complete -c docker -f -n '__fish_docker_no_subcommand' -l exec-opt -d 'Set exec driver options'
@@ -122,6 +123,7 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l cidfile -d '
 complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l cpuset -d 'CPUs in which to allow execution (0-3, 0,1)'
 complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l cpuset -d 'CPUs in which to allow execution (0-3, 0,1)'
 complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l device -d 'Add a host device to the container (e.g. --device=/dev/sdc:/dev/xvdc:rwm)'
 complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l device -d 'Add a host device to the container (e.g. --device=/dev/sdc:/dev/xvdc:rwm)'
 complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l dns -d 'Set custom DNS servers'
 complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l dns -d 'Set custom DNS servers'
+complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l dns-opt -d "Set custom DNS options (Use --dns-opt='' if you don't wish to set options)"
 complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l dns-search -d "Set custom DNS search domains (Use --dns-search=. if you don't wish to set the search domain)"
 complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l dns-search -d "Set custom DNS search domains (Use --dns-search=. if you don't wish to set the search domain)"
 complete -c docker -A -f -n '__fish_seen_subcommand_from create' -s e -l env -d 'Set environment variables'
 complete -c docker -A -f -n '__fish_seen_subcommand_from create' -s e -l env -d 'Set environment variables'
 complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l entrypoint -d 'Overwrite the default ENTRYPOINT of the image'
 complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l entrypoint -d 'Overwrite the default ENTRYPOINT of the image'
@@ -309,6 +311,7 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l cpuset -d 'CPUs
 complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s d -l detach -d 'Detached mode: run the container in the background and print the new container ID'
 complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s d -l detach -d 'Detached mode: run the container in the background and print the new container ID'
 complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l device -d 'Add a host device to the container (e.g. --device=/dev/sdc:/dev/xvdc:rwm)'
 complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l device -d 'Add a host device to the container (e.g. --device=/dev/sdc:/dev/xvdc:rwm)'
 complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l dns -d 'Set custom DNS servers'
 complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l dns -d 'Set custom DNS servers'
+complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l dns-opt -d "Set custom DNS options (Use --dns-opt='' if you don't wish to set options)"
 complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l dns-search -d "Set custom DNS search domains (Use --dns-search=. if you don't wish to set the search domain)"
 complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l dns-search -d "Set custom DNS search domains (Use --dns-search=. if you don't wish to set the search domain)"
 complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s e -l env -d 'Set environment variables'
 complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s e -l env -d 'Set environment variables'
 complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l entrypoint -d 'Overwrite the default ENTRYPOINT of the image'
 complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l entrypoint -d 'Overwrite the default ENTRYPOINT of the image'

+ 5 - 3
contrib/completion/zsh/_docker

@@ -226,8 +226,9 @@ __docker_subcommand() {
         "($help)*--cap-drop=-[Drop Linux capabilities]:capability: "
         "($help)*--cap-drop=-[Drop Linux capabilities]:capability: "
         "($help)--cidfile=-[Write the container ID to the file]:CID file:_files"
         "($help)--cidfile=-[Write the container ID to the file]:CID file:_files"
         "($help)*--device=-[Add a host device to the container]:device:_files"
         "($help)*--device=-[Add a host device to the container]:device:_files"
-        "($help)*--dns=-[Set custom dns servers]:dns server: "
-        "($help)*--dns-search=-[Set custom DNS search domains]:dns domains: "
+        "($help)*--dns=-[Set custom DNS servers]:DNS server: "
+        "($help)*--dns-opt=-[Set custom DNS options]:DNS option: "
+        "($help)*--dns-search=-[Set custom DNS search domains]:DNS domains: "
         "($help)*"{-e,--env=-}"[Set environment variables]:environment variable: "
         "($help)*"{-e,--env=-}"[Set environment variables]:environment variable: "
         "($help)--entrypoint=-[Overwrite the default entrypoint of the image]:entry point: "
         "($help)--entrypoint=-[Overwrite the default entrypoint of the image]:entry point: "
         "($help)*--env-file=-[Read environment variables from a file]:environment file:_files"
         "($help)*--env-file=-[Read environment variables from a file]:environment file:_files"
@@ -599,7 +600,8 @@ _docker() {
         "($help)--default-gateway[Container default gateway IPv4 address]:IPv4 address: " \
         "($help)--default-gateway[Container default gateway IPv4 address]:IPv4 address: " \
         "($help)--default-gateway-v6[Container default gateway IPv6 address]:IPv6 address: " \
         "($help)--default-gateway-v6[Container default gateway IPv6 address]:IPv6 address: " \
         "($help)*--dns=-[DNS server to use]:DNS: " \
         "($help)*--dns=-[DNS server to use]:DNS: " \
-        "($help)*--dns-search=-[DNS search domains to use]" \
+        "($help)*--dns-search=-[DNS search domains to use]:DNS search: " \
+        "($help)*--dns-opt=-[DNS options to use]:DNS option: " \
         "($help)*--default-ulimit=-[Set default ulimit settings for containers]:ulimit: " \
         "($help)*--default-ulimit=-[Set default ulimit settings for containers]:ulimit: " \
         "($help -e --exec-driver)"{-e,--exec-driver=-}"[Exec driver to use]:driver:(native lxc windows)" \
         "($help -e --exec-driver)"{-e,--exec-driver=-}"[Exec driver to use]:driver:(native lxc windows)" \
         "($help)*--exec-opt=-[Set exec driver options]:exec driver options: " \
         "($help)*--exec-opt=-[Set exec driver options]:exec driver options: " \

+ 2 - 0
daemon/config.go

@@ -19,6 +19,7 @@ type CommonConfig struct {
 	Context        map[string][]string
 	Context        map[string][]string
 	DisableBridge  bool
 	DisableBridge  bool
 	DNS            []string
 	DNS            []string
+	DNSOptions     []string
 	DNSSearch      []string
 	DNSSearch      []string
 	ExecDriver     string
 	ExecDriver     string
 	ExecOptions    []string
 	ExecOptions    []string
@@ -51,6 +52,7 @@ func (config *Config) InstallCommonFlags(cmd *flag.FlagSet, usageFn func(string)
 	cmd.IntVar(&config.Mtu, []string{"#mtu", "-mtu"}, 0, usageFn("Set the containers network MTU"))
 	cmd.IntVar(&config.Mtu, []string{"#mtu", "-mtu"}, 0, usageFn("Set the containers network MTU"))
 	// FIXME: why the inconsistency between "hosts" and "sockets"?
 	// FIXME: why the inconsistency between "hosts" and "sockets"?
 	cmd.Var(opts.NewListOptsRef(&config.DNS, opts.ValidateIPAddress), []string{"#dns", "-dns"}, usageFn("DNS server to use"))
 	cmd.Var(opts.NewListOptsRef(&config.DNS, opts.ValidateIPAddress), []string{"#dns", "-dns"}, usageFn("DNS server to use"))
+	cmd.Var(opts.NewListOptsRef(&config.DNSOptions, nil), []string{"-dns-opt"}, usageFn("DNS options to use"))
 	cmd.Var(opts.NewListOptsRef(&config.DNSSearch, opts.ValidateDNSSearch), []string{"-dns-search"}, usageFn("DNS search domains to use"))
 	cmd.Var(opts.NewListOptsRef(&config.DNSSearch, opts.ValidateDNSSearch), []string{"-dns-search"}, usageFn("DNS search domains to use"))
 	cmd.Var(opts.NewListOptsRef(&config.Labels, opts.ValidateLabel), []string{"-label"}, usageFn("Set key=value labels to the daemon"))
 	cmd.Var(opts.NewListOptsRef(&config.Labels, opts.ValidateLabel), []string{"-label"}, usageFn("Set key=value labels to the daemon"))
 	cmd.StringVar(&config.LogConfig.Type, []string{"-log-driver"}, "json-file", usageFn("Default driver for container logs"))
 	cmd.StringVar(&config.LogConfig.Type, []string{"-log-driver"}, "json-file", usageFn("Default driver for container logs"))

+ 11 - 0
daemon/container_unix.go

@@ -397,6 +397,7 @@ func (container *Container) buildSandboxOptions() ([]libnetwork.SandboxOption, e
 		err         error
 		err         error
 		dns         []string
 		dns         []string
 		dnsSearch   []string
 		dnsSearch   []string
+		dnsOptions  []string
 	)
 	)
 
 
 	sboxOptions = append(sboxOptions, libnetwork.OptionHostname(container.Config.Hostname),
 	sboxOptions = append(sboxOptions, libnetwork.OptionHostname(container.Config.Hostname),
@@ -444,6 +445,16 @@ func (container *Container) buildSandboxOptions() ([]libnetwork.SandboxOption, e
 		sboxOptions = append(sboxOptions, libnetwork.OptionDNSSearch(ds))
 		sboxOptions = append(sboxOptions, libnetwork.OptionDNSSearch(ds))
 	}
 	}
 
 
+	if len(container.hostConfig.DNSOptions) > 0 {
+		dnsOptions = container.hostConfig.DNSOptions
+	} else if len(container.daemon.configStore.DNSOptions) > 0 {
+		dnsOptions = container.daemon.configStore.DNSOptions
+	}
+
+	for _, ds := range dnsOptions {
+		sboxOptions = append(sboxOptions, libnetwork.OptionDNSOptions(ds))
+	}
+
 	if container.NetworkSettings.SecondaryIPAddresses != nil {
 	if container.NetworkSettings.SecondaryIPAddresses != nil {
 		name := container.Config.Hostname
 		name := container.Config.Hostname
 		if container.Config.Domainname != "" {
 		if container.Config.Domainname != "" {

+ 4 - 4
daemon/daemon_test.go

@@ -174,7 +174,7 @@ func TestLoadWithVolume(t *testing.T) {
 	}
 	}
 
 
 	hostConfig := `{"Binds":[],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
 	hostConfig := `{"Binds":[],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
-"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
+"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsOptions":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
 "Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
 "Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
 "SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
 "SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
 	if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
 	if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
@@ -262,7 +262,7 @@ func TestLoadWithBindMount(t *testing.T) {
 	}
 	}
 
 
 	hostConfig := `{"Binds":["/vol1:/vol1"],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
 	hostConfig := `{"Binds":["/vol1:/vol1"],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
-"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
+"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsOptions":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
 "Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
 "Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
 "SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
 "SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
 	if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
 	if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
@@ -353,7 +353,7 @@ func TestLoadWithVolume17RC(t *testing.T) {
 	}
 	}
 
 
 	hostConfig := `{"Binds":[],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
 	hostConfig := `{"Binds":[],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
-"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
+"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsOptions":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
 "Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
 "Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
 "SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
 "SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
 	if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
 	if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
@@ -458,7 +458,7 @@ func TestRemoveLocalVolumesFollowingSymlinks(t *testing.T) {
 	}
 	}
 
 
 	hostConfig := `{"Binds":[],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
 	hostConfig := `{"Binds":[],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
-"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
+"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsOptions":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
 "Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
 "Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
 "SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
 "SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
 	if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
 	if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {

+ 17 - 10
docs/articles/networking.md

@@ -102,7 +102,7 @@ server when it starts up, and cannot be changed once it is running:
  *  `--userland-proxy=true|false` — see
  *  `--userland-proxy=true|false` — see
     [Binding container ports](#binding-ports)
     [Binding container ports](#binding-ports)
 
 
-There are two networking options that can be supplied either at startup
+There are three networking options that can be supplied either at startup
 or when `docker run` is invoked.  When provided at startup, set the
 or when `docker run` is invoked.  When provided at startup, set the
 default value that `docker run` will later use if the options are not
 default value that `docker run` will later use if the options are not
 specified:
 specified:
@@ -113,6 +113,9 @@ specified:
  *  `--dns-search=DOMAIN...` — see
  *  `--dns-search=DOMAIN...` — see
     [Configuring DNS](#dns)
     [Configuring DNS](#dns)
 
 
+ *  `--dns-opt=OPTION...` — see
+    [Configuring DNS](#dns)
+
 Finally, several networking options can only be provided when calling
 Finally, several networking options can only be provided when calling
 `docker run` because they specify something specific to one container:
 `docker run` because they specify something specific to one container:
 
 
@@ -215,12 +218,16 @@ Four different options affect container domain name services.
     only look up `host` but also `host.example.com`.
     only look up `host` but also `host.example.com`.
     Use `--dns-search=.` if you don't wish to set the search domain.
     Use `--dns-search=.` if you don't wish to set the search domain.
 
 
-Regarding DNS settings, in the absence of either the `--dns=IP_ADDRESS...`
-or the `--dns-search=DOMAIN...` option, Docker makes each container's
-`/etc/resolv.conf` look like the `/etc/resolv.conf` of the host machine (where
-the `docker` daemon runs).  When creating the container's `/etc/resolv.conf`,
-the daemon filters out all localhost IP address `nameserver` entries from
-the host's original file.
+ *  `--dns-opt=OPTION...` — sets the options used by DNS resolvers
+    by writing an `options` line into the container's `/etc/resolv.conf`.
+    See documentation for `resolv.conf` for a list of valid options.
+
+Regarding DNS settings, in the absence of the `--dns=IP_ADDRESS...`,
+`--dns-search=DOMAIN...`, or `--dns-opt=OPTION...` options, Docker makes
+each container's `/etc/resolv.conf` look like the `/etc/resolv.conf` of the
+host machine (where the `docker` daemon runs).  When creating the container's
+`/etc/resolv.conf`, the daemon filters out all localhost IP address
+`nameserver` entries from the host's original file.
 
 
 Filtering is necessary because all localhost addresses on the host are
 Filtering is necessary because all localhost addresses on the host are
 unreachable from the container's network.  After this filtering, if there 
 unreachable from the container's network.  After this filtering, if there 
@@ -253,9 +260,9 @@ of a facility to ensure atomic writes of the `resolv.conf` file while the
 container is running. If the container's `resolv.conf` has been edited since
 container is running. If the container's `resolv.conf` has been edited since
 it was started with the default configuration, no replacement will be
 it was started with the default configuration, no replacement will be
 attempted as it would overwrite the changes performed by the container.
 attempted as it would overwrite the changes performed by the container.
-If the options (`--dns` or `--dns-search`) have been used to modify the 
-default host configuration, then the replacement with an updated host's
-`/etc/resolv.conf` will not happen as well.
+If the options (`--dns`, `--dns-search`, or `--dns-opt`) have been used to
+modify the default host configuration, then the replacement with an updated
+host's `/etc/resolv.conf` will not happen as well.
 
 
 > **Note**:
 > **Note**:
 > For containers which were created prior to the implementation of
 > For containers which were created prior to the implementation of

+ 2 - 0
docs/reference/api/docker_remote_api.md

@@ -84,6 +84,8 @@ This section lists each version from latest to oldest.  Each listing includes a
 * `GET /images/(name)/json` now returns information about tags of the image.
 * `GET /images/(name)/json` now returns information about tags of the image.
 * The `config` option now accepts the field `StopSignal`, which specifies the signal to use to kill a container.
 * The `config` option now accepts the field `StopSignal`, which specifies the signal to use to kill a container.
 * `GET /containers/(id)/stats` will return networking information respectively for each interface.
 * `GET /containers/(id)/stats` will return networking information respectively for each interface.
+* The `hostConfig` option now accepts the field `DnsOptions`, which specifies a
+list of DNS options to be used in the container.
 
 
 
 
 ### v1.20 API changes
 ### v1.20 API changes

+ 3 - 0
docs/reference/api/docker_remote_api_v1.21.md

@@ -186,6 +186,7 @@ Create a container
              "Privileged": false,
              "Privileged": false,
              "ReadonlyRootfs": false,
              "ReadonlyRootfs": false,
              "Dns": ["8.8.8.8"],
              "Dns": ["8.8.8.8"],
+             "DnsOptions": [""],
              "DnsSearch": [""],
              "DnsSearch": [""],
              "ExtraHosts": null,
              "ExtraHosts": null,
              "VolumesFrom": ["parent", "other:ro"],
              "VolumesFrom": ["parent", "other:ro"],
@@ -272,6 +273,7 @@ Json Parameters:
     -   **ReadonlyRootfs** - Mount the container's root filesystem as read only.
     -   **ReadonlyRootfs** - Mount the container's root filesystem as read only.
           Specified as a boolean value.
           Specified as a boolean value.
     -   **Dns** - A list of DNS servers for the container to use.
     -   **Dns** - A list of DNS servers for the container to use.
+    -   **DnsOptions** - A list of DNS options
     -   **DnsSearch** - A list of DNS search domains
     -   **DnsSearch** - A list of DNS search domains
     -   **ExtraHosts** - A list of hostnames/IP mappings to add to the
     -   **ExtraHosts** - A list of hostnames/IP mappings to add to the
         container's `/etc/hosts` file. Specified in the form `["hostname:IP"]`.
         container's `/etc/hosts` file. Specified in the form `["hostname:IP"]`.
@@ -388,6 +390,7 @@ Return low-level information on the container `id`
 			"CpuPeriod": 100000,
 			"CpuPeriod": 100000,
 			"Devices": [],
 			"Devices": [],
 			"Dns": null,
 			"Dns": null,
+			"DnsOptions": null,
 			"DnsSearch": null,
 			"DnsSearch": null,
 			"ExtraHosts": null,
 			"ExtraHosts": null,
 			"IpcMode": "",
 			"IpcMode": "",

+ 1 - 0
docs/reference/commandline/create.md

@@ -31,6 +31,7 @@ Creates a new container.
       --cpuset-mems=""              Memory nodes (MEMs) in which to allow execution (0-3, 0,1)
       --cpuset-mems=""              Memory nodes (MEMs) in which to allow execution (0-3, 0,1)
       --device=[]                   Add a host device to the container
       --device=[]                   Add a host device to the container
       --dns=[]                      Set custom DNS servers
       --dns=[]                      Set custom DNS servers
+      --dns-opt=[]                  Set custom DNS options
       --dns-search=[]               Set custom DNS search domains
       --dns-search=[]               Set custom DNS search domains
       -e, --env=[]                  Set environment variables
       -e, --env=[]                  Set environment variables
       --entrypoint=""               Overwrite the default ENTRYPOINT of the image
       --entrypoint=""               Overwrite the default ENTRYPOINT of the image

+ 1 - 0
docs/reference/commandline/daemon.md

@@ -23,6 +23,7 @@ weight=1
       --default-gateway=""                   Container default gateway IPv4 address
       --default-gateway=""                   Container default gateway IPv4 address
       --default-gateway-v6=""                Container default gateway IPv6 address
       --default-gateway-v6=""                Container default gateway IPv6 address
       --dns=[]                               DNS server to use
       --dns=[]                               DNS server to use
+      --dns-opt=[]                           DNS options to use
       --dns-search=[]                        DNS search domains to use
       --dns-search=[]                        DNS search domains to use
       --default-ulimit=[]                    Set default ulimit settings for containers
       --default-ulimit=[]                    Set default ulimit settings for containers
       -e, --exec-driver="native"             Exec driver to use
       -e, --exec-driver="native"             Exec driver to use

+ 1 - 0
docs/reference/commandline/run.md

@@ -30,6 +30,7 @@ weight=1
       -d, --detach=false            Run container in background and print container ID
       -d, --detach=false            Run container in background and print container ID
       --device=[]                   Add a host device to the container
       --device=[]                   Add a host device to the container
       --dns=[]                      Set custom DNS servers
       --dns=[]                      Set custom DNS servers
+      --dns-opt=[]                  Set custom DNS options
       --dns-search=[]               Set custom DNS search domains
       --dns-search=[]               Set custom DNS search domains
       -e, --env=[]                  Set environment variables
       -e, --env=[]                  Set environment variables
       --entrypoint=""               Overwrite the default ENTRYPOINT of the image
       --entrypoint=""               Overwrite the default ENTRYPOINT of the image

+ 5 - 5
docs/reference/run.md

@@ -330,8 +330,8 @@ traffic will be routed though this bridge to the container.
 With the networking mode set to `host` a container will share the host's
 With the networking mode set to `host` a container will share the host's
 network stack and all interfaces from the host will be available to the
 network stack and all interfaces from the host will be available to the
 container.  The container's hostname will match the hostname on the host
 container.  The container's hostname will match the hostname on the host
-system.  Note that `--add-host` `--hostname`  `--dns` `--dns-search` and
-`--mac-address` is invalid in `host` netmode.
+system.  Note that `--add-host` `--hostname`  `--dns` `--dns-search`
+`--dns-opt` and `--mac-address` are invalid in `host` netmode.
 
 
 Compared to the default `bridge` mode, the `host` mode gives *significantly*
 Compared to the default `bridge` mode, the `host` mode gives *significantly*
 better networking performance since it uses the host's native networking stack
 better networking performance since it uses the host's native networking stack
@@ -348,9 +348,9 @@ or a High Performance Web Server.
 With the networking mode set to `container` a container will share the
 With the networking mode set to `container` a container will share the
 network stack of another container.  The other container's name must be
 network stack of another container.  The other container's name must be
 provided in the format of `--net container:<name|id>`. Note that `--add-host`
 provided in the format of `--net container:<name|id>`. Note that `--add-host`
-`--hostname` `--dns` `--dns-search` and `--mac-address` is invalid
-in `container` netmode, and `--publish` `--publish-all` `--expose` are also
-invalid in `container` netmode.
+`--hostname` `--dns` `--dns-search` `--dns-opt` and `--mac-address` are
+invalid in `container` netmode, and `--publish` `--publish-all` `--expose` are
+also invalid in `container` netmode.
 
 
 Example running a Redis container with Redis binding to `localhost` then
 Example running a Redis container with Redis binding to `localhost` then
 running the `redis-cli` command and connecting to the Redis server over the
 running the `redis-cli` command and connecting to the Redis server over the

+ 16 - 6
integration-cli/docker_cli_run_test.go

@@ -940,7 +940,7 @@ func (s *DockerSuite) TestRunDnsDefaultOptions(c *check.C) {
 
 
 func (s *DockerSuite) TestRunDnsOptions(c *check.C) {
 func (s *DockerSuite) TestRunDnsOptions(c *check.C) {
 	testRequires(c, DaemonIsLinux)
 	testRequires(c, DaemonIsLinux)
-	out, stderr, _ := dockerCmdWithStdoutStderr(c, "run", "--dns=127.0.0.1", "--dns-search=mydomain", "busybox", "cat", "/etc/resolv.conf")
+	out, stderr, _ := dockerCmdWithStdoutStderr(c, "run", "--dns=127.0.0.1", "--dns-search=mydomain", "--dns-opt=ndots:9", "busybox", "cat", "/etc/resolv.conf")
 
 
 	// The client will get a warning on stderr when setting DNS to a localhost address; verify this:
 	// The client will get a warning on stderr when setting DNS to a localhost address; verify this:
 	if !strings.Contains(stderr, "Localhost DNS setting") {
 	if !strings.Contains(stderr, "Localhost DNS setting") {
@@ -948,15 +948,25 @@ func (s *DockerSuite) TestRunDnsOptions(c *check.C) {
 	}
 	}
 
 
 	actual := strings.Replace(strings.Trim(out, "\r\n"), "\n", " ", -1)
 	actual := strings.Replace(strings.Trim(out, "\r\n"), "\n", " ", -1)
-	if actual != "search mydomain nameserver 127.0.0.1" {
-		c.Fatalf("expected 'nameserver 127.0.0.1 search mydomain', but says: %q", actual)
+	if actual != "search mydomain nameserver 127.0.0.1 options ndots:9" {
+		c.Fatalf("expected 'search mydomain nameserver 127.0.0.1 options ndots:9', but says: %q", actual)
 	}
 	}
 
 
-	out, stderr, _ = dockerCmdWithStdoutStderr(c, "run", "--dns=127.0.0.1", "--dns-search=.", "busybox", "cat", "/etc/resolv.conf")
+	out, stderr, _ = dockerCmdWithStdoutStderr(c, "run", "--dns=127.0.0.1", "--dns-search=.", "--dns-opt=ndots:3", "busybox", "cat", "/etc/resolv.conf")
 
 
 	actual = strings.Replace(strings.Trim(strings.Trim(out, "\r\n"), " "), "\n", " ", -1)
 	actual = strings.Replace(strings.Trim(strings.Trim(out, "\r\n"), " "), "\n", " ", -1)
-	if actual != "nameserver 127.0.0.1" {
-		c.Fatalf("expected 'nameserver 127.0.0.1', but says: %q", actual)
+	if actual != "nameserver 127.0.0.1 options ndots:3" {
+		c.Fatalf("expected 'nameserver 127.0.0.1 options ndots:3', but says: %q", actual)
+	}
+}
+
+func (s *DockerSuite) TestRunDnsRepeatOptions(c *check.C) {
+	testRequires(c, DaemonIsLinux)
+	out, _, _ := dockerCmdWithStdoutStderr(c, "run", "--dns=1.1.1.1", "--dns=2.2.2.2", "--dns-search=mydomain", "--dns-search=mydomain2", "--dns-opt=ndots:9", "--dns-opt=timeout:3", "busybox", "cat", "/etc/resolv.conf")
+
+	actual := strings.Replace(strings.Trim(out, "\r\n"), "\n", " ", -1)
+	if actual != "search mydomain mydomain2 nameserver 1.1.1.1 nameserver 2.2.2.2 options ndots:9 timeout:3" {
+		c.Fatalf("expected 'search mydomain mydomain2 nameserver 1.1.1.1 nameserver 2.2.2.2 options ndots:9 timeout:3', but says: %q", actual)
 	}
 	}
 }
 }
 
 

+ 4 - 0
man/docker-create.1.md

@@ -21,6 +21,7 @@ docker-create - Create a new container
 [**--device**[=*[]*]]
 [**--device**[=*[]*]]
 [**--dns**[=*[]*]]
 [**--dns**[=*[]*]]
 [**--dns-search**[=*[]*]]
 [**--dns-search**[=*[]*]]
+[**--dns-opt**[=*[]*]]
 [**-e**|**--env**[=*[]*]]
 [**-e**|**--env**[=*[]*]]
 [**--entrypoint**[=*ENTRYPOINT*]]
 [**--entrypoint**[=*ENTRYPOINT*]]
 [**--env-file**[=*[]*]]
 [**--env-file**[=*[]*]]
@@ -118,6 +119,9 @@ two memory nodes.
 **--dns**=[]
 **--dns**=[]
    Set custom DNS servers
    Set custom DNS servers
 
 
+**--dns-opt**=[]
+   Set custom DNS options
+
 **--dns-search**=[]
 **--dns-search**=[]
    Set custom DNS search domains (Use --dns-search=. if you don't wish to set the search domain)
    Set custom DNS search domains (Use --dns-search=. if you don't wish to set the search domain)
 
 

+ 1 - 0
man/docker-inspect.1.md

@@ -123,6 +123,7 @@ To get information on a container use its ID or instance name:
         "PublishAllPorts": false,
         "PublishAllPorts": false,
         "Dns": null,
         "Dns": null,
         "DnsSearch": null,
         "DnsSearch": null,
+        "DnsOptions": null,
         "ExtraHosts": null,
         "ExtraHosts": null,
         "VolumesFrom": null,
         "VolumesFrom": null,
         "Devices": [],
         "Devices": [],

+ 4 - 0
man/docker-run.1.md

@@ -21,6 +21,7 @@ docker-run - Run a command in a new container
 [**-d**|**--detach**[=*false*]]
 [**-d**|**--detach**[=*false*]]
 [**--device**[=*[]*]]
 [**--device**[=*[]*]]
 [**--dns**[=*[]*]]
 [**--dns**[=*[]*]]
+[**--dns-opt**[=*[]*]]
 [**--dns-search**[=*[]*]]
 [**--dns-search**[=*[]*]]
 [**-e**|**--env**[=*[]*]]
 [**-e**|**--env**[=*[]*]]
 [**--entrypoint**[=*ENTRYPOINT*]]
 [**--entrypoint**[=*ENTRYPOINT*]]
@@ -185,6 +186,9 @@ stopping the process by pressing the keys CTRL-P CTRL-Q.
 **--dns-search**=[]
 **--dns-search**=[]
    Set custom DNS search domains (Use --dns-search=. if you don't wish to set the search domain)
    Set custom DNS search domains (Use --dns-search=. if you don't wish to set the search domain)
 
 
+**--dns-opt**=[]
+   Set custom DNS options
+
 **--dns**=[]
 **--dns**=[]
    Set custom DNS servers
    Set custom DNS servers
 
 

+ 3 - 0
man/docker.1.md

@@ -56,6 +56,9 @@ To see the man page for a command run **man docker <command>**.
 **--dns**=""
 **--dns**=""
   Force Docker to use specific DNS servers
   Force Docker to use specific DNS servers
 
 
+**--dns-opt**=[]
+  DNS options to use.
+
 **--dns-search**=[]
 **--dns-search**=[]
   DNS search domains to use.
   DNS search domains to use.
 
 

+ 1 - 0
runconfig/fixtures/container_config_1_17.json

@@ -38,6 +38,7 @@
        "ReadonlyRootfs": false,
        "ReadonlyRootfs": false,
        "Dns": ["8.8.8.8"],
        "Dns": ["8.8.8.8"],
        "DnsSearch": [""],
        "DnsSearch": [""],
+       "DnsOptions": [""],
        "ExtraHosts": null,
        "ExtraHosts": null,
        "VolumesFrom": ["parent", "other:ro"],
        "VolumesFrom": ["parent", "other:ro"],
        "CapAdd": ["NET_ADMIN"],
        "CapAdd": ["NET_ADMIN"],

+ 1 - 0
runconfig/fixtures/container_config_1_19.json

@@ -42,6 +42,7 @@
        "ReadonlyRootfs": false,
        "ReadonlyRootfs": false,
        "Dns": ["8.8.8.8"],
        "Dns": ["8.8.8.8"],
        "DnsSearch": [""],
        "DnsSearch": [""],
+       "DnsOptions": [""],
        "ExtraHosts": null,
        "ExtraHosts": null,
        "VolumesFrom": ["parent", "other:ro"],
        "VolumesFrom": ["parent", "other:ro"],
        "CapAdd": ["NET_ADMIN"],
        "CapAdd": ["NET_ADMIN"],

+ 3 - 2
runconfig/hostconfig.go

@@ -232,8 +232,9 @@ type HostConfig struct {
 	PortBindings     nat.PortMap           // Port mapping between the exposed port (container) and the host
 	PortBindings     nat.PortMap           // Port mapping between the exposed port (container) and the host
 	Links            []string              // List of links (in the name:alias form)
 	Links            []string              // List of links (in the name:alias form)
 	PublishAllPorts  bool                  // Should docker publish all exposed port for the container
 	PublishAllPorts  bool                  // Should docker publish all exposed port for the container
-	DNS              []string              `json:"Dns"`       // List of DNS server to lookup
-	DNSSearch        []string              `json:"DnsSearch"` // List of DNSSearch to look for
+	DNS              []string              `json:"Dns"`        // List of DNS server to lookup
+	DNSOptions       []string              `json:"DnsOptions"` // List of DNSOption to look for
+	DNSSearch        []string              `json:"DnsSearch"`  // List of DNSSearch to look for
 	ExtraHosts       []string              // List of extra hosts
 	ExtraHosts       []string              // List of extra hosts
 	VolumesFrom      []string              // List of volumes to take from other container
 	VolumesFrom      []string              // List of volumes to take from other container
 	Devices          []DeviceMapping       // List of devices to map inside the container
 	Devices          []DeviceMapping       // List of devices to map inside the container

+ 3 - 0
runconfig/parse.go

@@ -52,6 +52,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
 		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)
+		flDNSOptions  = opts.NewListOpts(nil)
 		flExtraHosts  = opts.NewListOpts(opts.ValidateExtraHost)
 		flExtraHosts  = opts.NewListOpts(opts.ValidateExtraHost)
 		flVolumesFrom = opts.NewListOpts(nil)
 		flVolumesFrom = opts.NewListOpts(nil)
 		flLxcOpts     = opts.NewListOpts(nil)
 		flLxcOpts     = opts.NewListOpts(nil)
@@ -109,6 +110,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
 	cmd.Var(&flExpose, []string{"#expose", "-expose"}, "Expose a port or a range of ports")
 	cmd.Var(&flExpose, []string{"#expose", "-expose"}, "Expose a port or a range of ports")
 	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(&flDNSOptions, []string{"-dns-opt"}, "Set DNS options")
 	cmd.Var(&flExtraHosts, []string{"-add-host"}, "Add a custom host-to-IP mapping (host:ip)")
 	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"}, "Add custom lxc options")
 	cmd.Var(&flLxcOpts, []string{"#lxc-conf", "-lxc-conf"}, "Add custom lxc options")
@@ -347,6 +349,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
 		PublishAllPorts:  *flPublishAll,
 		PublishAllPorts:  *flPublishAll,
 		DNS:              flDNS.GetAll(),
 		DNS:              flDNS.GetAll(),
 		DNSSearch:        flDNSSearch.GetAll(),
 		DNSSearch:        flDNSSearch.GetAll(),
+		DNSOptions:       flDNSOptions.GetAll(),
 		ExtraHosts:       flExtraHosts.GetAll(),
 		ExtraHosts:       flExtraHosts.GetAll(),
 		VolumesFrom:      flVolumesFrom.GetAll(),
 		VolumesFrom:      flVolumesFrom.GetAll(),
 		NetworkMode:      NetworkMode(*flNetMode),
 		NetworkMode:      NetworkMode(*flNetMode),