Add a script to update docker images with docker compose

This commit is contained in:
tim committed 2026-10-22 21:32:26 +02:00
1 parent fb747989d0
commit 1f6a602555
1 file changed
+108
+108
View File
@@ -0,0 +1,108 @@
#!/usr/bin/env bash
# Usage: ./update_docker_images.sh [--prune] [--build] [compose-directory]
# By default, pull images and update services without pruning or building.
# WARNING: Pruning removes stopped containers, unused images, build cache,
# and unused anonymous volumes.
set -euo pipefail
usage() {
printf 'Usage: %s [--prune] [--build] [compose-directory]\n' "$0"
printf '%s\n' \
' --prune Remove unused Docker resources before updating (including volumes).' \
' --build Build images with --pull before updating services.' \
' -h, --help Show this help.' \
'Default: pull images and update services; do not prune or build.'
}
prune=false
build=false
positional=()
while (( $# )); do
case "$1" in
--prune) prune=true ;;
--build) build=true ;;
-h|--help) usage; exit 0 ;;
--) shift; positional+=("$@"); break ;;
-*) printf 'Unknown option: %s\n' "$1" >&2; usage >&2; exit 2 ;;
*) positional+=("$1") ;;
esac
shift
done
if (( ${#positional[@]} > 1 )); then
usage >&2
exit 2
fi
compose_root=${positional[0]:-/etc/docker/compose}
if [[ ! -d "$compose_root" ]]; then
printf 'Compose directory not found: %s\n' "$compose_root" >&2
exit 1
fi
created_builder=
cleanup() {
local status=$?
trap - EXIT
if [[ -n "$created_builder" ]]; then
if ! docker buildx rm "$created_builder"; then
printf 'Could not remove builder: %s\n' "$created_builder" >&2
if (( status == 0 )); then
status=1
fi
fi
fi
exit "$status"
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
if "$prune"; then
docker system df
docker system prune -a --volumes -f
docker system df
fi
if "$build"; then
# Select an existing container builder, not merely check whether one exists.
# Capture the list separately so a failed Docker command stops the script.
builders=$(docker buildx ls --format '{{.Name}} {{.Driver}}')
builder=
while read -r name driver; do
if [[ "$driver" == docker-container ]]; then
builder=$name
break
fi
done <<< "$builders"
if [[ -z "$builder" ]]; then
# Bootstrap separately so cleanup can run if startup fails.
created_builder=$(docker buildx create \
--buildkitd-config /etc/docker/buildx/buildkit.toml \
--driver docker-container \
--driver-opt 'network=treehouse')
builder=$created_builder
fi
# Select the builder for this script without changing the user's default.
export BUILDX_BUILDER="$builder"
docker buildx inspect "$builder" --bootstrap
fi
for directory in "$compose_root"/*; do
[[ -d "$directory" ]] || continue
[[ -f "$directory/docker-compose.yml" ]] || continue
# Manually update Minecraft, so we're not always on the cutting edge
[[ "$directory" == *minecraft* ]] && continue
printf '\nUpdating %s\n' "$directory"
# A subshell restores the working directory even when a command fails.
(
cd -- "$directory"
docker compose pull
if "$build"; then
docker compose build --pull
fi
# Do not let Compose implicitly build images when starting services.
docker compose up -d --no-build
)
done