From 2c56d8679f2d6ff05e807a7f731c5acfc2037040 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 10 Aug 2026 17:11:14 +0000 Subject: [PATCH] fx: respect an externally provided DOCKER_HOST The rootless Docker setup hardcoded DOCKER_HOST in /etc/profile and in dockerd-rootless-start, clobbering any value supplied by the environment (workspace template, docker run -e, mounted host socket, remote daemon). Both now treat the rootless socket as a fallback only. The startup script skips starting a daemon when one already answers at DOCKER_HOST, derives XDG_RUNTIME_DIR from a provided unix .../docker.sock so dockerd and the CLI agree on the path, and fails with a clear message for non-unix hosts it cannot serve. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_017jPxeenJt19PJStMMeb1Em --- README.md | 3 +++ fx/Dockerfile | 5 +++-- fx/dockerd-rootless-start.sh | 29 ++++++++++++++++++++++------- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index dce806c..23cd609 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,9 @@ daemon automatically. The host must permit nested user namespaces — in a Coder run the workspace container with `privileged = true` (or the equivalent `--userns` setup), and call `dockerd-rootless-start` from `startup_script` so Docker is ready on boot. +Both variables are defaults. If `DOCKER_HOST` is already set, the image and the script keep that +value. The script starts no daemon if one answers there. + ## Development Images are built and tested per template with the provided `Makefile`. `DOCKER_VARIANT` selects the diff --git a/fx/Dockerfile b/fx/Dockerfile index 98f825e..57f118b 100644 --- a/fx/Dockerfile +++ b/fx/Dockerfile @@ -20,7 +20,8 @@ ENV GOROOT=/usr/local/go ENV GOPATH=/home/coder/go ENV PATH=$GOROOT/bin:$GOPATH/bin:$PATH -# Rootless Docker (docker-in-docker without privileged root) +# Rootless Docker (docker-in-docker without privileged root). +# Defaults. The environment can override them. ENV XDG_RUNTIME_DIR=/run/user/1000 ENV DOCKER_HOST=unix:///run/user/1000/docker.sock @@ -127,7 +128,7 @@ RUN \ echo '' >> /etc/profile && \ echo '# Rootless Docker' >> /etc/profile && \ echo 'export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"' >> /etc/profile && \ - echo 'export DOCKER_HOST="unix://${XDG_RUNTIME_DIR}/docker.sock"' >> /etc/profile && \ + echo 'export DOCKER_HOST="${DOCKER_HOST:-unix://${XDG_RUNTIME_DIR}/docker.sock}"' >> /etc/profile && \ # OWNERSHIP (coder can upgrade tools) ###################################### chown coder:coder /usr/local/bin/claude /usr/local/bin/opencode && \ chown -R coder:coder /home/coder/go && \ diff --git a/fx/dockerd-rootless-start.sh b/fx/dockerd-rootless-start.sh index aac2b1b..f223b0a 100644 --- a/fx/dockerd-rootless-start.sh +++ b/fx/dockerd-rootless-start.sh @@ -8,24 +8,39 @@ # dockerd-rootless-start # docker run --rm hello-world # +# A DOCKER_HOST from the environment is used if set. +# # Note: the host must allow user namespaces. In Coder, run the container # with --userns-host or the equivalent template option. set -euo pipefail uid="$(id -u)" -export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/${uid}}" -export DOCKER_HOST="unix://${XDG_RUNTIME_DIR}/docker.sock" +export DOCKER_HOST="${DOCKER_HOST:-unix://${XDG_RUNTIME_DIR:-/run/user/${uid}}/docker.sock}" + +if docker info >/dev/null 2>&1; then + echo "docker daemon already reachable at ${DOCKER_HOST}" + exit 0 +fi + +# dockerd-rootless.sh listens on ${XDG_RUNTIME_DIR}/docker.sock. Set the runtime +# dir from DOCKER_HOST so the daemon and the CLI use the same socket. +case "$DOCKER_HOST" in + unix://*/docker.sock) + socket="${DOCKER_HOST#unix://}" + export XDG_RUNTIME_DIR="$(dirname "$socket")" + ;; + *) + echo "no daemon at DOCKER_HOST=${DOCKER_HOST}" >&2 + echo "rootless dockerd needs a unix .../docker.sock path; unset DOCKER_HOST for the default" >&2 + exit 1 + ;; +esac # /run/user/ lives on tmpfs and is recreated on every container start. if [ ! -d "$XDG_RUNTIME_DIR" ]; then sudo install -d -m 0700 -o "$uid" -g "$(id -g)" "$XDG_RUNTIME_DIR" fi -if docker info >/dev/null 2>&1; then - echo "rootless dockerd already running at ${DOCKER_HOST}" - exit 0 -fi - echo "starting rootless dockerd ..." nohup dockerd-rootless.sh >/tmp/dockerd-rootless.log 2>&1 &