Skip to content

fix(docker): give rootlesskit a port driver, so -p means something - #13

Merged
TheHefty merged 1 commit into
mainfrom
fix/rootless-port-driver
Aug 10, 2026
Merged

fix(docker): give rootlesskit a port driver, so -p means something#13
TheHefty merged 1 commit into
mainfrom
fix/rootless-port-driver

Conversation

@TheHefty

Copy link
Copy Markdown
Owner

docker run -p published nothing in this image. docker port reported
0.0.0.0:<port> and no connection succeeded — not even from inside the container
itself
, on 127.0.0.1.

Cause

RootlessKit defaults --port-driver to none, which maps a published port inside
RootlessKit's own namespace and forwards it nowhere. svc-dockerd-rootless/run never
passed the flag.

The flag normally arrives with dockerd-rootless.sh, which sets it explicitly. This
image cannot use that script — docker-ce-rootless-extras is unavailable, as
core/Dockerfile.frag section 1 already records — so the invocation was reimplemented
by hand, and this is the piece that got lost. Everything else was right:
slirp4netns is installed, networking works, containers build and run, docker exec
works. Only forwarding was missing, which is why it went unnoticed.

The comment was asserting the opposite

The block above the invocation claimed publishing worked, and named Testcontainers as
a consumer that reaches a published port this way. Nothing had ever exercised it. It is
rewritten to say what actually happens and why the flag has to be there.

Isolation

Nothing is traded. The host Docker socket is still not mounted, no privilege is
added, the user namespace is unchanged. This turns on forwarding for ports of
containers this daemon already creates — the capability the file already claimed to
have.

--disable-host-loopback is orthogonal and stays. It blocks a nested container dialling
back into its parent; it has nothing to do with the parent reaching a published port.

builtin is what dockerd-rootless.sh defaults to and is the faster of the two;
slirp4netns is the fallback if a workload ever needs the source IP preserved.

Not verified

Proving it needs an image rebuild and a container restart, which ends the session that
found it. The reproduction is in the commit and is two commands:

docker run -d --rm -p 15432:5432 -e POSTGRES_PASSWORD=x postgres:18-alpine
bash -c '</dev/tcp/127.0.0.1/15432' && echo reachable || echo refused

Today that prints refused while docker port shows the mapping.

How it was found

A consumer project reached for Testcontainers and could not connect. Docker itself was
fine — a container ran and answered over docker exec — which is what pointed at
forwarding rather than at the daemon.

🤖 Generated with Claude Code

https://claude.ai/code/session_01TjvhhztqTYoQhJcJTgXdRb

`docker run -p` published nothing. `docker port` reported 0.0.0.0:<port>
and no connection succeeded, not even from inside this container on
127.0.0.1 — because RootlessKit defaults --port-driver to `none`, which
maps the port inside its own namespace and forwards it nowhere.

The flag normally arrives with dockerd-rootless.sh, which passes it
explicitly. This image cannot use that script — docker-ce-rootless-extras
is unavailable, as core/Dockerfile.frag section 1 records — so the
invocation was reimplemented by hand and the flag was the piece that got
lost. Everything else was right: slirp4netns is installed, networking
works, containers run.

The comment above the invocation asserted the opposite, naming
Testcontainers as a consumer that reaches a published port this way.
Nothing had ever exercised it.

No isolation is traded for this. The host socket is still not mounted, no
privilege is added, the user namespace is unchanged. It turns on
forwarding for ports of containers this daemon already creates — exactly
the capability the file already claimed to have.

--disable-host-loopback is orthogonal and stays: it blocks a nested
container dialling into its parent, not the parent reaching a published
port.

Unverified: proving it needs an image rebuild and a container restart.
The reproduction is `docker run -d -p 15432:5432 postgres:18-alpine`
followed by a TCP connect to 127.0.0.1:15432 from this container.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TjvhhztqTYoQhJcJTgXdRb
@TheHefty
TheHefty merged commit 7d91f0e into main Aug 10, 2026
15 checks passed
@TheHefty
TheHefty deleted the fix/rootless-port-driver branch August 10, 2026 17:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant