mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 19:01:54 +00:00
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
99 lines
3.7 KiB
Bash
Executable File
99 lines
3.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Move the host Docker data-root onto /mnt when it is a separate, roomier
|
|
# partition. Image/volume storage (swarm's nested DinD-node daemons, the
|
|
# DR-drill LUKS loop image, per-node registry pulls) otherwise piles onto
|
|
# the ~50 GB root fs and trips the <6 GB abort guard in
|
|
# utils/tests/swarm/matrix.py. On public runners without a separate /mnt
|
|
# this is a no-op and Docker stays on /.
|
|
#
|
|
# Best-effort: relocation is an optimization, never a requirement. Any
|
|
# failure rolls Docker back onto / and the step still exits 0, so a hiccup
|
|
# here can never turn an otherwise-green deploy red. Runs BEFORE any Docker
|
|
# usage; the free-disk-space step already pruned the preinstalled images, so
|
|
# /var/lib/docker is ~empty and nothing is copied.
|
|
#
|
|
# Usage: relocate_docker_dataroot.sh [min-free-gb]
|
|
# Default floor: 40 GB (swarm peak footprint; below it /mnt buys nothing).
|
|
#
|
|
# Debug toggle: SKIP_DOCKER_RELOCATE=1 leaves the data-root on /.
|
|
set -euo pipefail
|
|
|
|
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
DUMP="${HERE}/dump_state.sh"
|
|
|
|
if [ "${SKIP_DOCKER_RELOCATE:-0}" = "1" ]; then
|
|
echo "SKIP_DOCKER_RELOCATE=1 — leaving Docker data-root on /."
|
|
"$DUMP" "docker-relocate skipped (SKIP_DOCKER_RELOCATE=1)"
|
|
exit 0
|
|
fi
|
|
|
|
TARGET_DIR=/mnt/docker
|
|
MIN_FREE_GB="${1:-40}"
|
|
|
|
if ! mountpoint -q /mnt 2>/dev/null; then
|
|
echo "/mnt is not a separate mount — leaving Docker data-root on /."
|
|
"$DUMP" "docker-relocate skipped (no separate /mnt)"
|
|
exit 0
|
|
fi
|
|
|
|
mnt_free=$(df --output=avail -B1G /mnt | tail -n1 | tr -d ' ')
|
|
root_free=$(df --output=avail -B1G / | tail -n1 | tr -d ' ')
|
|
echo "Free: / ${root_free}G, /mnt ${mnt_free}G; need >= ${MIN_FREE_GB}G on /mnt and roomier than /"
|
|
|
|
if [ "$mnt_free" -lt "$MIN_FREE_GB" ] || [ "$mnt_free" -le "$root_free" ]; then
|
|
echo "/mnt below floor or not roomier than / — leaving Docker data-root on /."
|
|
"$DUMP" "docker-relocate skipped (/mnt not roomier)"
|
|
exit 0
|
|
fi
|
|
|
|
backup=""
|
|
if [ -s /etc/docker/daemon.json ]; then
|
|
backup="$(mktemp)"
|
|
cp /etc/docker/daemon.json "$backup"
|
|
fi
|
|
|
|
restore_and_continue() {
|
|
echo "WARN: Docker data-root relocation failed — keeping Docker on /." >&2
|
|
if [ -n "$backup" ]; then
|
|
sudo install -m 0644 "$backup" /etc/docker/daemon.json || true # nocheck: shell-or-true -- rollback must reach the docker restart even if the restore fails
|
|
else
|
|
sudo rm -f /etc/docker/daemon.json || true # nocheck: shell-or-true -- rollback must reach the docker restart even if the cleanup fails
|
|
fi
|
|
sudo systemctl start docker.service || sudo systemctl restart docker.service || true # nocheck: shell-or-true -- last-ditch daemon start; rollback still exits 0 by design
|
|
"$DUMP" "docker-relocate rolled back (kept on /)"
|
|
exit 0
|
|
}
|
|
|
|
echo "Relocating Docker data-root to ${TARGET_DIR}"
|
|
sudo systemctl stop docker.service docker.socket || true # nocheck: shell-or-true -- inactive/missing units may exit non-zero; a wedged daemon is caught by the post-start root-dir check
|
|
sudo mkdir -p "$TARGET_DIR" /etc/docker || restore_and_continue
|
|
|
|
tmp="$(mktemp)"
|
|
if [ -n "$backup" ]; then
|
|
jq --arg dr "$TARGET_DIR" '. + {"data-root": $dr}' "$backup" >"$tmp" || restore_and_continue
|
|
else
|
|
printf '{"data-root": "%s"}\n' "$TARGET_DIR" >"$tmp"
|
|
fi
|
|
sudo install -m 0644 "$tmp" /etc/docker/daemon.json || restore_and_continue
|
|
rm -f "$tmp"
|
|
|
|
sudo systemctl start docker.service || restore_and_continue
|
|
|
|
root_dir=""
|
|
attempt=0
|
|
while [ "$attempt" -lt 30 ]; do
|
|
root_dir="$(docker info --format '{{.DockerRootDir}}' 2>/dev/null || true)"
|
|
[ -n "$root_dir" ] && break
|
|
attempt=$((attempt + 1))
|
|
sleep 1
|
|
done
|
|
|
|
if [ "$root_dir" != "$TARGET_DIR" ]; then
|
|
echo "Docker came up with root '${root_dir}', expected '${TARGET_DIR}'." >&2
|
|
restore_and_continue
|
|
fi
|
|
|
|
echo "Docker Root Dir: ${root_dir}"
|
|
[ -n "$backup" ] && rm -f "$backup"
|
|
"$DUMP" "after docker-relocate -> ${TARGET_DIR}"
|