Building images with Docker Buildx
protect-dockerd supports the docker buildx docker-container driver, which runs BuildKit itself inside a Protect zone and drives it entirely through the ordinary container and exec Docker Engine API.
This guide assumes you’re already running protect-dockerd.
See Running containers with the Docker CLI if you haven’t set it up yet.
Why the docker-container driver
docker buildx can reach BuildKit two ways:
| Driver | Where BuildKit runs |
|---|---|
docker (default) | Embedded inside dockerd |
docker-container | In a container the driver launches |
With the default docker driver, build facilities are embedded into the privileged dockerd daemon.
protect-dockerd doesn’t implement such facilities itself.
Instead, the docker-container driver creates a BuildKit builder container inside a Protect zone—like any container managed by protect-dockerd—and tunnels BuildKit’s gRPC protocol inside a docker exec session to drive the image build.
Because BuildKit operates within a privileged container, the containment boundaries enforced by the Protect zone are paramount to minimizing its potential blast radius.
Create a builder
docker buildx create --name mybuilder --driver docker-container --useprotect-dockerd records the builder container, pulls the BuildKit builder image, and creates a privileged container for it.
The builder container is started on the first image build, but can also be bootstrapped manually:
docker buildx inspect --bootstrap mybuilderA successful bootstrap reports the builder instance running—buildkitd is now running inside a Protect zone.
Build
docker buildx build --builder mybuilder -t myimage:dev .The Dockerfile, build context, and all solve traffic tunnel through a single docker exec stream into the zone’s buildkitd.
By default, the result stays in BuildKit’s cache inside the zone—nothing is pulled out unless you ask for it.
Get the image out
To get the container image out of the zone after the build has completed, you must opt into one of the following actions:
| Flag | What happens |
|---|---|
| (none) | Resulting image stays in BuildKit’s cache inside the zone |
--load | Tarball streamed back over the exec tunnel and imported into the Protect image store |
--push | buildkitd pushes straight to the registry from inside the zone; the image never reaches the Protect image store |
docker buildx build --builder mybuilder --load -t myimage:dev .
docker run --rm myimage:dev--push isn’t limited by anything in protect-dockerd—zone egress works the same as any other outbound connection from a workload.Tear down
docker buildx rm mybuilderThis stops and removes the builder container, which tears down its zone and workload.
Current limitations
- No custom
buildkitdconfig.--buildkitd-configrelies on copying a config file into the container before it starts.protect-dockerddoes not honor that option and therefore supports default builders only. - No persistent BuildKit cache. buildx typically mounts a named volume at
/var/lib/buildkitto persist cache across builder re-creations.protect-dockerdonly honors bind mounts, so this volume is silently dropped—every fresh builder starts with a cold cache. - Multi-platform
--loadtakes the first manifest only. Single-platform builds are unaffected.