Faster Development with Live Update (Tutorial)
This tutorial looks at a
Tiltfile with build optimizations.
We explain what they do, and why you would want to use them.
(This is a tutorial that walks you through a sample project. If you’re looking for technical specs and details, check out the Live Update Reference docs.)
In the Tutorial, we introduced the
This function builds a Docker image. Tilt will watch the inputs to the
image, and do a fresh build every time the inputs change.
However, rebuilding your Docker image every time you change some code isn’t super efficient, even if your caching is good. The efficiency is even worse if you’re working with compiled languages, and even worse if you’re pushing images into the cloud.
That’s why Tilt has a feature called Live Update, to make your containerized development lightning-fast.
Let’s Look At an Example
Let’s look at an example app,
git clone https://github.com/tilt-dev/random_number cd random_number
This “microservice” app consists of:
numbers, a Python+Flask server which serves a random number
fe, a Golang server frontend which hits
numbersfor a random number
Tiltfile at the root of the repo contains this example:
# Service: numbers docker_build('random_number/numbers', 'numbers', live_update=[ sync('./numbers', '/app'), run('cd /app && pip install -r requirements.txt', trigger='numbers/requirements.txt'), ] ) # Service: fe docker_build_with_restart('random_number/fe', 'fe', entrypoint='/go/bin/fe', live_update=[ sync('./fe', '/go/src/github.com/tilt-dev/random_number/fe'), run('go install github.com/tilt-dev/random_number/fe'), ] )
This looks similar to the
Tiltfile in previous tutorials, but when we specify
how to build the image with
docker_build(), we pass an additional argument,
live_update, containing a list of steps for how to update the running container.
numbers (Python + Flask)
Let’s zoom in on the
live_update configuration for the
numbers service first:
docker_build('random_number/numbers', 'numbers', live_update=[ sync('./numbers', '/app'), # run `pip install` IF `requirements.txt` has changed run('cd /app && pip install -r requirements.txt', trigger='numbers/requirements.txt'), ] )
These lines configure Tilt to, when possible, update containers running the image
incrementally rather than doing a full build every time code changes. We’ll step through it line by line.
sync method watches a file or directory on your local filesystem, and when it detects a change, copies the changed file(s) into your container at the specified path.
In this case, we map the directory
./numbers (relative to the Tiltfile) into
the container filesystem at
docker_build behavior is to watch all files in the Docker build context (here,
and any time one changes, rebuild the image and re-deploy it to Kubernetes. The
sync here says that, if
the changed file matches
./numbers, to instead do a
live_update: Tilt will copy
the changed files into the container and execute any appropriate
steps, without actually building or pushing a Docker image or performing a Kubernetes deploy.
run('cd /app && pip install -r requirements.txt', trigger='numbers/requirements.txt'),
run method runs shell commands inside your container.
This particular run step relies on a
trigger: when this resource Live Updates, Tilt will
run this command in the container if any changed files match the trigger (here,
numbers/requirements.txt). This specificity means that we’ll only run
pip install if
dependencies have actually changed.
Let’s now look at the
live_update configuration for the other service in this app, the frontend, which is written in Go:
docker_build_with_restart('random_number/fe', 'fe', # command to run on container start/re-run on live update entrypoint='/go/bin/fe', live_update=[ sync('./fe', '/go/src/github.com/tilt-dev/random_number/fe'), run('go install github.com/tilt-dev/random_number/fe'), ] )
The eagle-eyed among you will notice that the function called here is slightly different: instead of
docker_build, we call
docker_build_with_restart. More on that in a moment; first let’s go through the
live_update steps one a time.
As we saw in the configuration for
sync call maps a local directory to a path on the container. Any time a file on disk changes, if it matches the path
./fe, Tilt will copy it to the designated path in the container.
run('go install github.com/tilt-dev/random_number/fe')
run step seen in
numbers, this one lacks a
trigger, which means that Tilt will run this command in the container every time a Live Update happens (i.e., when a file matching a
sync changes). In this example, every time Tilt syncs changed files to the container, it then recompiles the Go binary.
One of the major build optimizations here is that Tilt runs your command inside the existing container, instead of building from scratch to create a fresh image. This is much closer to how we normally run commands for local development. Real humans don’t delete all their code and re-clone it from GitHub every time we need to do a new build! Instead, we re-run the command in the same directory. Modern tools then take advantage of local caches; Tilt runs commands with the same approach, but inside a container.
- What about
This function is imported from
load call at the top of the Tiltfile:
(Extensions are open-source packaged functions that extend the capability Tilt; check out the docs for more info.)
docker_build_with_restart works just like the
docker_build call you’re used to, except that at the end of every Live Update, it restarts your process–in this case, it runs the newly built Go
binary. Notice the extra argument
entrypoint (in this example,
/go/bin/fe): this is the command
that you want to run on container start and re-run on Live Update.
For languages/frameworks like Node or Flask that have hot reloading (i.e., they can pick up code
changes without restarting the process), you don’t need to restart your process. For instance, the
numbers app takes advantage of Flask’s hot reloading, and thus doesn’t need a
In this guide, we explored just a few of the functions we can use in a
to keep your build fast. For even more functions and tricks,
read the complete Tiltfile API reference.
For more details on Live Update, see the Live Update Reference Documentation.
If you need more specifics on how to set up Live Update with your programming language of choice, all our major example projects use Live Update: