Files
computer-playbook/scripts/github/runner/relocate_docker_dataroot.sh
T
kevinveenbirkenbachandClaude Opus 4.8 51dbc46876 ci(runner): relocate Docker data-root onto /mnt when roomier
Swarm's nested DinD-node daemons plus the backup DR drill (LUKS loop image,
per-node registry pulls) fill the ~50 GB root fs and trip the <6 GB abort
guard in utils/tests/swarm/matrix.py, while /mnt is a separate ~74 GB
partition sitting idle behind only a swapfile.

Add a runner step that moves the host Docker data-root to /mnt/docker when
/mnt is a separate, roomier partition (detection mirrors enlarge_swap.sh),
before any Docker usage. Best-effort: any failure rolls Docker back onto /
and the step still exits 0, so it can never turn a green deploy red. Wired
into the compose, swarm, and host deploy workflows.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-24 20:05:59 +02:00

99 lines
3.3 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
else
sudo rm -f /etc/docker/daemon.json || true
fi
sudo systemctl start docker.service || sudo systemctl restart docker.service || true
"$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
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}"