Remove the docker module: dotfiles no longer installs Docker

Installing Docker Engine is a host/image decision, not a per-user
environment one. In Coder workspaces (unprivileged pods, no systemd) the
module ran get.docker.com on every start for a daemon that can never
run there. Where Docker is wanted, install it on the host or bake it
into the image.

Also drops the zshrc newgrp-docker hook that existed only for this
module's group change, and the docs/skills references to docker/.
docker-rootless-cgroup/ (configures Kasm's existing rootless daemon)
and bin/'s kind gate (detects a daemon) stay.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-19 13:39:59 -04:00
co-authored by Claude Opus 5
parent ffedc84cfb
commit 86b8e51646
7 changed files with 10 additions and 145 deletions
+4 -4
View File
@@ -44,9 +44,9 @@ Every module's `install.sh` satisfies all of these. Copy the shape from
## Wiring it up ## Wiring it up
**`bootstrap.sh`** — add the call. Order is load-bearing and each existing **`bootstrap.sh`** — add the call. Order is load-bearing and each existing
out-of-order entry carries a comment explaining why (`docker/` before `bin/` out-of-order entry carries a comment explaining why (`secrets/` after `bin/`
so kind's gate sees the daemon; `docker-rootless-cgroup/` last because it because it needs `op`; `docker-rootless-cgroup/` last because it needs the
needs the rootless daemon already up). If your module has an ordering rootless daemon already up). If your module has an ordering
constraint, add it *with* a comment; if it doesn't, append it near related constraint, add it *with* a comment; if it doesn't, append it near related
modules. modules.
@@ -61,7 +61,7 @@ Never commit the value itself.
## Non-systemd hosts ## Non-systemd hosts
Kasm has no systemd. Anything that would `systemctl enable` must degrade Kasm has no systemd. Anything that would `systemctl enable` must degrade
gracefully — see `docker/install.sh`, which detects the situation and no-ops gracefully — see `docker-rootless-cgroup/install.sh`, which detects the situation and no-ops
rather than failing the whole bootstrap run. rather than failing the whole bootstrap run.
## Before you're done ## Before you're done
+1 -1
View File
@@ -14,7 +14,7 @@ Everything in this repo is version-pinned on purpose. Nothing floats.
| CLI tools | `bin/install.sh` | `ver=v1.2.3` inside each `install_<name>()` | | CLI tools | `bin/install.sh` | `ver=v1.2.3` inside each `install_<name>()` |
| Node.js | `node/install.sh` | `NODE_VERSION="v24.18.0"` | | Node.js | `node/install.sh` | `NODE_VERSION="v24.18.0"` |
| MCP servers | `mcp-config/opencode.gateway.json` | `["npx", "-y", "pkg@0.0.10"]` | | MCP servers | `mcp-config/opencode.gateway.json` | `["npx", "-y", "pkg@0.0.10"]` |
| oh-my-zsh, Docker | `zsh/`, `docker/` | installed from upstream scripts — not pinned | | oh-my-zsh | `zsh/` | installed from upstream script — not pinned |
Grep before assuming: `grep -rnE 'ver=|_VERSION=|@[0-9]+\.[0-9]+' --include='*.sh' --include='*.json'` Grep before assuming: `grep -rnE 'ver=|_VERSION=|@[0-9]+\.[0-9]+' --include='*.sh' --include='*.json'`
+2 -2
View File
@@ -63,8 +63,8 @@ faithful rehearsal.
Kasm has no systemd and no rootful Docker. Anything that would `systemctl` must Kasm has no systemd and no rootful Docker. Anything that would `systemctl` must
no-op rather than abort — you can't fully rehearse this in a container, so read no-op rather than abort — you can't fully rehearse this in a container, so read
the code path and confirm the guard exists (`docker/install.sh` and the code path and confirm the guard exists (`docker-rootless-cgroup/install.sh`
`docker-rootless-cgroup/install.sh` are the references). is the reference).
## Full run ## Full run
+2 -8
View File
@@ -32,14 +32,6 @@ Already have a clone? Just run it directly:
- `git/` — sets git `user.name`/`user.email` and configures - `git/` — sets git `user.name`/`user.email` and configures
`credential.helper store` (plaintext `~/.git-credentials`, 0600) for `credential.helper store` (plaintext `~/.git-credentials`, 0600) for
HTTPS auth. HTTPS auth.
- `docker/` — installs full (rootful) Docker Engine from Docker's upstream
package repo (get.docker.com on Debian-family; the docker-ce repo wired up
directly on RHEL-family, since the convenience script rejects EL rebuilds
like Oracle Linux by name), enables the service (systemd hosts), and adds
the invoking user to the
`docker` group (takes effect at next login). No-ops where a rootless
Docker daemon is already running (e.g. Kasm) so it never fights that
setup. Uses sudo.
- `bin/` — installs userland devops CLIs as self-contained, statically - `bin/` — installs userland devops CLIs as self-contained, statically
linked release binaries into `~/.local/bin`: jq, kubectl, kubelogin (the linked release binaries into `~/.local/bin`: jq, kubectl, kubelogin (the
`kubectl oidc-login` plugin, for OIDC auth to Omni clusters), helm, k9s, `kubectl oidc-login` plugin, for OIDC auth to Omni clusters), helm, k9s,
@@ -50,6 +42,8 @@ Already have a clone? Just run it directly:
coder CLI for Coder workspaces. coder CLI for Coder workspaces.
kind is installed only when full (non-rootless) Docker is available — kind is installed only when full (non-rootless) Docker is available —
it doesn't work against rootless Docker, so it is skipped on Kasm. it doesn't work against rootless Docker, so it is skipped on Kasm.
Dotfiles does not install Docker itself; install it on the host (or bake
it into the image) where you want it.
No sudo, nothing outside `$HOME`, so tools persist across Kasm No sudo, nothing outside `$HOME`, so tools persist across Kasm
redeploys with no reinstall. Idempotent: each tool records its version redeploys with no reinstall. Idempotent: each tool records its version
under `~/.local/bin/.versions` and is skipped when the pinned version under `~/.local/bin/.versions` and is skipped when the pinned version
+1 -3
View File
@@ -66,7 +66,7 @@ fi
# #
# WHY: these used to be bare calls, so under `set -eu` the FIRST failing module # WHY: these used to be bare calls, so under `set -eu` the FIRST failing module
# aborted bootstrap and every later module silently never ran — one unsupported # aborted bootstrap and every later module silently never ran — one unsupported
# distro in docker/ was enough to leave a box with no CLIs, no npx and no # distro in one module was enough to leave a box with no CLIs, no npx and no
# ansible. The modules are independent, so a failure in one is not a reason to # ansible. The modules are independent, so a failure in one is not a reason to
# skip the rest. (bin/install.sh does the same for individual tools; this is # skip the rest. (bin/install.sh does the same for individual tools; this is
# that guard one level up.) # that guard one level up.)
@@ -79,8 +79,6 @@ run_module() {
run_module zsh run_module zsh
run_module git run_module git
# Runs before bin/ so the kind install gate can see the rootful daemon.
run_module docker
run_module bin run_module bin
# Needs op and jq from bin/. Runs before everything that consumes a secret, and # Needs op and jq from bin/. Runs before everything that consumes a secret, and
# its output is loaded into THIS process so later modules see the vault's # its output is loaded into THIS process so later modules see the vault's
-114
View File
@@ -1,114 +0,0 @@
#!/usr/bin/env sh
# docker/install.sh — install full (rootful) Docker Engine and let the
# invoking user talk to it without sudo.
#
# What it does:
# 1. Installs Docker Engine from Docker's upstream package repo. Skipped when
# `docker` is already installed. Debian-family hosts go through Docker's
# convenience script (get.docker.com); RHEL-family hosts wire up the
# docker-ce repo directly — see install_rhel() for why.
# 2. Enables and starts the service (systemd hosts only).
# 3. Adds the invoking user to the `docker` group so the daemon socket is
# usable without sudo. Takes effect at next login.
#
# Deliberately no-ops when a rootless Docker daemon is detected (e.g. Kasm
# ships its own rootless setup) — installing rootful Docker there would fight
# the existing runtime. See docker-rootless-cgroup/ for the Kasm-side config.
#
# Idempotent and safe to re-run. Uses sudo.
set -eu
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
REPO_ROOT="$(dirname -- "$SCRIPT_DIR")"
# shellcheck source=../lib/os-detect.sh
. "$REPO_ROOT/lib/os-detect.sh"
say() { printf '%s\n' "$*" >&2; }
DOCKER_PKGS="docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin"
# install_rhel — install docker-ce from Docker's EL repo.
#
# WHY NOT get.docker.com: the convenience script allowlists distros by
# /etc/os-release ID and aborts on anything it does not recognize —
# "ERROR: Unsupported distribution 'ol'" on Oracle Linux, and the same for
# other EL rebuilds it has not enumerated. On a match it does nothing more
# than what this function does: add the repo, then install the packages.
# Wiring the repo up directly drops the allowlist, so every EL rebuild
# (Oracle, Rocky, Alma, CentOS, RHEL) installs from one code path.
#
# The repo URL is keyed on $releasever/$basearch, which dnf expands per host,
# so EL9 and EL10 both resolve without a version table here.
install_rhel() {
say "docker: adding Docker CE repo (EL \$releasever/\$basearch)..."
sudo tee /etc/yum.repos.d/docker-ce.repo >/dev/null <<'REPO'
[docker-ce-stable]
name=Docker CE Stable - $basearch
baseurl=https://download.docker.com/linux/centos/$releasever/$basearch/stable
enabled=1
gpgcheck=1
gpgkey=https://download.docker.com/linux/centos/gpg
REPO
# --allowerasing: containerd.io conflicts with the distro's own runc/containerd
# on EL rebuilds that ship them (Oracle Linux does). Let dnf swap them out
# rather than dead-end on the conflict.
if command -v dnf >/dev/null 2>&1; then
# shellcheck disable=SC2086
sudo dnf install -y --allowerasing $DOCKER_PKGS
else
# shellcheck disable=SC2086
sudo yum install -y --allowerasing $DOCKER_PKGS
fi
}
# install_debian — Docker's convenience script; it supports every Debian-family
# distro this repo targets and sets up the apt repo and keyring.
install_debian() {
say "docker: installing Docker Engine via get.docker.com..."
tmp="$(mktemp)"
if command -v curl >/dev/null 2>&1; then
curl -fsSL https://get.docker.com -o "$tmp"
elif command -v wget >/dev/null 2>&1; then
wget -qO "$tmp" https://get.docker.com
else
say "docker: need curl or wget"; rm -f "$tmp"; return 1
fi
sudo sh "$tmp"
rm -f "$tmp"
}
# --- skip on rootless-Docker hosts -------------------------------------------
if command -v docker >/dev/null 2>&1 &&
docker info -f '{{println .SecurityOptions}}' 2>/dev/null | grep -q 'name=rootless'; then
say "docker: rootless Docker daemon detected; leaving it alone."
exit 0
fi
# --- 1. install engine -------------------------------------------------------
if command -v docker >/dev/null 2>&1; then
say "docker: engine already installed ($(docker --version 2>/dev/null || echo 'version unknown'))."
else
case "$(detect_pkg_family)" in
rhel) install_rhel ;;
debian) install_debian ;;
*) say "docker: unsupported/undetected OS family; install Docker manually."; exit 1 ;;
esac
fi
# --- 2. enable + start the service (systemd only) ----------------------------
if [ -d /run/systemd/system ] && command -v systemctl >/dev/null 2>&1; then
sudo systemctl enable --now docker
else
say "docker: no systemd; not managing the service (start dockerd yourself)."
fi
# --- 3. group membership for the invoking user -------------------------------
user="$(id -un)"
if id -nG "$user" | tr ' ' '\n' | grep -qx docker; then
say "docker: $user already in the docker group."
else
sudo usermod -aG docker "$user"
say "docker: added $user to the docker group."
say " Log out and back in (or run 'newgrp docker') for it to take effect."
fi
-13
View File
@@ -2,19 +2,6 @@
# overwritten on the next bootstrap run. Edit zsh/zshrc in the dotfiles repo # overwritten on the next bootstrap run. Edit zsh/zshrc in the dotfiles repo
# instead. # instead.
# If this account was added to the docker group (dotfiles/docker/install.sh)
# but this shell's session predates that, re-exec via newgrp so docker works
# without a full logout. Guarded: fires only when the group is on the account
# yet missing from the running shell's groups, so the newgrp'd shell (which
# has the group) cannot loop.
# Only for real terminals ([ -t 0 ]): newgrp replaces the shell and would
# swallow the command in scripted `zsh -i -c ...` invocations.
if [ -t 0 ] && [ -S /var/run/docker.sock ] \
&& id -nG "${USER:-$(id -un)}" 2>/dev/null | grep -qw docker \
&& ! id -Gn 2>/dev/null | grep -qw docker; then
exec newgrp docker
fi
# Userland tools installed by dotfiles/bin/install.sh live here. # Userland tools installed by dotfiles/bin/install.sh live here.
case ":$PATH:" in case ":$PATH:" in
*":$HOME/.local/bin:"*) ;; *":$HOME/.local/bin:"*) ;;