From 89f2bfe4f392b1bb74ab85af01dc95d2d6b47202 Mon Sep 17 00:00:00 2001 From: Gil Raphaelli Date: Tue, 31 Jul 2018 11:54:32 -0400 Subject: [PATCH] add --parallel option to build Signed-off-by: Gil Raphaelli --- compose/cli/main.py | 2 ++ compose/project.py | 27 +++++++++++++++++-- tests/acceptance/cli_test.py | 7 +++++ .../build-multiple-composefile/a/Dockerfile | 4 +++ .../build-multiple-composefile/b/Dockerfile | 4 +++ .../docker-compose.yml | 8 ++++++ 6 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 tests/fixtures/build-multiple-composefile/a/Dockerfile create mode 100644 tests/fixtures/build-multiple-composefile/b/Dockerfile create mode 100644 tests/fixtures/build-multiple-composefile/docker-compose.yml diff --git a/compose/cli/main.py b/compose/cli/main.py index fa6401412..d224093cb 100644 --- a/compose/cli/main.py +++ b/compose/cli/main.py @@ -260,6 +260,7 @@ class TopLevelCommand(object): --pull Always attempt to pull a newer version of the image. -m, --memory MEM Sets memory limit for the build container. --build-arg key=val Set build-time variables for services. + --parallel Build images in parallel. """ service_names = options['SERVICE'] build_args = options.get('--build-arg', None) @@ -280,6 +281,7 @@ class TopLevelCommand(object): memory=options.get('--memory'), build_args=build_args, gzip=options.get('--compress', False), + parallel_build=options.get('--parallel', False), ) def bundle(self, options): diff --git a/compose/project.py b/compose/project.py index 005b7e240..a7ef327e6 100644 --- a/compose/project.py +++ b/compose/project.py @@ -372,13 +372,36 @@ class Project(object): return containers def build(self, service_names=None, no_cache=False, pull=False, force_rm=False, memory=None, - build_args=None, gzip=False): + build_args=None, gzip=False, parallel_build=False): + + services = [] for service in self.get_services(service_names): if service.can_be_built(): - service.build(no_cache, pull, force_rm, memory, build_args, gzip) + services.append(service) else: log.info('%s uses an image, skipping' % service.name) + def build_service(service): + service.build(no_cache, pull, force_rm, memory, build_args, gzip) + + if parallel_build: + _, errors = parallel.parallel_execute( + services, + build_service, + operator.attrgetter('name'), + 'Building', + limit=5, + ) + if len(errors): + combined_errors = '\n'.join([ + e.decode('utf-8') if isinstance(e, six.binary_type) else e for e in errors.values() + ]) + raise ProjectError(combined_errors) + + else: + for service in services: + build_service(service) + def create( self, service_names=None, diff --git a/tests/acceptance/cli_test.py b/tests/acceptance/cli_test.py index 6c6cf32f5..2361a1fbf 100644 --- a/tests/acceptance/cli_test.py +++ b/tests/acceptance/cli_test.py @@ -773,6 +773,13 @@ class CLITestCase(DockerClientTestCase): assert 'does not exist, is not accessible, or is not a valid URL' in result.stderr + def test_build_parallel(self): + self.base_dir = 'tests/fixtures/build-multiple-composefile' + result = self.dispatch(['build', '--parallel']) + assert 'Successfully tagged build-multiple-composefile_a:latest' in result.stdout + assert 'Successfully tagged build-multiple-composefile_b:latest' in result.stdout + assert 'Successfully built' in result.stdout + def test_create(self): self.dispatch(['create']) service = self.project.get_service('simple') diff --git a/tests/fixtures/build-multiple-composefile/a/Dockerfile b/tests/fixtures/build-multiple-composefile/a/Dockerfile new file mode 100644 index 000000000..2ba45ce55 --- /dev/null +++ b/tests/fixtures/build-multiple-composefile/a/Dockerfile @@ -0,0 +1,4 @@ + +FROM busybox:latest +RUN echo a +CMD top diff --git a/tests/fixtures/build-multiple-composefile/b/Dockerfile b/tests/fixtures/build-multiple-composefile/b/Dockerfile new file mode 100644 index 000000000..e282e8bbf --- /dev/null +++ b/tests/fixtures/build-multiple-composefile/b/Dockerfile @@ -0,0 +1,4 @@ + +FROM busybox:latest +RUN echo b +CMD top diff --git a/tests/fixtures/build-multiple-composefile/docker-compose.yml b/tests/fixtures/build-multiple-composefile/docker-compose.yml new file mode 100644 index 000000000..efa70d7e0 --- /dev/null +++ b/tests/fixtures/build-multiple-composefile/docker-compose.yml @@ -0,0 +1,8 @@ + +version: "2" + +services: + a: + build: ./a + b: + build: ./b