Context
Found during code review of PR #620. The app runtime image runs as root by default (no USER directive in the runtime stage). This is intentional and documented (Dockerfile:128-139): the host X11 auth cookie is bind-mounted read-only at mode 0600 owned by the host user, so a non-root container user cannot read it and Swing fails with "Can't connect to X11 window server".
The fast-sim runtime, by contrast, runs as a non-root app user (no X11 requirement).
The tradeoff to re-evaluate
Root runtime is a real privilege-escalation surface for a dev tool, e.g. the ./artifacts/app bind mount becomes root-owned on the host if the container writes there.
A safer middle ground exists that the PR did not appear to adopt: run the container as a user whose UID matches the host user — e.g. --user $(id -u):$(id -g) at docker compose run time, or a RUNTIME_UID/RUNTIME_GID ARG built from the host UID. A matching-UID user can read the 0600 X11 cookie without root. This is the standard pattern for X11-forwarding dev containers.
Ask
Confirm whether the matching-UID option was considered and rejected for this project, or whether it was overlooked. If viable, adopt it so the app runtime is non-root like fast-sim.
If the root-runtime tradeoff is accepted as-is, consider adding a brief "Future: matching-UID runtime" note to the Dockerfile comment block so the rationale for not doing it now is captured alongside the rationale for root.
Files
Dockerfile runtime stage (no USER directive; rationale comment at lines 128-139)
docker-compose.yml app service
Severity
Important (confirm-only) — this is an intentional, documented decision and matches #620's stated tradeoff, so it is not a defect of #620. Filed so the matching-UID option is evaluated on its own merits rather than implicitly locked in by #620.
Context
Found during code review of PR #620. The
appruntime image runs as root by default (noUSERdirective in the runtime stage). This is intentional and documented (Dockerfile:128-139): the host X11 auth cookie is bind-mounted read-only at mode 0600 owned by the host user, so a non-root container user cannot read it and Swing fails with "Can't connect to X11 window server".The
fast-simruntime, by contrast, runs as a non-rootappuser (no X11 requirement).The tradeoff to re-evaluate
Root runtime is a real privilege-escalation surface for a dev tool, e.g. the
./artifacts/appbind mount becomes root-owned on the host if the container writes there.A safer middle ground exists that the PR did not appear to adopt: run the container as a user whose UID matches the host user — e.g.
--user $(id -u):$(id -g)atdocker compose runtime, or aRUNTIME_UID/RUNTIME_GIDARGbuilt from the host UID. A matching-UID user can read the 0600 X11 cookie without root. This is the standard pattern for X11-forwarding dev containers.Ask
Confirm whether the matching-UID option was considered and rejected for this project, or whether it was overlooked. If viable, adopt it so the
appruntime is non-root likefast-sim.If the root-runtime tradeoff is accepted as-is, consider adding a brief "Future: matching-UID runtime" note to the Dockerfile comment block so the rationale for not doing it now is captured alongside the rationale for root.
Files
Dockerfileruntime stage (noUSERdirective; rationale comment at lines 128-139)docker-compose.ymlappserviceSeverity
Important (confirm-only) — this is an intentional, documented decision and matches #620's stated tradeoff, so it is not a defect of #620. Filed so the matching-UID option is evaluated on its own merits rather than implicitly locked in by #620.