Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions fx/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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 && \
Expand Down
29 changes: 22 additions & 7 deletions fx/dockerd-rootless-start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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/<uid> 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 &

Expand Down