-
Notifications
You must be signed in to change notification settings - Fork 289
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
dockercompose: fix spurious full rebuild instead of Live Update #5242
Conversation
Occasionally, when using Live Update with a Docker Compose project, a file change would trigger a full rebuild instead of Live Update despite matching a sync path. The root cause here is that the Docker Compose target watched files in addition to the image target, so there was a race: if the Docker Compose target saw the file but the image target hadn't yet, the Docker Compose builder would take over and do a full rebuild. This has probably been exacerbated by the API transition as there's now greater potential for timing-related issues like this to manifest. The reason the Docker Compose target watches for files is because in some cases, there IS no image target for a Docker Compose service. If there's no `docker_build` or `custom_build` configured, and the Docker Compose service has a `build:` section in its YAML, the Docker Compose build and deployer watched for file changes and then triggered a build via passing the `--build` flag to the `docker-compose up` call. To address this, the Docker Compose target now behaves more like a Kubernetes target. It does not watch for any files. Instead, image targets are created for both services that will be managed by Tilt (via `docker_build` or `custom_build`) as well as those that will be built by Docker Compose. (NOTE: If a Docker Compose service has no `build:` section and there's no corresponding `docker_build` or `custom_build` call for it, there will be no target, as no image builds will occur. This is commonly seen for infra deps that are pulled from a registry.) The image targets for Docker Compose managed builds have a new `BuildDetails` type of `DockerComposeBuild` to go along with the pre-existing `DockerBuild` and `CustomBuild` types. This ensures that all file changes are tie to the image, so it will pass through the `LiveUpdateBuildAndDeployer` first, and fallback to the `DockerComposeBuildAndDeployer` if not Live Update-eligible. (This is always the case for `DockerComposeBuild` targets currently!) The `DockerComposeBuildAndDeployer` looks at the image targets and either builds the set of Tilt-managed images for the service OR delegates to `docker-compose up` by including the `--build` flag. The `DockerComposeBuild` targets are created during Docker Compose assembly during Tiltfile loading if no Tilt-managed builder exists. This is kinda icky - it'd probably be nicer to create these as stubs when `docker_compose()` is called and allow `docker_build` and `custom_build` to override them, but that's a bigger yak shave than practical for this fix.
Apologies for the number of changes here - there's unfortunately lots of tiny ripples [especially in tests], and I couldn't figure out a great way to chunk it because it's a pretty atomic cut-over.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice cleanup! Explanation makes sense to me, code and functionality are in better shape than before even with the caveats.
high-level question: how do you think we should represent this in the api server? i was originally assuming that the DockerComposeUp object would know which images come from a DockerImage (handled by tilt) and which images are handled by the DockerComposeUp object (handled by docker-compose). But this PR introduces a second possibility - that we have some sort of DockerComposeImage object in the system. But I'm not sure. what do you think? |
Good question! FWIW my decision for approach of modeling this as close to the image builds for K8s was based on hopefully making API transitions easier. I actually see a few possibilities:
The common thread here is that I believe it makes sense to split the build from the deploy long-term, so that we can have consistent semantics across K8s + DC. |
Occasionally, when using Live Update with a Docker Compose project,
a file change would trigger a full rebuild instead of Live Update
despite matching a sync path.
The root cause here is that the Docker Compose target watched files
in addition to the image target, so there was a race: if the Docker
Compose target saw the file but the image target hadn't yet, the
Docker Compose builder would take over and do a full rebuild. This
has probably been exacerbated by the API transition as there's now
greater potential for timing-related issues like this to manifest.
The reason the Docker Compose target watches for files is because
in some cases, there IS no image target for a Docker Compose service.
If there's no
docker_build
orcustom_build
configured, and theDocker Compose service has a
build:
section in its YAML, the DockerCompose build and deployer watched for file changes and then triggered
a build via passing the
--build
flag to thedocker-compose up
call.
To address this, the Docker Compose target now behaves more like a
Kubernetes target. It does not watch for any files. Instead, image
targets are created for both services that will be managed by Tilt
(via
docker_build
orcustom_build
) as well as those that willbe built by Docker Compose. (NOTE: If a Docker Compose service has
no
build:
section and there's no correspondingdocker_build
orcustom_build
call for it, there will be no target, as no imagebuilds will occur. This is commonly seen for infra deps that are
pulled from a registry.)
The image targets for Docker Compose managed builds have a new
BuildDetails
type ofDockerComposeBuild
to go along with thepre-existing
DockerBuild
andCustomBuild
types. This ensuresthat all file changes are tied to the image, so it will pass through
the
LiveUpdateBuildAndDeployer
first, and fallback to theDockerComposeBuildAndDeployer
if not Live Update-eligible. (Thisis always the case for
DockerComposeBuild
targets currently!)The
DockerComposeBuildAndDeployer
looks at the image targets andeither builds the set of Tilt-managed images for the service OR
delegates to
docker-compose up
by including the--build
flag.The
DockerComposeBuild
targets are created during Docker Composeassembly during Tiltfile loading if no Tilt-managed builder exists.
This is kinda icky - it'd probably be nicer to create these as
stubs when
docker_compose()
is called and allowdocker_build
and
custom_build
to override them, but that's a bigger yak shavethan practical for this fix.
Fixes #5196.