docker/: install rootful Docker; gate kind on it
kind never worked reliably against rootless Docker on Kasm, even with the cgroup delegation from docker-rootless-cgroup/. So install full Docker where we can, and flip bin/'s kind gate from "rootless is available" to "a rootful daemon answers" — kind is simply skipped on Kasm now. docker/install.sh no-ops when a rootless daemon is already running so it never fights Kasm's setup. It runs before bin/ in bootstrap so the kind gate can see the daemon it just started. zsh/zshrc re-execs via newgrp when the account gained the docker group but the live shell predates it. docker-rootless-cgroup/ keeps its delegation (still useful for per-container resource limits); only its kind-centric comments change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+12
-11
@@ -20,13 +20,15 @@ REPO_ROOT="$(dirname -- "$SCRIPT_DIR")"
|
|||||||
ARCH="$(fetch_arch)" # x86_64 / aarch64
|
ARCH="$(fetch_arch)" # x86_64 / aarch64
|
||||||
DEB="$(fetch_arch_deb)" # amd64 / arm64
|
DEB="$(fetch_arch_deb)" # amd64 / arm64
|
||||||
|
|
||||||
# docker_rootless_available — true only if a rootless Docker daemon is up and
|
# docker_full_available — true only if a non-rootless (full) Docker daemon is
|
||||||
# reachable. kind needs a container runtime to create clusters; on Kasm we run
|
# up and reachable. kind needs full Docker: we could not get it working against
|
||||||
# Docker rootless (never system Docker), so kind is worth installing only when
|
# rootless Docker on Kasm, so it is only worth installing where a rootful
|
||||||
# that daemon answers. SecurityOptions lists name=rootless under rootless mode.
|
# daemon answers. SecurityOptions lists name=rootless under rootless mode.
|
||||||
docker_rootless_available() {
|
docker_full_available() {
|
||||||
command -v docker >/dev/null 2>&1 || return 1
|
command -v docker >/dev/null 2>&1 || return 1
|
||||||
docker info -f '{{println .SecurityOptions}}' 2>/dev/null | grep -q 'name=rootless'
|
_secopts="$(docker info -f '{{println .SecurityOptions}}' 2>/dev/null)" || return 1
|
||||||
|
[ -n "$_secopts" ] || return 1
|
||||||
|
! printf '%s' "$_secopts" | grep -q 'name=rootless'
|
||||||
}
|
}
|
||||||
|
|
||||||
# jq — command-line JSON processor (single static binary).
|
# jq — command-line JSON processor (single static binary).
|
||||||
@@ -68,9 +70,8 @@ install_k9s() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# kind — run local Kubernetes clusters in Docker (single static binary). Gated
|
# kind — run local Kubernetes clusters in Docker (single static binary). Gated
|
||||||
# on rootless Docker at the call site since it is useless without a runtime.
|
# on full (non-rootless) Docker at the call site: kind could not be made to
|
||||||
# On systemd-less hosts the rootless daemon also needs cgroup delegation before
|
# work against rootless Docker on Kasm, so it is skipped there.
|
||||||
# kind can create clusters; see the docker-rootless-cgroup/ module.
|
|
||||||
install_kind() {
|
install_kind() {
|
||||||
ver=v0.32.0
|
ver=v0.32.0
|
||||||
have_version kind "$ver" && { fsay "kind $ver already installed."; return 0; }
|
have_version kind "$ver" && { fsay "kind $ver already installed."; return 0; }
|
||||||
@@ -150,10 +151,10 @@ install_jq
|
|||||||
install_kubectl
|
install_kubectl
|
||||||
install_helm
|
install_helm
|
||||||
install_k9s
|
install_k9s
|
||||||
if docker_rootless_available; then
|
if docker_full_available; then
|
||||||
install_kind
|
install_kind
|
||||||
else
|
else
|
||||||
fsay "Skipping kind: rootless Docker not available."
|
fsay "Skipping kind: full (non-rootless) Docker not available."
|
||||||
fi
|
fi
|
||||||
install_kubectx
|
install_kubectx
|
||||||
install_kubens
|
install_kubens
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ fi
|
|||||||
|
|
||||||
"$SCRIPT_DIR/zsh/install.sh"
|
"$SCRIPT_DIR/zsh/install.sh"
|
||||||
"$SCRIPT_DIR/git/install.sh"
|
"$SCRIPT_DIR/git/install.sh"
|
||||||
|
# Runs before bin/ so the kind install gate can see the rootful daemon.
|
||||||
|
"$SCRIPT_DIR/docker/install.sh"
|
||||||
"$SCRIPT_DIR/bin/install.sh"
|
"$SCRIPT_DIR/bin/install.sh"
|
||||||
"$SCRIPT_DIR/ansible/install.sh"
|
"$SCRIPT_DIR/ansible/install.sh"
|
||||||
# Runs last: needs rootless Docker already up (started at boot) so it can
|
# Runs last: needs rootless Docker already up (started at boot) so it can
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
# docker-rootless-cgroup/install.sh — give rootless Docker cgroup v2 controller
|
# docker-rootless-cgroup/install.sh — give rootless Docker cgroup v2 controller
|
||||||
# delegation on a systemd-less host (e.g. Kasm), so per-container cgroups work
|
# delegation on a systemd-less host (e.g. Kasm), so per-container cgroups work.
|
||||||
# and `kind` can create clusters.
|
# (This was originally done to support `kind`, but kind never worked reliably
|
||||||
|
# against rootless Docker even with delegation — bin/ now only installs kind
|
||||||
|
# where full Docker is available. The delegation itself is still useful for
|
||||||
|
# per-container resource limits.)
|
||||||
#
|
#
|
||||||
# Why: rootless Docker only receives delegated cgroup v2 controllers when
|
# Why: rootless Docker only receives delegated cgroup v2 controllers when
|
||||||
# systemd sets `Delegate=yes` on the user session. Kasm images run no systemd
|
# systemd sets `Delegate=yes` on the user session. Kasm images run no systemd
|
||||||
@@ -117,7 +120,7 @@ cat > "$tmp" <<'SH'
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Managed by dotfiles (docker-rootless-cgroup). Shadows /usr/bin/dockerd-rootless.sh
|
# Managed by dotfiles (docker-rootless-cgroup). Shadows /usr/bin/dockerd-rootless.sh
|
||||||
# on PATH. Places the rootless Docker daemon in a private, delegated cgroup v2
|
# on PATH. Places the rootless Docker daemon in a private, delegated cgroup v2
|
||||||
# leaf so it can enable controllers (needed by `kind`), then execs the real
|
# leaf so it can enable controllers (per-container cgroups), then execs the real
|
||||||
# launcher. No-op if the delegated slice is absent, so it is safe anywhere.
|
# launcher. No-op if the delegated slice is absent, so it is safe anywhere.
|
||||||
_cg=/sys/fs/cgroup/rootless/daemon
|
_cg=/sys/fs/cgroup/rootless/daemon
|
||||||
if [ -w /sys/fs/cgroup/rootless ] && [ -d "$_cg" ]; then
|
if [ -w /sys/fs/cgroup/rootless ] && [ -d "$_cg" ]; then
|
||||||
@@ -156,9 +159,9 @@ done
|
|||||||
driver="$(docker info -f '{{.CgroupDriver}}' 2>/dev/null || true)"
|
driver="$(docker info -f '{{.CgroupDriver}}' 2>/dev/null || true)"
|
||||||
if [ "$driver" = "none" ] || [ -z "$driver" ]; then
|
if [ "$driver" = "none" ] || [ -z "$driver" ]; then
|
||||||
say "docker-rootless-cgroup: WARNING — CgroupDriver is still '${driver:-unreachable}'."
|
say "docker-rootless-cgroup: WARNING — CgroupDriver is still '${driver:-unreachable}'."
|
||||||
say " kind will not work yet. Inspect the new dockerd's cgroup:"
|
say " Per-container cgroups will not work yet. Inspect the new dockerd's cgroup:"
|
||||||
say " cat /proc/\$(pgrep -x dockerd | head -1)/cgroup # expect .../rootless/daemon"
|
say " cat /proc/\$(pgrep -x dockerd | head -1)/cgroup # expect .../rootless/daemon"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
say "docker-rootless-cgroup: done. CgroupDriver=$driver — rootless Docker now has"
|
say "docker-rootless-cgroup: done. CgroupDriver=$driver — rootless Docker now has"
|
||||||
say " delegated cgroups; \`kind create cluster\` can run."
|
say " delegated cgroups; per-container resource limits work."
|
||||||
|
|||||||
Executable
+62
@@ -0,0 +1,62 @@
|
|||||||
|
#!/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 via Docker's official convenience script
|
||||||
|
# (get.docker.com — supports both RHEL- and Debian-family distros and
|
||||||
|
# sets up the upstream package repo). Skipped when `docker` is already
|
||||||
|
# installed.
|
||||||
|
# 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
|
||||||
|
|
||||||
|
say() { printf '%s\n' "$*" >&2; }
|
||||||
|
|
||||||
|
# --- 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
|
||||||
|
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"; exit 1
|
||||||
|
fi
|
||||||
|
sudo sh "$tmp"
|
||||||
|
rm -f "$tmp"
|
||||||
|
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
|
||||||
@@ -2,6 +2,19 @@
|
|||||||
# 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:"*) ;;
|
||||||
|
|||||||
Reference in New Issue
Block a user