diff --git a/compose/config/config.py b/compose/config/config.py index 242e7af92..c716393d4 100644 --- a/compose/config/config.py +++ b/compose/config/config.py @@ -564,7 +564,8 @@ def validate_paths(service_dict): (not os.path.exists(build_path) or not os.access(build_path, os.R_OK)) ): raise ConfigurationError( - "build path %s either does not exist or is not accessible." % build_path) + "build path %s either does not exist, is not accessible, " + "or is not a valid URL." % build_path) def merge_path_mappings(base, override): diff --git a/docs/compose-file.md b/docs/compose-file.md index 51d1f5e1a..800d2aa98 100644 --- a/docs/compose-file.md +++ b/docs/compose-file.md @@ -31,15 +31,18 @@ definition. ### build -Path to a directory containing a Dockerfile. When the value supplied is a -relative path, it is interpreted as relative to the location of the yml file -itself. This directory is also the build context that is sent to the Docker daemon. +Either a path to a directory containing a Dockerfile, or a url to a git repository. + +When the value supplied is a relative path, it is interpreted as relative to the +location of the Compose file. This directory is also the build context that is +sent to the Docker daemon. Compose will build and tag it with a generated name, and use that image thereafter. build: /path/to/build/dir -Using `build` together with `image` is not allowed. Attempting to do so results in an error. +Using `build` together with `image` is not allowed. Attempting to do so results in +an error. ### cap_add, cap_drop diff --git a/tests/integration/service_test.py b/tests/integration/service_test.py index 5dd3d2e68..b03baac59 100644 --- a/tests/integration/service_test.py +++ b/tests/integration/service_test.py @@ -507,6 +507,13 @@ class ServiceTest(DockerClientTestCase): self.create_service('web', build=text_type(base_dir)).build() self.assertEqual(len(self.client.images(name='composetest_web')), 1) + def test_build_with_git_url(self): + build_url = "https://github.com/dnephin/docker-build-from-url.git" + service = self.create_service('buildwithurl', build=build_url) + self.addCleanup(self.client.remove_image, service.image_name) + service.build() + assert service.image() + def test_start_container_stays_unpriviliged(self): service = self.create_service('web') container = create_and_start_container(service).inspect() diff --git a/tests/unit/config/config_test.py b/tests/unit/config/config_test.py index 6de794ade..e15ac3502 100644 --- a/tests/unit/config/config_test.py +++ b/tests/unit/config/config_test.py @@ -1497,13 +1497,14 @@ class BuildPathTest(unittest.TestCase): service_dict = load_from_filename('tests/fixtures/build-path/docker-compose.yml') self.assertEquals(service_dict, [{'name': 'foo', 'build': self.abs_context_path}]) - def test_valid_url_path(self): + def test_valid_url_in_build_path(self): valid_urls = [ 'git://github.com/docker/docker', 'git@github.com:docker/docker.git', 'git@bitbucket.org:atlassianlabs/atlassian-docker.git', 'https://github.com/docker/docker.git', 'http://github.com/docker/docker.git', + 'github.com/docker/docker.git', ] for valid_url in valid_urls: service_dict = config.load(build_config_details({ @@ -1511,6 +1512,19 @@ class BuildPathTest(unittest.TestCase): }, '.', None)) assert service_dict[0]['build'] == valid_url + def test_invalid_url_in_build_path(self): + invalid_urls = [ + 'example.com/bogus', + 'ftp://example.com/', + '/path/does/not/exist', + ] + for invalid_url in invalid_urls: + with pytest.raises(ConfigurationError) as exc: + config.load(build_config_details({ + 'invalidurl': {'build': invalid_url}, + }, '.', None)) + assert 'build path' in exc.exconly() + class GetDefaultConfigFilesTestCase(unittest.TestCase):