Skip to content

Commit

Permalink
Add custom DNS settings to service definition
Browse files Browse the repository at this point in the history
This fix tries to fix the issue raised in 24391 about allowing
custom DNS settings to service definition.

This fix adds `DNSConfig` (`Nameservers`, `Options`, `Search`) to
service definition, as well as `--dns`, `--dns-opt`, and `dns-search`
to `service create`.

An integration test has been added to cover the changes in this fix.

This fix fixes 24391.

A PR in swarmkit will be created separately.

Signed-off-by: Yong Tang <[email protected]>
  • Loading branch information
yongtang committed Nov 8, 2016
1 parent 703dcbe commit 9e8adbe
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 11 deletions.
15 changes: 15 additions & 0 deletions api/types/swarm/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ import (
"github.com/docker/docker/api/types/mount"
)

// DNSConfig specifies DNS related configurations in resolver configuration file (resolv.conf)
// Detailed documentation is available in:
// http://man7.org/linux/man-pages/man5/resolv.conf.5.html
// `nameserver`, `search`, `options` have been supported.
// TODO: `domain` is not supported yet.
type DNSConfig struct {
// Nameservers specifies the IP addresses of the name servers
Nameservers []string `json:",omitempty"`
// Search specifies the search list for host-name lookup
Search []string `json:",omitempty"`
// Options allows certain internal resolver variables to be modified
Options []string `json:",omitempty"`
}

