Skip to content

Instantly share code, notes, and snippets.

@cb1kenobi
Created June 30, 2026 15:27
Show Gist options
  • Select an option

  • Save cb1kenobi/43d6607180a1f90ca8ec36ececb3d903 to your computer and use it in GitHub Desktop.

Select an option

Save cb1kenobi/43d6607180a1f90ca8ec36ececb3d903 to your computer and use it in GitHub Desktop.
Check whether live Docker container volumes exist
#!/usr/bin/env bash
#
# check-container-volumes.sh
#
# Iterates over all running Docker containers and, for each mount/volume,
# reports whether the associated directory on the host exists.
#
# Notes:
# - Must be run ON the Docker host (paths are checked on the local
# filesystem). For named volumes the source lives under
# /var/lib/docker/volumes/<name>/_data, which usually requires root,
# so you may need to run this with sudo.
# - Exits non-zero if any expected source path is missing.
#
set -uo pipefail
# Make sure docker is available.
if ! command -v docker >/dev/null 2>&1; then
echo "Error: docker command not found." >&2
exit 1
fi
# Field separator for parsing inspect output. We use ASCII Unit Separator
# (0x1F) instead of a tab: tab is IFS-whitespace, so `read` would collapse
# the empty .Name field of bind mounts and shift every column over by one.
sep=$'\x1f'
# Collect running container IDs (container IDs contain no whitespace,
# so word-splitting the output here is safe).
containers=$(docker ps -q)
if [ -z "$containers" ]; then
echo "No running containers found."
exit 0
fi
exit_code=0
for cid in $containers; do
name=$(docker inspect --format '{{.Name}}' "$cid" | sed 's#^/##')
echo "=== Container: $name ($cid) ==="
# One line per mount, fields separated by 0x1F:
# TYPE <sep> NAME <sep> SOURCE <sep> DESTINATION
fmt="{{range .Mounts}}{{.Type}}${sep}{{.Name}}${sep}{{.Source}}${sep}{{.Destination}}{{\"\\n\"}}{{end}}"
mounts=$(docker inspect --format "$fmt" "$cid")
if [ -z "$mounts" ]; then
echo " (no volumes or bind mounts)"
echo
continue
fi
while IFS="$sep" read -r type vol_name source destination; do
[ -z "$type" ] && continue
# Build a readable label, e.g. "volume:mydata" or "bind".
label="$type"
[ -n "$vol_name" ] && label="$type:$vol_name"
if [ -z "$source" ]; then
# tmpfs and similar have no host source path.
echo " [$label] -> $destination : no host source path"
elif [ -d "$source" ]; then
echo " [$label] DIR EXISTS $source -> $destination"
elif [ -e "$source" ]; then
# Bind mount of a single file rather than a directory.
echo " [$label] EXISTS (not a dir) $source -> $destination"
else
echo " [$label] MISSING $source -> $destination"
exit_code=1
fi
done <<< "$mounts"
echo
done
exit "$exit_code"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment