Repository: docker/docker-py
Issue: swarm services: extra_hosts set in wrong format

Dear all,
we encounter issues with setting `extra_hosts` for swarm services on docker-py 2.6.1

```
docker version
Client:
 Version:      17.06.2-ce
 API version:  1.30
 Go version:   go1.8.3
 Git commit:   cec0b72
 Built:        Tue Sep  5 19:59:06 2017
 OS/Arch:      linux/amd64

Server:
 Version:      17.06.2-ce
 API version:  1.30 (minimum version 1.12)
 Go version:   go1.8.3
 Git commit:   cec0b72
 Built:        Tue Sep  5 20:00:25 2017
 OS/Arch:      linux/amd64
 Experimental: false
```
**What we do**
```
extra_hosts = dict()
extra_hosts.update({'domain.com': '8.8.8.8'})
client.services.create(name='myservice', image='nginx', hosts=extra_hosts)
```

**Result**
The entry is not found in `/etc/hosts` in the container.
The attribute `Hosts` of the service's `ContainerSpec` shows the following syntax: `domain.com:8.8.8.8`
However, the syntax should have been `8.8.8.8 domain.com`

**Analysis**
docker-py uses this line to format `extra_hosts` (https://github.com/docker/docker-py/blob/2.6.1/docker/utils/utils.py#L569):
```
 '{}:{}'.format(k, v) for k, v in sorted(six.iteritems(extra_hosts))
```

According to swarm's API (https://github.com/moby/moby/blob/d91c5f42eb37c6f88cec4021c10c0a1ded1785c3/api/types/swarm/container.go#L65), the ContainerSpec of a TaskSpec expects `extra_hosts` in the format described per http://man7.org/linux/man-pages/man5/hosts.5.html which is:
```
IP HostnameA
```

**Workaround**
Currently, we compensate this as follows:
```
create_service_kwargs = docker.models.services._get_create_service_kwargs(...)
create_service_kwargs['task_template']['ContainerSpec']['Hosts'] = ['8.8.8.8 domain.com']
client.api.create_service(**create_service_kwargs)
```

Maybe you can comment on this.

Thanks and Regards,
Stephen

Changed files:
tests/integration/api_service_test.py, docker/utils/utils.py, docker/types/services.py

diff --git a/docker/types/services.py b/docker/types/services.py
index 9031e609..5b6af8f5 100644
--- a/docker/types/services.py
+++ b/docker/types/services.py
@@ -137,7 +137,7 @@ class ContainerSpec(dict):
         if labels is not None:
             self['Labels'] = labels
         if hosts is not None:
-            self['Hosts'] = format_extra_hosts(hosts)
+            self['Hosts'] = format_extra_hosts(hosts, task=True)
 
         if mounts is not None:
             parsed_mounts = []
diff --git a/docker/utils/utils.py b/docker/utils/utils.py
index a123fd8f..845af653 100644
--- a/docker/utils/utils.py
+++ b/docker/utils/utils.py
@@ -564,7 +564,13 @@ def format_environment(environment):
     return [format_env(*var) for var in six.iteritems(environment)]
 
 
-def format_extra_hosts(extra_hosts):
+def format_extra_hosts(extra_hosts, task=False):
+    # Use format dictated by Swarm API if container is part of a task
+    if task:
+        return [
+            '{} {}'.format(v, k) for k, v in sorted(six.iteritems(extra_hosts))
+        ]
+
     return [
         '{}:{}'.format(k, v) for k, v in sorted(six.iteritems(extra_hosts))
     ]
diff --git a/tests/integration/api_service_test.py b/tests/integration/api_service_test.py
index b9311549..05b5ba75 100644
--- a/tests/integration/api_service_test.py
+++ b/tests/integration/api_service_test.py
@@ -588,8 +588,8 @@ class ServiceTest(BaseAPIIntegrationTest):
         assert 'Hosts' in svc_info['Spec']['TaskTemplate']['ContainerSpec']
         hosts = svc_info['Spec']['TaskTemplate']['ContainerSpec']['Hosts']
         assert len(hosts) == 2
-        assert 'foobar:127.0.0.1' in hosts
-        assert 'baz:8.8.8.8' in hosts
+        assert '127.0.0.1 foobar' in hosts
+        assert '8.8.8.8 baz' in hosts
 
     @requires_api_version('1.25')
     def test_create_service_with_hostname(self):