mirror of
https://github.com/docker/compose.git
synced 2025-07-21 12:44:54 +02:00
Added --force-rm to compose build.
It's a flag passed to docker build that removes the intermediate containers left behind on fail builds. Signed-off-by: Adrian Budau <budau.adi@gmail.com>
This commit is contained in:
parent
0017f43d7f
commit
c5c36d8b00
@ -180,12 +180,14 @@ class TopLevelCommand(DocoptCommand):
|
|||||||
Usage: build [options] [SERVICE...]
|
Usage: build [options] [SERVICE...]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
|
--force-rm Always remove intermediate containers.
|
||||||
--no-cache Do not use cache when building the image.
|
--no-cache Do not use cache when building the image.
|
||||||
--pull Always attempt to pull a newer version of the image.
|
--pull Always attempt to pull a newer version of the image.
|
||||||
"""
|
"""
|
||||||
|
force_rm = bool(options.get('--force-rm', False))
|
||||||
no_cache = bool(options.get('--no-cache', False))
|
no_cache = bool(options.get('--no-cache', False))
|
||||||
pull = bool(options.get('--pull', False))
|
pull = bool(options.get('--pull', False))
|
||||||
project.build(service_names=options['SERVICE'], no_cache=no_cache, pull=pull)
|
project.build(service_names=options['SERVICE'], no_cache=no_cache, pull=pull, force_rm=force_rm)
|
||||||
|
|
||||||
def help(self, project, options):
|
def help(self, project, options):
|
||||||
"""
|
"""
|
||||||
|
@ -278,10 +278,10 @@ class Project(object):
|
|||||||
for service in self.get_services(service_names):
|
for service in self.get_services(service_names):
|
||||||
service.restart(**options)
|
service.restart(**options)
|
||||||
|
|
||||||
def build(self, service_names=None, no_cache=False, pull=False):
|
def build(self, service_names=None, no_cache=False, pull=False, force_rm=False):
|
||||||
for service in self.get_services(service_names):
|
for service in self.get_services(service_names):
|
||||||
if service.can_be_built():
|
if service.can_be_built():
|
||||||
service.build(no_cache, pull)
|
service.build(no_cache, pull, force_rm)
|
||||||
else:
|
else:
|
||||||
log.info('%s uses an image, skipping' % service.name)
|
log.info('%s uses an image, skipping' % service.name)
|
||||||
|
|
||||||
|
@ -701,7 +701,7 @@ class Service(object):
|
|||||||
cgroup_parent=cgroup_parent
|
cgroup_parent=cgroup_parent
|
||||||
)
|
)
|
||||||
|
|
||||||
def build(self, no_cache=False, pull=False):
|
def build(self, no_cache=False, pull=False, force_rm=False):
|
||||||
log.info('Building %s' % self.name)
|
log.info('Building %s' % self.name)
|
||||||
|
|
||||||
path = self.options['build']
|
path = self.options['build']
|
||||||
@ -715,6 +715,7 @@ class Service(object):
|
|||||||
tag=self.image_name,
|
tag=self.image_name,
|
||||||
stream=True,
|
stream=True,
|
||||||
rm=True,
|
rm=True,
|
||||||
|
forcerm=force_rm,
|
||||||
pull=pull,
|
pull=pull,
|
||||||
nocache=no_cache,
|
nocache=no_cache,
|
||||||
dockerfile=self.options.get('dockerfile', None),
|
dockerfile=self.options.get('dockerfile', None),
|
||||||
|
@ -93,7 +93,7 @@ __docker_compose_services_stopped() {
|
|||||||
_docker_compose_build() {
|
_docker_compose_build() {
|
||||||
case "$cur" in
|
case "$cur" in
|
||||||
-*)
|
-*)
|
||||||
COMPREPLY=( $( compgen -W "--help --no-cache --pull" -- "$cur" ) )
|
COMPREPLY=( $( compgen -W "--help --force-rm --no-cache --pull" -- "$cur" ) )
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
__docker_compose_services_from_build
|
__docker_compose_services_from_build
|
||||||
|
@ -192,6 +192,7 @@ __docker-compose_subcommand() {
|
|||||||
(build)
|
(build)
|
||||||
_arguments \
|
_arguments \
|
||||||
$opts_help \
|
$opts_help \
|
||||||
|
'--force-rm[Always remove intermediate containers.]' \
|
||||||
'--no-cache[Do not use cache when building the image]' \
|
'--no-cache[Do not use cache when building the image]' \
|
||||||
'--pull[Always attempt to pull a newer version of the image.]' \
|
'--pull[Always attempt to pull a newer version of the image.]' \
|
||||||
'*:services:__docker-compose_services_from_build' && ret=0
|
'*:services:__docker-compose_services_from_build' && ret=0
|
||||||
|
@ -15,6 +15,7 @@ parent = "smn_compose_cli"
|
|||||||
Usage: build [options] [SERVICE...]
|
Usage: build [options] [SERVICE...]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
|
--force-rm Always remove intermediate containers.
|
||||||
--no-cache Do not use cache when building the image.
|
--no-cache Do not use cache when building the image.
|
||||||
--pull Always attempt to pull a newer version of the image.
|
--pull Always attempt to pull a newer version of the image.
|
||||||
```
|
```
|
||||||
|
@ -9,6 +9,7 @@ from operator import attrgetter
|
|||||||
from .. import mock
|
from .. import mock
|
||||||
from compose.cli.command import get_project
|
from compose.cli.command import get_project
|
||||||
from compose.cli.docker_client import docker_client
|
from compose.cli.docker_client import docker_client
|
||||||
|
from compose.container import Container
|
||||||
from tests.integration.testcases import DockerClientTestCase
|
from tests.integration.testcases import DockerClientTestCase
|
||||||
|
|
||||||
|
|
||||||
@ -145,6 +146,33 @@ class CLITestCase(DockerClientTestCase):
|
|||||||
assert BUILD_CACHE_TEXT not in result.stdout
|
assert BUILD_CACHE_TEXT not in result.stdout
|
||||||
assert BUILD_PULL_TEXT in result.stdout
|
assert BUILD_PULL_TEXT in result.stdout
|
||||||
|
|
||||||
|
def test_build_failed(self):
|
||||||
|
self.base_dir = 'tests/fixtures/simple-failing-dockerfile'
|
||||||
|
self.dispatch(['build', 'simple'], returncode=1)
|
||||||
|
|
||||||
|
labels = ["com.docker.compose.test_failing_image=true"]
|
||||||
|
containers = [
|
||||||
|
Container.from_ps(self.project.client, c)
|
||||||
|
for c in self.project.client.containers(
|
||||||
|
all=True,
|
||||||
|
filters={"label": labels})
|
||||||
|
]
|
||||||
|
assert len(containers) == 1
|
||||||
|
|
||||||
|
def test_build_failed_forcerm(self):
|
||||||
|
self.base_dir = 'tests/fixtures/simple-failing-dockerfile'
|
||||||
|
self.dispatch(['build', '--force-rm', 'simple'], returncode=1)
|
||||||
|
|
||||||
|
labels = ["com.docker.compose.test_failing_image=true"]
|
||||||
|
|
||||||
|
containers = [
|
||||||
|
Container.from_ps(self.project.client, c)
|
||||||
|
for c in self.project.client.containers(
|
||||||
|
all=True,
|
||||||
|
filters={"label": labels})
|
||||||
|
]
|
||||||
|
assert not containers
|
||||||
|
|
||||||
def test_up_detached(self):
|
def test_up_detached(self):
|
||||||
self.dispatch(['up', '-d'])
|
self.dispatch(['up', '-d'])
|
||||||
service = self.project.get_service('simple')
|
service = self.project.get_service('simple')
|
||||||
|
7
tests/fixtures/simple-failing-dockerfile/Dockerfile
vendored
Normal file
7
tests/fixtures/simple-failing-dockerfile/Dockerfile
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
FROM busybox:latest
|
||||||
|
LABEL com.docker.compose.test_image=true
|
||||||
|
LABEL com.docker.compose.test_failing_image=true
|
||||||
|
# With the following label the container wil be cleaned up automatically
|
||||||
|
# Must be kept in sync with LABEL_PROJECT from compose/const.py
|
||||||
|
LABEL com.docker.compose.project=composetest
|
||||||
|
RUN exit 1
|
2
tests/fixtures/simple-failing-dockerfile/docker-compose.yml
vendored
Normal file
2
tests/fixtures/simple-failing-dockerfile/docker-compose.yml
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
simple:
|
||||||
|
build: .
|
@ -356,6 +356,7 @@ class ServiceTest(unittest.TestCase):
|
|||||||
stream=True,
|
stream=True,
|
||||||
path='.',
|
path='.',
|
||||||
pull=False,
|
pull=False,
|
||||||
|
forcerm=False,
|
||||||
nocache=False,
|
nocache=False,
|
||||||
rm=True,
|
rm=True,
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user