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
62 lines
3.4 KiB
Markdown
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.
|