diff --git a/README.md b/README.md index 39bbced9..04f7982c 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,8 @@ is hosted. `version` is the version of the API the client will use and ```python c.build(path=None, tag=None, quiet=False, fileobj=None, nocache=False, - rm=False, stream=False) + rm=False, stream=False, timeout=None, + custom_context=False, encoding=None): ``` Similar to the `docker build` command. Either `path` or `fileobj` needs @@ -38,6 +39,11 @@ to be set. `path` can be a local path (to a directory containing a Dockerfile) or a remote URL. `fileobj` must be a readable file-like object to a Dockerfile. +If you have a tar file for the docker build context (including a dockerfile) +already, pass a readable file-like object to `fileobj` and also pass +`custom_context=True`. If the stream is compressed also, set `encoding` to +the correct value (e.g `gzip`). + ```python c.commit(container, repository=None, tag=None, message=None, author=None, conf=None) diff --git a/docker/client.py b/docker/client.py index ff490712..9678b0d2 100644 --- a/docker/client.py +++ b/docker/client.py @@ -304,17 +304,23 @@ class Client(requests.Session): u, None, params=self._attach_params(params), stream=True)) def build(self, path=None, tag=None, quiet=False, fileobj=None, - nocache=False, rm=False, stream=False, timeout=None): + nocache=False, rm=False, stream=False, timeout=None, + custom_context=False, encoding=None): remote = context = headers = None if path is None and fileobj is None: raise TypeError("Either path or fileobj needs to be provided.") + if custom_context and not fileobj: + raise TypeError("You must specify fileobj for a custom context") - if fileobj is not None: - context = utils.mkbuildcontext(fileobj) - elif path.startswith(('http://', 'https://', 'git://', 'github.com/')): - remote = path + if custom_context: + context = fileobj else: - context = utils.tar(path) + if fileobj is not None: + context = utils.mkbuildcontext(fileobj) + elif path.startswith(('http://', 'https://', 'git://', 'github.com/')): + remote = path + else: + context = utils.tar(path) if utils.compare_version('1.8', self._version) >= 0: stream = True @@ -327,8 +333,11 @@ class Client(requests.Session): 'nocache': nocache, 'rm': rm } + if context is not None: - headers = {'Content-Type': 'application/tar'} + headers['Content-Type'] = 'application/tar' + if encoding: + headers['Content-Encoding'] = encoding if utils.compare_version('1.9', self._version) >= 0: # If we don't have any auth data so far, try reloading the config diff --git a/tests/test.py b/tests/test.py index b70823c3..a7f410af 100644 --- a/tests/test.py +++ b/tests/test.py @@ -1230,6 +1230,22 @@ class DockerClientTest(unittest.TestCase): except Exception as e: self.fail('Command should not raise exception: {0}'.format(e)) + def test_build_container_custom_context(self): + script = io.BytesIO('\n'.join([ + 'FROM busybox', + 'MAINTAINER docker-py', + 'RUN mkdir -p /tmp/test', + 'EXPOSE 8080', + 'ADD https://dl.dropboxusercontent.com/u/20637798/silence.tar.gz' + ' /tmp/silence.tar.gz' + ]).encode('ascii')) + context = docker.utils.mkbuildcontext(script) + try: + self.client.build(fileobj=context, custom_context=True) + except Exception as e: + self.fail('Command should not raise exception: {0}'.format(e)) + + ####################### # PY SPECIFIC TESTS # #######################