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 &