// ContainerSpec represents the spec of a container.
type ContainerSpec struct {
Image string `json:",omitempty"`
Expand All @@ -22,4 +36,5 @@ type ContainerSpec struct {
Mounts []mount.Mount `json:",omitempty"`
StopGracePeriod *time.Duration `json:",omitempty"`
Healthcheck *container.HealthConfig `json:",omitempty"`
DNSConfig *DNSConfig `json:",omitempty"`
}
3 changes: 3 additions & 0 deletions cli/command/service/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ func newCreateCommand(dockerCli *command.DockerCli) *cobra.Command {
flags.StringSliceVar(&opts.networks, flagNetwork, []string{}, "Network attachments")
flags.VarP(&opts.endpoint.ports, flagPublish, "p", "Publish a port as a node port")
flags.StringSliceVar(&opts.groups, flagGroup, []string{}, "Set one or more supplementary user groups for the container")
flags.Var(&opts.dns, flagDNS, "Set custom DNS servers")
flags.Var(&opts.dnsOptions, flagDNSOptions, "Set DNS options")
flags.Var(&opts.dnsSearch, flagDNSSearch, "Set custom DNS search domains")

flags.SetInterspersed(false)
return cmd
Expand Down
36 changes: 25 additions & 11 deletions cli/command/service/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,9 @@ type serviceOptions struct {
groups []string
tty bool
mounts opts.MountOpt
dns opts.ListOpts
dnsSearch opts.ListOpts
dnsOptions opts.ListOpts

resources resourceOptions
stopGrace DurationOpt
Expand Down Expand Up @@ -325,7 +328,10 @@ func newServiceOptions() *serviceOptions {
endpoint: endpointOptions{
ports: opts.NewListOpts(ValidatePort),
},
logDriver: newLogDriverOptions(),
logDriver: newLogDriverOptions(),
dns: opts.NewListOpts(opts.ValidateIPAddress),
dnsOptions: opts.NewListOpts(nil),
dnsSearch: opts.NewListOpts(opts.ValidateDNSSearch),
}
}

Expand Down Expand Up @@ -358,16 +364,21 @@ func (opts *serviceOptions) ToService() (swarm.ServiceSpec, error) {
},
TaskTemplate: swarm.TaskSpec{
ContainerSpec: swarm.ContainerSpec{
Image: opts.image,
Args: opts.args,
Env: currentEnv,
Hostname: opts.hostname,
Labels: runconfigopts.ConvertKVStringsToMap(opts.containerLabels.GetAll()),
Dir: opts.workdir,
User: opts.user,
Groups: opts.groups,
TTY: opts.tty,
Mounts: opts.mounts.Value(),
Image: opts.image,
Args: opts.args,
Env: currentEnv,
Hostname: opts.hostname,
Labels: runconfigopts.ConvertKVStringsToMap(opts.containerLabels.GetAll()),
Dir: opts.workdir,
User: opts.user,
Groups: opts.groups,
TTY: opts.tty,
Mounts: opts.mounts.Value(),
DNSConfig: &swarm.DNSConfig{
Nameservers: opts.dns.GetAll(),
Search: opts.dnsSearch.GetAll(),
Options: opts.dnsOptions.GetAll(),
},
StopGracePeriod: opts.stopGrace.Value(),
},
Networks: convertNetworks(opts.networks),
Expand Down Expand Up @@ -463,6 +474,9 @@ const (
flagContainerLabel = "container-label"
flagContainerLabelRemove = "container-label-rm"
flagContainerLabelAdd = "container-label-add"
flagDNS = "dns"
flagDNSOptions = "dns-opt"
flagDNSSearch = "dns-search"
flagEndpointMode = "endpoint-mode"
flagHostname = "hostname"
flagEnv = "env"
Expand Down
16 changes: 16 additions & 0 deletions daemon/cluster/convert/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ func containerSpecFromGRPC(c *swarmapi.ContainerSpec) types.ContainerSpec {
TTY: c.TTY,
}

if c.DNSConfig != nil {
containerSpec.DNSConfig = &types.DNSConfig{
Nameservers: c.DNSConfig.Nameservers,
Search: c.DNSConfig.Search,
Options: c.DNSConfig.Options,
}
}

// Mounts
for _, m := range c.Mounts {
mount := mounttypes.Mount{
Expand Down Expand Up @@ -81,6 +89,14 @@ func containerToGRPC(c types.ContainerSpec) (*swarmapi.ContainerSpec, error) {
TTY: c.TTY,
}

if c.DNSConfig != nil {
containerSpec.DNSConfig = &swarmapi.ContainerSpec_DNSConfig{
Nameservers: c.DNSConfig.Nameservers,
Search: c.DNSConfig.Search,
Options: c.DNSConfig.Options,
}
}

if c.StopGracePeriod != nil {
containerSpec.StopGracePeriod = ptypes.DurationProto(*c.StopGracePeriod)
}
Expand Down
6 changes: 6 additions & 0 deletions daemon/cluster/executor/container/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,12 @@ func (c *containerConfig) hostConfig() *enginecontainer.HostConfig {
GroupAdd: c.spec().Groups,
}

if c.spec().DNSConfig != nil {
hc.DNS = c.spec().DNSConfig.Nameservers
hc.DNSSearch = c.spec().DNSConfig.Search
hc.DNSOptions = c.spec().DNSConfig.Options
}

if c.task.LogDriver != nil {
hc.LogConfig = enginecontainer.LogConfig{
Type: c.task.LogDriver.Name,
Expand Down
3 changes: 3 additions & 0 deletions docs/reference/commandline/service_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ Create a new service
Options:
--constraint value Placement constraints (default [])
--container-label value Service container labels (default [])
--dns list Set custom DNS servers (default [])
--dns-opt list Set DNS options (default [])
--dns-search list Set custom DNS search domains (default [])
--endpoint-mode string Endpoint mode (vip or dnsrr)
-e, --env value Set environment variables (default [])
--env-file value Read in a file of environment variables (default [])
Expand Down
27 changes: 27 additions & 0 deletions integration-cli/docker_cli_swarm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -789,3 +789,30 @@ func (s *DockerSwarmSuite) TestSwarmServiceTTYUpdate(c *check.C) {
c.Assert(err, checker.IsNil)
c.Assert(strings.TrimSpace(out), checker.Equals, "true")
}

func (s *DockerSwarmSuite) TestDNSConfig(c *check.C) {
d := s.AddDaemon(c, true, true)

// Create a service
name := "top"
_, err := d.Cmd("service", "create", "--name", name, "--dns=1.2.3.4", "--dns-search=example.com", "--dns-opt=timeout:3", "busybox", "top")
c.Assert(err, checker.IsNil)

// Make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, 1)

// We need to get the container id.
out, err := d.Cmd("ps", "-a", "-q", "--no-trunc")
c.Assert(err, checker.IsNil)
id := strings.TrimSpace(out)

// Compare against expected output.
expectedOutput1 := "nameserver 1.2.3.4"
expectedOutput2 := "search example.com"
expectedOutput3 := "options timeout:3"
out, err = d.Cmd("exec", id, "cat", "/etc/resolv.conf")
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, expectedOutput1, check.Commentf("Expected '%s', but got %q", expectedOutput1, out))
c.Assert(out, checker.Contains, expectedOutput2, check.Commentf("Expected '%s', but got %q", expectedOutput2, out))
c.Assert(out, checker.Contains, expectedOutput3, check.Commentf("Expected '%s', but got %q", expectedOutput3, out))
}

0 comments on commit 9e8adbe

Please sign in to comment.