Dockers idea of the build context is among its most restrictive and misunderstood characteristics. The build context defines the neighborhood files and folders it is possible to reference in your Dockerfile. Content outside it can’t be used, which frequently hinders complex build procedures.
BuildKit v0.8 improves this example by permitting you to use multiple contexts with each build you perform. This helps it be better to reference files that could have a home in completely separate locations, like a file inside your working directory and a dependency at a remote URL.
In this post well explain why multiple build contexts are of help and how you may use them with the most recent Docker CLI release. First lets recap what the build context is and just why more and more people have come across issues previously.
Reason for the Build Context
Docker is daemon-based. The procedure that runs your image builds is in addition to the CLI process that issues the command. The daemon could possibly be located on a remote host which cant directly access your machines filesystem.
The build context identifies the files which are used in the Docker daemon whenever a build occurs. For this reason only content within the context could be referenced by your Dockerfile.
Its common to perform
docker build with
. as its argument, making your working directory the build context:
docker build -t my-website:latest .
This permits references to any path within your working directory:
FROM httpd:latest COPY index.html /var/www/html/index.html
You cant get in touch with copy anything above the working directory in your filesystem:
FROM httpd:latest COPY index.html /var/www/html/index.html COPY ../company-css/company.css /var/www/html/company.css
Every file you will need in your container image must exist under an individual directory which you can use because the build context. This is often problematic in situations just like the one shown above, where you intend to pull in dependencies from sources that arent in work tree.
Using Multiple Build Contexts
Multiple build contexts are actually supported in BuildKit v0.8 and newer once you opt-in to Dockerfile syntax v1.4. These releases are shipped with the Docker CLI beginning with version 20.10.13. You have to be in a position to utilize them today if youre running the most recent version of Docker.
You need to build your image with BuildKit to utilize multiple contexts. They arent supported by the legacy builder. Utilize the
docker buildx build command rather than plain
$ docker buildx build -t my-website:latest .
You can now utilize the
--build-context flag to define multiple named build contexts:
$ docker buildx build -t my-website:latest . --build-context company-css=../company-css --build-context company-js=../company-js
Adjust your Dockerfile to reference content from these contexts:
#syntax=docker/dockerfile:1.4 FROM httpd:latest COPY index.html /var/www/html/index.html COPY --from=company-css /company.css /var/www/html/company.css COPY --from=company-js /company.js /var/www/html/company.js
This illustrates ways to copy in files and folders that lie outside your primary build context, regardless of their position in your filesystem tree.
The Dockerfile v1.4 syntax declaration must enable support for the feature. After that you can utilize the
--from option with
COPY instructions to pull in files from named build contexts, much like referencing a resource within an earlier build stage.
Multiple build contexts modify the resource resolution order for the
--from flag. Docker will now match the main element you supply (
--from=key) utilizing the following procedure:
- Search for a named build context set with the
- Search for a youthful build stage made up of
FROM my-image:latest AS stage-name.
- Develop a new inline build stage utilizing the given key because the stages image.
This implies you may use named contexts to override remote dependencies defined using build stages.
Think about this example:
#syntax=docker/dockerfile:1.4 FROM my-org/company-scss:latest AS css RUN sass company.scss company.css FROM httpd:latest COPY index.html /var/www/html/index.html COPY --from=css /company.css /var/www/html/company.css
This Docker image pulls in a few remote resources from another shared Docker image. This may create difficulties when youre testing assembling your project there may be a bug in the dependency that you desire to quickly patch.
Named build contexts enable you to override the
css stage name to provide an area file instead:
$ docker buildx build -t my-website:latest . --build-context css=css/
This can copy your working directorys
css/company.css file in to the final image, rather than the version given by the
The resolution order means overrides could be applied even though your image doesnt use named build stages. By defining a build context with exactly the same name being an image, your Dockerfile will pull in content from that context, rather than the original registry image.
$ docker buildx build -t my-website:latest . --build-context my-org/company-scss:latest=css/
Named build contexts support all of the sources that
docker build already accepted:
--build-context my-context=../local/pathA path in your filesystem.
--build-context my-context=https://github.com/user/repo.gitA remote Git repository.
--build-context my-context=https://example.com/data.tarA remote tarball supplied by an HTTP server.
--build-context my-context=docker-image://busybox:latestThis content of another Docker image.
Remote sources further simplify dependency overrides. It is possible to point right to a forked Git repository or perhaps a different Docker image tag, all while leaving your Dockerfile unchanged.
Mounting Files From the Build Context
Named build contexts use
RUN instructions too. You may use
--mount=from to perform an executable from another build context.
#syntax=docker/dockerfile:1.4 RUN --mount=from=name-of-build-context demo-executable
This mounts the file without copying it in to the current layer, assisting to improve performance.
demo-executable wont exist in the ultimate image.
Precisely Rebuilding Images
Another use case for named build contexts concerns rebuilding images later on. Dockerfiles with instructions like
FROM alpine:3.15 arent fully reproducible. Image tags are mutable so
alpine:3.15 may contain different content later on, following a new patch is released. This implies rebuilt images arent guaranteed to create exactly the same layers as their original versions.
It is possible to solve this issue by inspecting the initial builds metadata to find the precise base image that has been used:
$ docker buildx imagetools inspect --format 'json .BuildInfo' my-image:latest ... "sources": [ "type": "docker-image", "ref": "docker.io/library/alpine:3.15", "pin": "sha256:4edbd2beb5f78b1014028f4fbb99f3237d9561100b6881aabbf5acce2c4f9454" ] ...
You can now define a named build context called
alpine:3.15 that points to the precise version that has been used:
$ docker buildx build -t my-image:latest . --build-context alpine:3.15=docker-image://alpine3.15@4edbd2beb5f78b1014028f4fbb99f3237d9561100b6881aabbf5acce2c4f9454
This simplifies developing a precise rebuild of a previously created image, without needing to modify its Dockerfile.
Multiple build contexts offer you more choices for organizing complex Dockerfiles and project directory trees. They solve the longstanding usability challenges that you might experience with an individual build context.
Named build contexts enable you to include out-of-tree dependencies and perform ad-hoc overrides. They work very well alongside Dockers existing named build stages. Combining both features can help you create modular Dockerfiles which can be customized at build time.
You may get started with multiple build contexts today by updating to Docker 20.10.13 or newer and using
docker buildx to generate your images. Standalone BuildKit distributions can be found too once you dont desire to install the complete Docker CLI.