generated from br3ndonland/template-python
-
Notifications
You must be signed in to change notification settings - Fork 17
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
Use BuildKit for Docker builds #54
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
Previously, build-time dependencies for building Python packages with binary extensions were installed and uninstalled in one `RUN` command, as they were only needed to install some dependencies on Alpine Linux. However, this also meant that build-time dependencies were not available to later installation steps, such as installing FastAPI dependencies. pydantic has binary extensions, and although it now provides wheels with the `musllinux` tag (for Alpine), inboard should account for the possibility that packages like pydantic might need to build from source. This commit will refactor build-time dependency installation into two steps. The dependencies will be installed in the new `builder` stage, then uninstalled at the end of each subsequent stage.
This commit will refactor the Dockerfile examples in the docs to use heredoc syntax, and will also add a tip explaining the syntax.
This commit will add `--link` to `COPY` commands in the Dockerfile. This allows re-use of these layers, even when layers built previously change. https://github.com/moby/buildkit/blob/HEAD/frontend/dockerfile/docs/syntax.md
The `BUILDKIT_INLINE_CACHE` build argument tells Docker to write cache metadata into the image during `docker build`. The image can then be used as a cache source for subsequent builds. The build argument will be provided with the `docker build` command. The build argument could be provided directly within the Dockerfile, but BuildKit does not offer any guidance on where it goes. It could either be supplied before the first `FROM`, or after the first `FROM`, and could work differently in each case. https://docs.docker.com/engine/reference/commandline/build/#specifying-external-cache-sources
`--cache-from` allows build commands to specify external cache sources. The Docker build was previously caching from the official Python image. With the BuildKit inline cache metadata provided by images built with `BUILDKIT_INLINE_CACHE=1`, layers from inboard can now also be cached. The inboard caching may not kick in until after this PR is merged, because images must first be pushed to a registry before cache metadata can be read. The standard caching mechanism may not be effective for the multi-stage builds used here, so `--cache-from` may not end up reducing build times. https://docs.docker.com/engine/reference/commandline/build/#specifying-external-cache-sources
Now that Dockerfile 1.4 is in stable release, this commit will relax the Dockerfile version from 1.4 to 1, to allow further 1.x releases. https://github.com/moby/buildkit/blob/f4eb826799e53547c793bfa83a035b8e24a2b88d/frontend/dockerfile/docs/reference.md
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
This PR will update Docker builds to use BuildKit, a next-generation build back-end that can be used with front-ends including
buildctl
,docker
, anddocker buildx
.BuildKit supports some helpful features, including:
RUN
commands to be written like shell scripts, instead of having to jam commands into long run-on lines.COPY --link
, which allows layers to be re-used, even if layers built previously have changedRUN --mount
, which allows advanced mounting and caching of files during builds, as well as access to secrets without baking the secrets into the final image layersRUN --network
, which allows advanced networking configurationIn addition to the
buildctl
front-end, Docker confusingly offers two front-end options for working with the BuildKit back-end:DOCKER_BUILDKIT=1 docker build
, using the same Docker CLI commands as usual, but with BuildKit as a back-end instead of the legacy (but apparently not deprecated) build back-enddocker buildx build
, invoking a Docker CLI plugin which also uses BuildKit as a back-endThe differences between these two options are poorly-documented, and it is unclear why the Buildx features aren't included in the mainline Docker CLI. The
DOCKER_BUILDKIT=1 docker build
option will be used.Changes
Dockerfile
RUN
command were previously added to thebase
stage to support Alpine Linux (Add support for Alpine Linux #37) and Debian "slim" Linux (Add support for Debian slim Docker images #38).base
stage intobuilder
andbase
stages (thebuilder
name comes from the "builder" pattern discussed in the Docker docs)builder
stage, install build-time dependencies and Python packages (but don't uninstall the build-time dependencies yet, as the previousRUN
command did)base
,starlette
, andfastapi
stages, start withFROM builder
, install any additional packages, and then uninstall build-time dependenciesRUN
command, as they were only needed to install some dependencies on Alpine Linux. However, this also meant that build-time dependencies were not available to later installation steps, such as installing FastAPI dependencies. The FastAPI dependency pydantic has binary extensions, and although it now provides wheels with themusllinux
tag (for Alpine), inboard should account for the possibility that packages like pydantic might need to build from source.builder
stage, then uninstalled at the end of each subsequent stage.COPY --link
to improve layer cachingCOPY --link
allows re-use of layers, even when layers built previously have changed.docker build
commandDOCKER_BUILDKIT=1 docker build
option will be used.BUILDKIT_INLINE_CACHE
Docker build argumentBUILDKIT_INLINE_CACHE
build argument tells Docker to write cache metadata into the image duringdocker build
. The image can then be used as a cache source for subsequent builds.docker build
command. The build argument could be provided directly within the Dockerfile, but BuildKit does not offer clear guidance on where it goes. It could either be supplied before the firstFROM
, or after the firstFROM
, and could work differently in each case.BUILDKIT_INLINE_CACHE
build argument, but they shouldn't be a concern for this project.docker build --cache-from
for inboard--cache-from
allows build commands to specify external cache sources.BUILDKIT_INLINE_CACHE=1
, layers from inboard can now also be cached.--cache-from
may not end up reducing build times. See notes section for additional info on caching in GitHub Actions.Docs
TODOs
Build Starlette and FastAPI images concurrently?Use the GitHub Actions external cache source?Notes
Build concurrency
BuildKit automatically runs build stages concurrently when possible. Unfortunately, tags can't be specified for intermediate stages/targets, and inboard needs to specify tags for each stage. Docker recommends multiple builds for multiple targets, so inboard will continue using separate build commands for each stage.
GitHub Actions external cache source
At this time, the caching APIs are confusing and experimental. There are three different caching APIs, two cache export modes, and four "exporters."
Caching APIs:
--cache-from
flag.--cache-from
allows build commands to specify external cache sources. The docs on use of this flag are confusing and poorly written, but it appears that this option usesmin
caching mode, which does not cache intermediate stages.buildctl
front-end offers different flags,--export-cache
and--import-cache
, which apparently support at least two modes and at least four "exporters."mode=min
. The BuildKit README saysmin
only caches layers from the final image, and not from intermediate build stages.mode=max
. This mode can read layer data from intermediate stages in multi-stage builds.inline
: "embed the cache into the image, and push them to the registry together" (isn't this specified byBUILDKIT_INLINE_CACHE=1
?)gha
: "export to GitHub Actions cache"local
: "export to a local directory"registry
: "push the image and the cache separately"--cache-from
as the Docker CLI does, but accepts different values, and also offers a--cache-to
flag that apparently supportsmode=min
andmode=max
.In addition to deciphering the confusing caching APIs, there are other considerations needed:
docker build
.Trying to figure out all the confusion around caching takes inordinate amounts of human time, and in the case of this project, would only save negligible amounts of machine time (without caching, Docker builds only take 1-3 minutes of machine time). Not worth it at all.
Related
docker build
- Specifying external cache sources