Merge pull request #16 from globocom/bind-mounts

Add support for bind mounts
This commit is contained in:
Joffrey F 2013-07-12 06:45:17 -07:00
commit eb62af9dab
3 changed files with 51 additions and 7 deletions

View File

@ -66,7 +66,7 @@ Identical to the `docker port` command.
* `c.pull(repository, tag=None, registry=None)`
Identical to the `docker pull` command.
* `c.push(repository, registry=None)`
* `c.push(repository, registry=None)`
Identical to the `docker push` command.
* `c.remove_container(containers..., v=False)`
@ -85,7 +85,13 @@ Identical to the `docker search` command.
Identical to the `docker start` command, but doesn't support attach options. Use `docker logs` to
recover `stdout`/`stderr`
* `c.stop(containers..., t=10)`
* `c.start(container, binds={'/host': '/mnt'})`
Allows to bind a directory in the host to the container.
Similar to the `docker run` command with the `-b="/host:/mnt"`.
Requires the container to be created with the volumes argument:
`c.create_container(..., volumes={'/mnt': {}})`
* `c.stop(containers..., t=10)`
Identical to the `docker stop` command.
* `c.tag(image, repository, tag=None, force=False)`
@ -96,3 +102,4 @@ Identical to the `docker version` command.
* `c.wait(containers...)`
Identical to the `docker wait` command.

View File

@ -77,6 +77,9 @@ class Client(requests.Session):
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 @@ class Client(requests.Session):
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)
@ -285,10 +288,18 @@ class Client(requests.Session):
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 @@ class Client(requests.Session):
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 @@ class BuilderClient(object):
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:

View File

@ -1,3 +1,4 @@
import os
import six
import unittest
@ -97,6 +98,27 @@ class TestCreateContainer(BaseTestCase):
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')