Repository: docker/docker-py

Issue:
networks argument to containers.run()
I am doing:

```
api.containers.run(
    ...,
    networks=['foo']
)
```

This has no effect. The container will instead be part of the default bridge. 

The command apparently sends this to the API:

```
{...,
'NetworkingConfig': {'foo': None}
}
```

What is the correct way to use this?


Discussion:
Hi,

Unfortunately that looks like a bug on our end. I believe you should be able to do the same thing using the `network_mode` parameter, i.e

```python
api.containers.run(
  ...
  network_mode='foo'
)
```

Hope that helps
Was affected by this bug/unexpected usage today but @shin-'s suggestion worked.


````
import docker

client = docker.from_env()

network = client.networks.create("mynetwork")

#Expected to work but does not
#c1 = client.containers.run('alpine', 'echo hello', detach=True, name="c1", networks=[network.name])
#c2 = client.containers.run('alpine', 'echo hello', detach=True, name="c2", networks=[network.name])

#Does work
c1 = client.containers.run('alpine', 'echo hello', detach=True, name="c1", network_mode=network.name)
c2 = client.containers.run('alpine', 'echo hello', detach=True, name="c2", network_mode=network.name)

network.reload()
print network.containers
````

Resolving patch:
diff --git a/docker/models/containers.py b/docker/models/containers.py
--- a/docker/models/containers.py
+++ b/docker/models/containers.py
@@ -147,7 +147,7 @@ def exec_run(self, cmd, stdout=True, stderr=True, stdin=False, tty=False,
 
         Returns:
             (generator or str): If ``stream=True``, a generator yielding
-            response chunks. A string containing response data otherwise.
+                response chunks. A string containing response data otherwise.
 
         Raises:
             :py:class:`docker.errors.APIError`
@@ -546,10 +546,12 @@ def run(self, image, command=None, stdout=True, stderr=False,
                 behavior. Accepts number between 0 and 100.
             memswap_limit (str or int): Maximum amount of memory + swap a
                 container is allowed to consume.
-            networks (:py:class:`list`): A list of network names to connect
-                this container to.
             name (str): The name for this container.
             nano_cpus (int):  CPU quota in units of 10-9 CPUs.
+            network (str): Name of the network this container will be connected
+                to at creation time. You can connect to additional networks
+                using :py:meth:`Network.connect`. Incompatible with
+                ``network_mode``.
             network_disabled (bool): Disable networking.
             network_mode (str): One of:
 
@@ -559,6 +561,7 @@ def run(self, image, command=None, stdout=True, stderr=False,
                 - ``container:<name|id>`` Reuse another container's network
                   stack.
                 - ``host`` Use the host network stack.
+                Incompatible with ``network``.
             oom_kill_disable (bool): Whether to disable OOM killer.
             oom_score_adj (int): An integer value containing the score given
                 to the container in order to tune OOM killer preferences.
@@ -680,6 +683,12 @@ def run(self, image, command=None, stdout=True, stderr=False,
             raise RuntimeError("The options 'detach' and 'remove' cannot be "
                                "used together.")
 
+        if kwargs.get('network') and kwargs.get('network_mode'):
+            raise RuntimeError(
+                'The options "network" and "network_mode" can not be used '
+                'together.'
+            )
+
         try:
             container = self.create(image=image, command=command,
                                     detach=detach, **kwargs)
@@ -902,10 +911,10 @@ def _create_container_args(kwargs):
     if volumes:
         host_config_kwargs['binds'] = volumes
 
-    networks = kwargs.pop('networks', [])
-    if networks:
-        create_kwargs['networking_config'] = {network: None
-                                              for network in networks}
+    network = kwargs.pop('network', None)
+    if network:
+        create_kwargs['networking_config'] = {network: None}
+        host_config_kwargs['network_mode'] = network
 
     # All kwargs should have been consumed by this point, so raise
     # error if any are left
diff --git a/docker/models/plugins.py b/docker/models/plugins.py
--- a/docker/models/plugins.py
+++ b/docker/models/plugins.py
@@ -103,8 +103,8 @@ def upgrade(self, remote=None):
 
             Args:
                 remote (string): Remote reference to upgrade to. The
-                ``:latest`` tag is optional and is the default if omitted.
-                Default: this plugin's name.
+                    ``:latest`` tag is optional and is the default if omitted.
+                    Default: this plugin's name.
 
             Returns:
                 A generator streaming the decoded API logs
diff --git a/docker/types/services.py b/docker/types/services.py
--- a/docker/types/services.py
+++ b/docker/types/services.py
@@ -127,7 +127,7 @@ def __init__(self, image, command=None, args=None, hostname=None, env=None,
 class Mount(dict):
     """
     Describes a mounted folder's configuration inside a container. A list of
-    :py:class:`Mount`s would be used as part of a
+    :py:class:`Mount` would be used as part of a
     :py:class:`~docker.types.ContainerSpec`.
 
     Args:


Test patch:
diff --git a/tests/integration/models_containers_test.py b/tests/integration/models_containers_test.py
--- a/tests/integration/models_containers_test.py
+++ b/tests/integration/models_containers_test.py
@@ -1,6 +1,7 @@
 import docker
 import tempfile
 from .base import BaseIntegrationTest, TEST_API_VERSION
+from ..helpers import random_name
 
 
 class ContainerCollectionTest(BaseIntegrationTest):
@@ -69,6 +70,24 @@ def test_run_with_named_volume(self):
         )
         self.assertEqual(out, b'hello\n')
 
+    def test_run_with_network(self):
+        net_name = random_name()
+        client = docker.from_env(version=TEST_API_VERSION)
+        client.networks.create(net_name)
+        self.tmp_networks.append(net_name)
+
+        container = client.containers.run(
+            'alpine', 'echo hello world', network=net_name,
+            detach=True
+        )
+        self.tmp_containers.append(container.id)
+
+        attrs = container.attrs
+
+        assert 'NetworkSettings' in attrs
+        assert 'Networks' in attrs['NetworkSettings']
+        assert list(attrs['NetworkSettings']['Networks'].keys()) == [net_name]
+
     def test_get(self):
         client = docker.from_env(version=TEST_API_VERSION)
         container = client.containers.run("alpine", "sleep 300", detach=True)
diff --git a/tests/unit/models_containers_test.py b/tests/unit/models_containers_test.py
--- a/tests/unit/models_containers_test.py
+++ b/tests/unit/models_containers_test.py
@@ -71,8 +71,7 @@ def test_create_container_args(self):
             memswap_limit=456,
             name='somename',
             network_disabled=False,
-            network_mode='blah',
-            networks=['foo'],
+            network='foo',
             oom_kill_disable=True,
             oom_score_adj=5,
             pid_mode='host',
@@ -153,7 +152,7 @@ def test_create_container_args(self):
                 'MemoryReservation': 123,
                 'MemorySwap': 456,
                 'MemorySwappiness': 2,
-                'NetworkMode': 'blah',
+                'NetworkMode': 'foo',
                 'OomKillDisable': True,
                 'OomScoreAdj': 5,
                 'PidMode': 'host',