Files
werkator/docs/prs/2026-10-01-PR#86-rootlesskit-host-override.md
b37855e04a
werkator build succeeded after 03:40
werkator/deploy build succeeded after 00:07
feat(docker): ask rootlesskit where a rootless daemon publishes ports (#86)
With the slirp4netns port driver a rootless daemon publishes ports on
its child address only, not on localhost. Werkator now asks rootlesskit
(GET /v1/info on dockerd-rootless/api.sock) before every Docker build
and passes that address as TESTCONTAINERS_HOST_OVERRIDE, in both network
modes; the builtin driver keeps the defaults. A daemon switched between
drivers needs no configuration change. docker.env still wins.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: mhoennig <michael@hoennig.de>
Reviewed-on: #86
2026-10-01 11:59:07 +02:00

62 lines
3.4 KiB
Markdown

> **WARNING:** This document describes only the change applied in this PR.
> It may already be outdated once the next PR is merged.
> Historic PR-documentation is not maintained along with new PRs — treat it as a snapshot, not as current documentation.
## The Problem
On vm4006 the rootless Docker daemon switched from the `builtin` to the `slirp4netns` port driver at a reboot on 2026-10-01; the host's configuration management had rewritten its unit a week before.
With `slirp4netns`, published ports listen only on the child address of the daemon's network namespace, `10.0.2.100`, not on `localhost`.
Every Testcontainers test failed with "connection refused".
PR#85 let the host write the address into `docker.env`.
But the address is rootlesskit's default, not a constant, and the driver can change back just as unannounced; each change would need a hand-edited configuration again.
## Non-Goals
- No support for rootful daemons with unusual port setups; their defaults stay.
- No change to how a build script inside the container finds the address; it reads `TESTCONTAINERS_HOST_OVERRIDE`.
## The Scenarios
### Feature: Werkator asks the daemon where it publishes ports
#### Scenario#86.01: rootlesskit names the address
So that the address follows the daemon, both ways, without a configuration change.
- **Given** a rootless daemon whose rootlesskit API reports the `slirp4netns` port driver
- **Then** the published-port host is the child address it reports
- **Given** the `builtin` driver, a rootful daemon, a missing API or an unreadable answer
- **Then** there is none, and the defaults apply
##### Verified by
- [RootlessKitPortsTest](../../src/test/kotlin/de/hoennig/werkator/build/RootlessKitPortsTest.kt) — a real HTTP exchange over a Unix socket with vm4006's answer, the builtin driver, rootful, missing and unreadable cases
- By hand on vm4006: `curl --unix-socket /run/user/10000/dockerd-rootless/api.sock http://rootlesskit/v1/info` answers as the test assumes, and `10.0.2.100:<port>` is reachable from a host-network and from a bridge container, `host.docker.internal:<port>` is not.
#### Scenario#86.02: The build gets it as TESTCONTAINERS_HOST_OVERRIDE
- **Given** a published-port host from rootlesskit
- **Then** the build container gets it as `TESTCONTAINERS_HOST_OVERRIDE`, with `network: host` and on the bridge network alike
- **And** an entry in `docker.env` still wins
##### Verified by
- [DockerBuildRunnerTest](../../src/test/kotlin/de/hoennig/werkator/build/DockerBuildRunnerTest.kt) — both network modes, and `docker.env` winning
## The Solution
`RootlessKitPorts` sends `GET /v1/info` to `dockerd-rootless/api.sock` next to the daemon socket, over a Unix domain socket channel, with a two-second limit.
It takes `networkDriver.childIP` when `portDriver.driver` is `slirp4netns` and the address is IPv4, and logs a change of state once.
`DockerBuildRunner` asks it on every build, for the located socket whether or not the build mounts it.
No `curl` is needed on the host, and nothing is cached: a driver change takes effect at the next build.
## Additional Changes
- `docs/configuration.md` and the architecture skill describe how the variable is set.
- Version 1.25.0 with its release note.
## Follow-up PRs
- vm4006: remove `TESTCONTAINERS_HOST_OVERRIDE` from the machine config once this runs there.
- hsadmin-ng: `tools/smoke-test` reads `TESTCONTAINERS_HOST_OVERRIDE` for its own database.