From b222aa1a582f24d0164a72883e5f6503cc6a1d64 Mon Sep 17 00:00:00 2001
From: Nikolay Milovanov <nmil@itransformers.net>
Date: Thu, 27 Oct 2016 12:44:19 +0100
Subject: [PATCH] Adding the hostname option to docker service command

Signed-off-by: Nikolay Milovanov <nmil@itransformers.net>
---
 api/types/swarm/container.go                  |  1 +
 cli/command/service/create.go                 |  1 +
 cli/command/service/opts.go                   |  3 ++
 daemon/cluster/convert/container.go           | 34 ++++++++++---------
 .../cluster/executor/container/container.go   |  1 +
 docs/reference/commandline/service_create.md  |  7 ++++
 6 files changed, 31 insertions(+), 16 deletions(-)

diff --git a/api/types/swarm/container.go b/api/types/swarm/container.go
index 7ea87caa38..fe5fef5bae 100644
--- a/api/types/swarm/container.go
+++ b/api/types/swarm/container.go
@@ -13,6 +13,7 @@ type ContainerSpec struct {
 	Labels          map[string]string       `json:",omitempty"`
 	Command         []string                `json:",omitempty"`
 	Args            []string                `json:",omitempty"`
+	Hostname        string                  `json:",omitempty"`
 	Env             []string                `json:",omitempty"`
 	Dir             string                  `json:",omitempty"`
 	User            string                  `json:",omitempty"`
diff --git a/cli/command/service/create.go b/cli/command/service/create.go
index 28790ec8e6..430d448565 100644
--- a/cli/command/service/create.go
+++ b/cli/command/service/create.go
@@ -33,6 +33,7 @@ func newCreateCommand(dockerCli *command.DockerCli) *cobra.Command {
 
 	flags.VarP(&opts.labels, flagLabel, "l", "Service labels")
 	flags.Var(&opts.containerLabels, flagContainerLabel, "Container labels")
+	flags.StringVar(&opts.hostname, flagHostname, "", "Container hostname")
 	flags.VarP(&opts.env, flagEnv, "e", "Set environment variables")
 	flags.Var(&opts.envFile, flagEnvFile, "Read in a file of environment variables")
 	flags.Var(&opts.mounts, flagMount, "Attach a mount to the service")
diff --git a/cli/command/service/opts.go b/cli/command/service/opts.go
index 43b7b671cb..a134327356 100644
--- a/cli/command/service/opts.go
+++ b/cli/command/service/opts.go
@@ -455,6 +455,7 @@ type serviceOptions struct {
 	containerLabels opts.ListOpts
 	image           string
 	args            []string
+	hostname        string
 	env             opts.ListOpts
 	envFile         opts.ListOpts
 	workdir         string
@@ -526,6 +527,7 @@ func (opts *serviceOptions) ToService() (swarm.ServiceSpec, error) {
 				Image:           opts.image,
 				Args:            opts.args,
 				Env:             currentEnv,
+				Hostname:        opts.hostname,
 				Labels:          runconfigopts.ConvertKVStringsToMap(opts.containerLabels.GetAll()),
 				Dir:             opts.workdir,
 				User:            opts.user,
@@ -625,6 +627,7 @@ const (
 	flagContainerLabelRemove  = "container-label-rm"
 	flagContainerLabelAdd     = "container-label-add"
 	flagEndpointMode          = "endpoint-mode"
+	flagHostname              = "hostname"
 	flagEnv                   = "env"
 	flagEnvFile               = "env-file"
 	flagEnvRemove             = "env-rm"
diff --git a/daemon/cluster/convert/container.go b/daemon/cluster/convert/container.go
index 36c4aed52f..5e0cd3c49d 100644
--- a/daemon/cluster/convert/container.go
+++ b/daemon/cluster/convert/container.go
@@ -13,14 +13,15 @@ import (
 
 func containerSpecFromGRPC(c *swarmapi.ContainerSpec) types.ContainerSpec {
 	containerSpec := types.ContainerSpec{
-		Image:   c.Image,
-		Labels:  c.Labels,
-		Command: c.Command,
-		Args:    c.Args,
-		Env:     c.Env,
-		Dir:     c.Dir,
-		User:    c.User,
-		Groups:  c.Groups,
+		Image:    c.Image,
+		Labels:   c.Labels,
+		Command:  c.Command,
+		Args:     c.Args,
+		Hostname: c.Hostname,
+		Env:      c.Env,
+		Dir:      c.Dir,
+		User:     c.User,
+		Groups:   c.Groups,
 	}
 
 	// Mounts
@@ -67,14 +68,15 @@ func containerSpecFromGRPC(c *swarmapi.ContainerSpec) types.ContainerSpec {
 
 func containerToGRPC(c types.ContainerSpec) (*swarmapi.ContainerSpec, error) {
 	containerSpec := &swarmapi.ContainerSpec{
-		Image:   c.Image,
-		Labels:  c.Labels,
-		Command: c.Command,
-		Args:    c.Args,
-		Env:     c.Env,
-		Dir:     c.Dir,
-		User:    c.User,
-		Groups:  c.Groups,
+		Image:    c.Image,
+		Labels:   c.Labels,
+		Command:  c.Command,
+		Args:     c.Args,
+		Hostname: c.Hostname,
+		Env:      c.Env,
+		Dir:      c.Dir,
+		User:     c.User,
+		Groups:   c.Groups,
 	}
 
 	if c.StopGracePeriod != nil {
diff --git a/daemon/cluster/executor/container/container.go b/daemon/cluster/executor/container/container.go
index 10b2a371f7..fb0ab489d2 100644
--- a/daemon/cluster/executor/container/container.go
+++ b/daemon/cluster/executor/container/container.go
@@ -128,6 +128,7 @@ func (c *containerConfig) config() *enginecontainer.Config {
 	config := &enginecontainer.Config{
 		Labels:      c.labels(),
 		User:        c.spec().User,
+		Hostname:    c.spec().Hostname,
 		Env:         c.spec().Env,
 		WorkingDir:  c.spec().Dir,
 		Image:       c.image(),
diff --git a/docs/reference/commandline/service_create.md b/docs/reference/commandline/service_create.md
index 3406ad68a0..9f0d5a83b7 100644
--- a/docs/reference/commandline/service_create.md
+++ b/docs/reference/commandline/service_create.md
@@ -32,6 +32,7 @@ Options:
       --health-retries int               Consecutive failures needed to report unhealthy
       --health-timeout duration          Maximum time to allow one check to run
       --help                             Print usage
+      --hostname                         Service containers hostname
   -l, --label value                      Service labels (default [])
       --limit-cpu value                  Limit CPUs (default 0.000)
       --limit-memory value               Limit Memory (default 0 B)
@@ -134,6 +135,12 @@ This sets environmental variables for all tasks in a service. For example:
 $ docker service create --name redis_2 --replicas 5 --env MYVAR=foo redis:3.0.6
 ```
 
+### Create a docker service with specific hostname (--hostname)
+
+This option sets the docker service containers hostname to a specific string. For example:
+```bash
+$ docker service create --name redis --hostname myredis redis:3.0.6
+```
 ### Set metadata on a service (-l, --label)
 
 A label is a `key=value` pair that applies metadata to a service. To label a