Make smart recreate the default
Add --force-recreate flag to enable the old default behaviour of recreating everything. Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
This commit is contained in:
parent
b2cb5a48d2
commit
ced94a3504
8 changed files with 77 additions and 53 deletions
|
|
@ -429,17 +429,22 @@ class TopLevelCommand(Command):
|
|||
|
||||
def up(self, project, options):
|
||||
"""
|
||||
Build, (re)create, start and attach to containers for a service.
|
||||
Builds, (re)creates, starts, and attaches to containers for a service.
|
||||
|
||||
By default, `docker-compose up` will aggregate the output of each container, and
|
||||
when it exits, all containers will be stopped. If you run `docker-compose up -d`,
|
||||
it'll start the containers in the background and leave them running.
|
||||
Unless they are already running, this command also starts any linked services.
|
||||
|
||||
If there are existing containers for a service, `docker-compose up` will stop
|
||||
and recreate them (preserving mounted volumes with volumes-from),
|
||||
so that changes in `docker-compose.yml` are picked up. If you do not want existing
|
||||
containers to be recreated, `docker-compose up --no-recreate` will re-use existing
|
||||
containers.
|
||||
The `docker-compose up` command aggregates the output of each container. When
|
||||
the command exits, all containers are stopped. Running `docker-compose up -d`
|
||||
starts the containers in the background and leaves them running.
|
||||
|
||||
If there are existing containers for a service, and the service's configuration
|
||||
or image was changed after the container's creation, `docker-compose up` picks
|
||||
up the changes by stopping and recreating the containers (preserving mounted
|
||||
volumes). To prevent Compose from picking up changes, use the `--no-recreate`
|
||||
flag.
|
||||
|
||||
If you want to force Compose to stop and recreate all containers, use the
|
||||
`--force-recreate` flag.
|
||||
|
||||
Usage: up [options] [SERVICE...]
|
||||
|
||||
|
|
@ -450,9 +455,10 @@ class TopLevelCommand(Command):
|
|||
print new container names.
|
||||
--no-color Produce monochrome output.
|
||||
--no-deps Don't start linked services.
|
||||
--x-smart-recreate Only recreate containers whose configuration or
|
||||
image needs to be updated. (EXPERIMENTAL)
|
||||
--force-recreate Recreate containers even if their configuration and
|
||||
image haven't changed. Incompatible with --no-recreate.
|
||||
--no-recreate If containers already exist, don't recreate them.
|
||||
Incompatible with --force-recreate.
|
||||
--no-build Don't build an image, even if it's missing
|
||||
-t, --timeout TIMEOUT Use this timeout in seconds for container shutdown
|
||||
when attached or when containers are already
|
||||
|
|
@ -465,15 +471,18 @@ class TopLevelCommand(Command):
|
|||
|
||||
start_deps = not options['--no-deps']
|
||||
allow_recreate = not options['--no-recreate']
|
||||
smart_recreate = options['--x-smart-recreate']
|
||||
force_recreate = options['--force-recreate']
|
||||
service_names = options['SERVICE']
|
||||
timeout = int(options.get('--timeout') or DEFAULT_TIMEOUT)
|
||||
|
||||
if force_recreate and not allow_recreate:
|
||||
raise UserError("--force-recreate and --no-recreate cannot be combined.")
|
||||
|
||||
to_attach = project.up(
|
||||
service_names=service_names,
|
||||
start_deps=start_deps,
|
||||
allow_recreate=allow_recreate,
|
||||
smart_recreate=smart_recreate,
|
||||
force_recreate=force_recreate,
|
||||
insecure_registry=insecure_registry,
|
||||
do_build=not options['--no-build'],
|
||||
timeout=timeout
|
||||
|
|
|
|||
|
|
@ -223,11 +223,14 @@ class Project(object):
|
|||
service_names=None,
|
||||
start_deps=True,
|
||||
allow_recreate=True,
|
||||
smart_recreate=False,
|
||||
force_recreate=False,
|
||||
insecure_registry=False,
|
||||
do_build=True,
|
||||
timeout=DEFAULT_TIMEOUT):
|
||||
|
||||
if force_recreate and not allow_recreate:
|
||||
raise ValueError("force_recreate and allow_recreate are in conflict")
|
||||
|
||||
services = self.get_services(service_names, include_deps=start_deps)
|
||||
|
||||
for service in services:
|
||||
|
|
@ -236,7 +239,7 @@ class Project(object):
|
|||
plans = self._get_convergence_plans(
|
||||
services,
|
||||
allow_recreate=allow_recreate,
|
||||
smart_recreate=smart_recreate,
|
||||
force_recreate=force_recreate,
|
||||
)
|
||||
|
||||
return [
|
||||
|
|
@ -253,7 +256,7 @@ class Project(object):
|
|||
def _get_convergence_plans(self,
|
||||
services,
|
||||
allow_recreate=True,
|
||||
smart_recreate=False):
|
||||
force_recreate=False):
|
||||
|
||||
plans = {}
|
||||
|
||||
|
|
@ -265,19 +268,19 @@ class Project(object):
|
|||
and plans[name].action == 'recreate'
|
||||
]
|
||||
|
||||
if updated_dependencies:
|
||||
if updated_dependencies and allow_recreate:
|
||||
log.debug(
|
||||
'%s has upstream changes (%s)',
|
||||
service.name, ", ".join(updated_dependencies),
|
||||
)
|
||||
plan = service.convergence_plan(
|
||||
allow_recreate=allow_recreate,
|
||||
smart_recreate=False,
|
||||
force_recreate=True,
|
||||
)
|
||||
else:
|
||||
plan = service.convergence_plan(
|
||||
allow_recreate=allow_recreate,
|
||||
smart_recreate=smart_recreate,
|
||||
force_recreate=force_recreate,
|
||||
)
|
||||
|
||||
plans[service.name] = plan
|
||||
|
|
|
|||
|
|
@ -264,25 +264,28 @@ class Service(object):
|
|||
|
||||
def convergence_plan(self,
|
||||
allow_recreate=True,
|
||||
smart_recreate=False):
|
||||
force_recreate=False):
|
||||
|
||||
if force_recreate and not allow_recreate:
|
||||
raise ValueError("force_recreate and allow_recreate are in conflict")
|
||||
|
||||
containers = self.containers(stopped=True)
|
||||
|
||||
if not containers:
|
||||
return ConvergencePlan('create', [])
|
||||
|
||||
if smart_recreate and not self._containers_have_diverged(containers):
|
||||
stopped = [c for c in containers if not c.is_running]
|
||||
|
||||
if stopped:
|
||||
return ConvergencePlan('start', stopped)
|
||||
|
||||
return ConvergencePlan('noop', containers)
|
||||
|
||||
if not allow_recreate:
|
||||
return ConvergencePlan('start', containers)
|
||||
|
||||
return ConvergencePlan('recreate', containers)
|
||||
if force_recreate or self._containers_have_diverged(containers):
|
||||
return ConvergencePlan('recreate', containers)
|
||||
|
||||
stopped = [c for c in containers if not c.is_running]
|
||||
|
||||
if stopped:
|
||||
return ConvergencePlan('start', stopped)
|
||||
|
||||
return ConvergencePlan('noop', containers)
|
||||
|
||||
def _containers_have_diverged(self, containers):
|
||||
config_hash = None
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue