Repository: docker/docker-py

Issue:
Can't create and bind mounts
Debugging the go client I've found out the combination it uses to bind mounts in the container to the host.

Here is the command of the docker command-line client:

``` sh
docker run -b "/host/path:/mnt" image-name ls /mnt
```

The container must be created with volumes:

``` python
container = client.create_container(image_id, command, volumes={'/mnt': {}})
```

And started binding the volume to the host. Here is a sample code to allow posting json when starting the container (the current implementation of the `start` method can't do this):

``` python
url = client._url("/containers/{0}/start".format(id_do_container))
res = client.post_json(url, {"Binds": ['/host/path:/mnt']}, headers={"Content-Type":"application/json"})
```

Here is the `start` api documentation:
http://docs.docker.io/en/latest/api/docker_remote_api_v1.3/#start-a-container

Couldn't find any documentation of the complete procedure for binding a mount.



Discussion:

Resolving patch:
diff --git a/docker/client.py b/docker/client.py
--- a/docker/client.py
+++ b/docker/client.py
@@ -77,6 +77,9 @@ def post_json(self, url, data, **kwargs):
                 if v is not None:
                     data2[k] = v
 
+        if 'headers' not in kwargs:
+            kwargs['headers'] = {}
+        kwargs['headers']["Content-Type"] = "application/json"
         return self.post(url, json.dumps(data2), **kwargs)
 
     def attach(self, container):
@@ -99,8 +102,8 @@ def attach(self, container):
             else:
                 break
 
-    def build(self, dockerfile, tag=None, logger=None):
-        bc = BuilderClient(self, logger)
+    def build(self, dockerfile, tag=None, logger=None, follow_build_steps=False):
+        bc = BuilderClient(self, follow_build_steps, logger)
         img_id = None
         try:
             img_id = bc.build(dockerfile, tag=tag)
@@ -241,7 +244,7 @@ def logs(self, container):
     def port(self, container, private_port):
         res = self.get(self._url("/containers/{0}/json".format(container)))
         json_ = res.json()
-        return json_['NetworkSettings']['PortMapping'][private_port]
+        return json_['NetworkSettings']['PortMapping'][str(private_port)]
 
     def pull(self, repository, tag=None, registry=None):
         if repository.count(":") == 1:
@@ -285,10 +288,18 @@ def search(self, term):
         return self._result(self.get(self._url("/images/search"),
             params={'term': term}), True)
 
-    def start(self, *args):
+    def start(self, *args, **kwargs):
+        start_config = {}
+        binds = kwargs.pop('binds', '')
+        if binds:
+            bind_pairs = ['{0}:{1}'.format(host, dest) for host, dest in binds.items()]
+            start_config = {
+                'Binds': bind_pairs,
+            }
+
         for name in args:
             url = self._url("/containers/{0}/start".format(name))
-            self.post(url, None)
+            self.post_json(url, start_config)
 
     def stop(self, *args, **kwargs):
         params = {
@@ -326,8 +337,9 @@ def wait(self, *args):
 
 
 class BuilderClient(object):
-    def __init__(self, client, logger=None):
+    def __init__(self, client, follow_build_steps=False, logger=None):
         self.client = client
+        self.follow_build_steps = follow_build_steps
         self.tmp_containers = {}
         self.tmp_images = {}
         self.image = None
@@ -428,6 +440,9 @@ def run(self):
             for warning in container['Warnings']:
                 self.logger.warning(warning)
         self.client.start(container['Id'])
+        if self.follow_build_steps:
+            for log_line in self.client.attach(container['Id']):
+                self.logger.info(" {0}".format(log_line))
         self.tmp_containers[container['Id']] = {}
         status = self.client.wait(container['Id'])
         if status != 0:


Test patch:
diff --git a/tests/test.py b/tests/test.py
--- a/tests/test.py
+++ b/tests/test.py
@@ -1,3 +1,4 @@
+import os
 import six
 import unittest
 
@@ -97,6 +98,27 @@ def runTest(self):
         self.assertIn('Id', res)
         self.tmp_containers.append(res['Id'])
 
+class TestCreateContainerWithBinds(BaseTestCase):
+    def runTest(self):
+        mount_dest = '/mnt'
+        mount_origin = os.getcwd()
+
+        filename = 'shared.txt'
+        shared_file = os.path.join(mount_origin, filename)
+
+        with open(shared_file, 'w'):
+            container = self.client.create_container('busybox',
+                ['ls', mount_dest], volumes={mount_dest: {}})
+            container_id = container['Id']
+            self.client.start(container_id, binds={mount_origin: mount_dest})
+            self.tmp_containers.append(container_id)
+            exitcode = self.client.wait(container_id)
+            self.assertEqual(exitcode, 0)
+            logs = self.client.logs(container_id)
+
+        os.unlink(shared_file)
+        self.assertIn(filename, logs)
+
 class TestStartContainer(BaseTestCase):
     def runTest(self):
         res = self.client.create_container('busybox', 'true')