79 lines
4.1 KiB
Plaintext
79 lines
4.1 KiB
Plaintext
|
RESTART_FILE = '/.restart-proc'
|
||
|
TYPE_RESTART_CONTAINER_STEP = 'live_update_restart_container_step'
|
||
|
|
||
|
KWARGS_BLACKLIST = [
|
||
|
# since we'll be passing `dockerfile_contents` when building the
|
||
|
# child image, remove any kwargs that might conflict
|
||
|
'dockerfile', 'dockerfile_contents',
|
||
|
|
||
|
# 'target' isn't relevant to our child build--if we pass this arg,
|
||
|
# Docker will just fail to find the specified stage and error out
|
||
|
'target',
|
||
|
]
|
||
|
|
||
|
def docker_build_with_restart(ref, context, entrypoint, live_update,
|
||
|
base_suffix='-tilt_docker_build_with_restart_base', restart_file=RESTART_FILE, **kwargs):
|
||
|
"""Wrap a docker_build call and its associated live_update steps so that the last step
|
||
|
of any live update is to rerun the given entrypoint.
|
||
|
|
||
|
|
||
|
Args:
|
||
|
ref: name for this image (e.g. 'myproj/backend' or 'myregistry/myproj/backend'); as the parameter of the same name in docker_build
|
||
|
context: path to use as the Docker build context; as the parameter of the same name in docker_build
|
||
|
entrypoint: the command to be (re-)executed when the container starts or when a live_update is run
|
||
|
live_update: set of steps for updating a running container; as the parameter of the same name in docker_build
|
||
|
base_suffix: suffix for naming the base image, applied as {ref}{base_suffix}
|
||
|
restart_file: file that Tilt will update during a live_update to signal the entrypoint to rerun
|
||
|
**kwargs: will be passed to the underlying `docker_build` call
|
||
|
"""
|
||
|
|
||
|
# first, validate the given live_update steps
|
||
|
if len(live_update) == 0:
|
||
|
fail("`docker_build_with_restart` requires at least one live_update step")
|
||
|
for step in live_update:
|
||
|
if type(step) == TYPE_RESTART_CONTAINER_STEP:
|
||
|
fail("`docker_build_with_restart` is not compatible with live_update step: "+
|
||
|
"`restart_container()` (this extension is meant to REPLACE restart_container() )")
|
||
|
|
||
|
# rename the original image to make it a base image and declare a docker_build for it
|
||
|
base_ref = '{}{}'.format(ref, base_suffix)
|
||
|
docker_build(base_ref, context, **kwargs)
|
||
|
|
||
|
# declare a new docker build that adds a static binary of tilt-restart-wrapper
|
||
|
# (which makes use of `entr` to watch files and restart processes) to the user's image
|
||
|
df = '''
|
||
|
FROM tiltdev/restart-helper:2020-07-16 as restart-helper
|
||
|
|
||
|
FROM {}
|
||
|
USER root
|
||
|
RUN ["touch", "{}"]
|
||
|
COPY --from=restart-helper /tilt-restart-wrapper /
|
||
|
COPY --from=restart-helper /entr /
|
||
|
'''.format(base_ref, restart_file)
|
||
|
|
||
|
# Clean kwargs for building the child image (which builds on user's specified
|
||
|
# image and copies in Tilt's restart wrapper). In practice, this means removing
|
||
|
# kwargs that were relevant to building the user's specified image but are NOT
|
||
|
# relevant to building the child image / may conflict with args we specifically
|
||
|
# pass for the child image.
|
||
|
cleaned_kwargs = {k: v for k, v in kwargs.items() if k not in KWARGS_BLACKLIST}
|
||
|
|
||
|
# Change the entrypoint to use `tilt-restart-wrapper`.
|
||
|
# `tilt-restart-wrapper` makes use of `entr` (https://github.com/eradman/entr/) to
|
||
|
# re-execute $entrypoint whenever $restart_file changes
|
||
|
if type(entrypoint) == type(""):
|
||
|
entrypoint_with_entr = ["/tilt-restart-wrapper", "--watch_file={}".format(restart_file), "sh", "-c", entrypoint]
|
||
|
elif type(entrypoint) == type([]):
|
||
|
entrypoint_with_entr = ["/tilt-restart-wrapper", "--watch_file={}".format(restart_file)] + entrypoint
|
||
|
else:
|
||
|
fail("`entrypoint` must be a string or list of strings: got {}".format(type(entrypoint)))
|
||
|
|
||
|
# last live_update step should always be to modify $restart_file, which
|
||
|
# triggers the process wrapper to rerun $entrypoint
|
||
|
# NB: write `date` instead of just `touch`ing because `entr` doesn't respond
|
||
|
# to timestamp changes, only writes (see https://github.com/eradman/entr/issues/32)
|
||
|
live_update = live_update + [run('date > {}'.format(restart_file))]
|
||
|
|
||
|
docker_build(ref, context, entrypoint=entrypoint_with_entr, dockerfile_contents=df,
|
||
|
live_update=live_update, **cleaned_kwargs)
|