diff --git a/docker/api/container.py b/docker/api/container.py index 9fa6d763..551e72aa 100644 --- a/docker/api/container.py +++ b/docker/api/container.py @@ -313,9 +313,10 @@ class ContainerApiMixin(object): **Using volumes** - Volume declaration is done in two parts. Provide a list of mountpoints - to the with the ``volumes`` parameter, and declare mappings in the - ``host_config`` section. + Volume declaration is done in two parts. Provide a list of + paths to use as mountpoints inside the container with the + ``volumes`` parameter, and declare mappings from paths on the host + in the ``host_config`` section. .. code-block:: python @@ -392,7 +393,8 @@ class ContainerApiMixin(object): version 1.10. Use ``host_config`` instead. dns_opt (:py:class:`list`): Additional options to be added to the container's ``resolv.conf`` file - volumes (str or list): + volumes (str or list): List of paths inside the container to use + as volumes. volumes_from (:py:class:`list`): List of container names or Ids to get volumes from. network_disabled (bool): Disable networking diff --git a/docker/models/containers.py b/docker/models/containers.py index 78463fd8..330ac92c 100644 --- a/docker/models/containers.py +++ b/docker/models/containers.py @@ -885,5 +885,15 @@ def _create_container_args(kwargs): for p in sorted(port_bindings.keys())] binds = create_kwargs['host_config'].get('Binds') if binds: - create_kwargs['volumes'] = [v.split(':')[0] for v in binds] + create_kwargs['volumes'] = [_host_volume_from_bind(v) for v in binds] return create_kwargs + + +def _host_volume_from_bind(bind): + bits = bind.split(':') + if len(bits) == 1: + return bits[0] + elif len(bits) == 2 and bits[1] in ('ro', 'rw'): + return bits[0] + else: + return bits[1] diff --git a/tests/integration/models_containers_test.py b/tests/integration/models_containers_test.py index d0f87d60..4f1e6a1f 100644 --- a/tests/integration/models_containers_test.py +++ b/tests/integration/models_containers_test.py @@ -1,4 +1,5 @@ import docker +import tempfile from .base import BaseIntegrationTest, TEST_API_VERSION @@ -32,6 +33,42 @@ class ContainerCollectionTest(BaseIntegrationTest): with self.assertRaises(docker.errors.ImageNotFound): client.containers.run("dockerpytest_does_not_exist") + def test_run_with_volume(self): + client = docker.from_env(version=TEST_API_VERSION) + path = tempfile.mkdtemp() + + container = client.containers.run( + "alpine", "sh -c 'echo \"hello\" > /insidecontainer/test'", + volumes=["%s:/insidecontainer" % path], + detach=True + ) + self.tmp_containers.append(container.id) + container.wait() + + out = client.containers.run( + "alpine", "cat /insidecontainer/test", + volumes=["%s:/insidecontainer" % path] + ) + self.assertEqual(out, b'hello\n') + + def test_run_with_named_volume(self): + client = docker.from_env(version=TEST_API_VERSION) + client.volumes.create(name="somevolume") + + container = client.containers.run( + "alpine", "sh -c 'echo \"hello\" > /insidecontainer/test'", + volumes=["somevolume:/insidecontainer"], + detach=True + ) + self.tmp_containers.append(container.id) + container.wait() + + out = client.containers.run( + "alpine", "cat /insidecontainer/test", + volumes=["somevolume:/insidecontainer"] + ) + self.assertEqual(out, b'hello\n') + 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 index c3086c62..ae1bd12a 100644 --- a/tests/unit/models_containers_test.py +++ b/tests/unit/models_containers_test.py @@ -100,6 +100,9 @@ class ContainerCollectionTest(unittest.TestCase): volumes=[ '/home/user1/:/mnt/vol2', '/var/www:/mnt/vol1:ro', + 'volumename:/mnt/vol3', + '/volumewithnohostpath', + '/anothervolumewithnohostpath:ro', ], volumes_from=['container'], working_dir='/code' @@ -116,6 +119,9 @@ class ContainerCollectionTest(unittest.TestCase): 'Binds': [ '/home/user1/:/mnt/vol2', '/var/www:/mnt/vol1:ro', + 'volumename:/mnt/vol3', + '/volumewithnohostpath', + '/anothervolumewithnohostpath:ro' ], 'BlkioDeviceReadBps': [{'Path': 'foo', 'Rate': 3}], 'BlkioDeviceReadIOps': [{'Path': 'foo', 'Rate': 3}], @@ -181,7 +187,13 @@ class ContainerCollectionTest(unittest.TestCase): tty=True, user='bob', volume_driver='some_driver', - volumes=['/home/user1/', '/var/www'], + volumes=[ + '/mnt/vol2', + '/mnt/vol1', + '/mnt/vol3', + '/volumewithnohostpath', + '/anothervolumewithnohostpath' + ], working_dir='/code' )