Skip to content

Commit 4267ab6

Browse files
committed
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 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017jPxeenJt19PJStMMeb1Em
1 parent aa72ac3 commit 4267ab6

3 files changed

Lines changed: 34 additions & 9 deletions

File tree

‎README.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ daemon automatically. The host must permit nested user namespaces — in a Coder
132132
run the workspace container with `privileged = true` (or the equivalent `--userns` setup), and call
133133
`dockerd-rootless-start` from `startup_script` so Docker is ready on boot.
134134

135+
Both variables are defaults only: a `DOCKER_HOST` provided by the environment (workspace template,
136+
`docker run -e`, mounted host socket, remote daemon) is left untouched. `dockerd-rootless-start`
137+
respects it too — if a daemon already answers there it starts nothing, and if the value is a unix
138+
`.../docker.sock` path with no daemon behind it, the rootless daemon is started on that socket.
139+
135140
## Development
136141

137142
Images are built and tested per template with the provided `Makefile`. `DOCKER_VARIANT` selects the

‎fx/Dockerfile‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ ENV GOROOT=/usr/local/go
99
ENV GOPATH=/home/coder/go
1010
ENV PATH=$GOROOT/bin:$GOPATH/bin:$PATH
1111

12-
# Rootless Docker (docker-in-docker without privileged root)
12+
# Rootless Docker (docker-in-docker without privileged root).
13+
# Defaults only — override either at runtime (e.g. to use a mounted host socket
14+
# or a remote daemon) and the profile and startup script honour the override.
1315
ENV XDG_RUNTIME_DIR=/run/user/1000
1416
ENV DOCKER_HOST=unix:///run/user/1000/docker.sock
1517

@@ -117,7 +119,7 @@ RUN \
117119
echo '' >> /etc/profile && \
118120
echo '# Rootless Docker' >> /etc/profile && \
119121
echo 'export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"' >> /etc/profile && \
120-
echo 'export DOCKER_HOST="unix://${XDG_RUNTIME_DIR}/docker.sock"' >> /etc/profile && \
122+
echo 'export DOCKER_HOST="${DOCKER_HOST:-unix://${XDG_RUNTIME_DIR}/docker.sock}"' >> /etc/profile && \
121123
# OWNERSHIP (coder can upgrade tools) ######################################
122124
chown coder:coder /usr/local/bin/claude /usr/local/bin/opencode 2>/dev/null || true && \
123125
chown -R coder:coder /home/coder/go 2>/dev/null || true && \

‎fx/dockerd-rootless-start.sh‎

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,42 @@
88
# dockerd-rootless-start
99
# docker run --rm hello-world
1010
#
11+
# A DOCKER_HOST already present in the environment is respected: if a daemon is
12+
# reachable there, nothing is started; if it is a unix socket with no daemon
13+
# behind it, dockerd is started on that socket.
14+
#
1115
# Note: the host must allow user namespaces. In Coder, run the container
1216
# with --userns-host or the equivalent template option.
1317
set -euo pipefail
1418

1519
uid="$(id -u)"
16-
export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/${uid}}"
17-
export DOCKER_HOST="unix://${XDG_RUNTIME_DIR}/docker.sock"
20+
export DOCKER_HOST="${DOCKER_HOST:-unix://${XDG_RUNTIME_DIR:-/run/user/${uid}}/docker.sock}"
21+
22+
if docker info >/dev/null 2>&1; then
23+
echo "docker daemon already reachable at ${DOCKER_HOST}"
24+
exit 0
25+
fi
26+
27+
# dockerd-rootless.sh listens on ${XDG_RUNTIME_DIR}/docker.sock, so derive the
28+
# runtime dir from DOCKER_HOST to keep the daemon and the CLI in agreement.
29+
case "$DOCKER_HOST" in
30+
unix://*/docker.sock)
31+
socket="${DOCKER_HOST#unix://}"
32+
export XDG_RUNTIME_DIR="$(dirname "$socket")"
33+
;;
34+
*)
35+
echo "no daemon reachable at DOCKER_HOST=${DOCKER_HOST}" >&2
36+
echo "rootless dockerd can only be started on a unix .../docker.sock path;" >&2
37+
echo "unset DOCKER_HOST to use the default rootless socket" >&2
38+
exit 1
39+
;;
40+
esac
1841

1942
# /run/user/<uid> lives on tmpfs and is recreated on every container start.
2043
if [ ! -d "$XDG_RUNTIME_DIR" ]; then
2144
sudo install -d -m 0700 -o "$uid" -g "$(id -g)" "$XDG_RUNTIME_DIR"
2245
fi
2346

24-
if docker info >/dev/null 2>&1; then
25-
echo "rootless dockerd already running at ${DOCKER_HOST}"
26-
exit 0
27-
fi
28-
2947
echo "starting rootless dockerd ..."
3048
nohup dockerd-rootless.sh >/tmp/dockerd-rootless.log 2>&1 &
3149

0 commit comments

Comments
 (0)