You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3.4 KiB

draft title date series author cover tags summary showFullContent
false How to find that one volume you're pretty sure you didn't lose 2024-06-25
Nick Dumas
bash
docker
Docker volumes can be opaque, so I wrote a small bash script to help you troubleshoot. false

What I expect you to know

This article is only relevant if you know about and use Docker volumes and have some fluency in bash. I'll explain the code as I go, if it helps.

The Problem

Over the lifetime of a Docker host machine, it's likely that orphaned volumes and other detritus will accumulate over time. You might find yourself fumbling a configuration and orphaning a volume yourself. However we got here, we have a bunch of volumes and we need to know if any of them are important. In a perfect world, they'll have decent names.

We don't live in a perfect world.

Make a list

Luckily, we have tools at our disposal to handle this. My thought process almost always starts with "Can I make a newline separated list of the things I care about?" If I can do that, I can start automating my troubleshooting.

Let's start with docker volume ls. This is how we list volumes, but the default output isn't quite what I'm looking for:

docker volume ls
DRIVER    VOLUME NAME
local     d35fce052fbce42b94b2f9b2957be0f77090fa006b1a192030eff07db3675af2
local     grafana-storage
local     plausible_db-data
local     plausible_event-data

This is human readable, and we could even do some slicing with cut or awk, but Docker gives us a flag that will take us exactly where we need to go: --format. Docker uses Go's text/template library to power this feature and individual flags (usually) document the template verbs available. Here, we want Name.

docker volume ls --format "{{.Name}}"
d35fce052fbce42b94b2f9b2957be0f77090fa006b1a192030eff07db3675af2
grafana-storage
plausible_db-data
plausible_event-data

We now have a newline separated list of volume names.

Process of elimination

The next part is fairly straightforward. We loop over this list and ask Docker to create a temporary container based on alpine, with a single volume mounted at /test/.

#! /bin/bash

# Newline separated list of volume names
volumes=$(docker volume ls --format="{{.Name}}")
for volume in $volumes; do
	# Help the user keep track of which volume they're exploring
	echo "Mounting $volume in a temporary image."
    docker run --rm -v $volume:/test/ -it alpine /bin/sh
done

Running this script should do something like this:

./cycle-volumes.sh
Mounting d35fce052fbce42b94b2f9b2957be0f77090fa006b1a192030eff07db3675af2 in a temporary image.
/ # ls /test/
clickhouse-server.err.log   clickhouse-server.log.1.gz  clickhouse-server.log.4.gz  clickhouse-server.log.7.gz
clickhouse-server.log       clickhouse-server.log.2.gz  clickhouse-server.log.5.gz  clickhouse-server.log.8.gz
clickhouse-server.log.0.gz  clickhouse-server.log.3.gz  clickhouse-server.log.6.gz
/ #
Mounting grafana-storage in a temporary image.
/ # ls /test
alerting          csv               file-collections  grafana.db        plugins           png
/ # exit
Mounting plausible_db-data in a temporary image.
/ # exit
Mounting plausible_event-data in a temporary image.
/ # exit

You can use bash to explore the volume and identify its contents, make note of which ones are which, and proceed accordingly.