Back up and restore a self-hosted build cache
A build cache can always be rebuilt, so you do not have to back it up. But a big cache takes days of builds to fill again, and you may want to move it to a new host. This page shows a backup and restore of the Docker volume, run for real on the 0.2.1 image.
Do you need a backup?
Usually not. If the cache is lost, builds are slower until it refills, and nothing breaks. A backup is worth it only if refilling is expensive for you, or if you are moving the cache to a new server. To simply empty a cache, see how to clear or reset a build cache.
Where the data lives
The Docker command in our guides mounts a volume at /home/nonroot. The server keeps its blobs and index in a data folder inside it, and it runs as user 65532. Backing up the volume backs up the cache.
1. Stop the server, then back up the volume
I stopped the container first. I did not test copying the files while the server is running, so I cannot say that is safe. The container image has no shell, so a second small container does the copying:
docker stop fscache
docker run --rm -v fscache-data:/data:ro -v "$PWD":/backup ubuntu:24.04 \
tar czf /backup/fscache-data.tgz -C /data .
In my test, with three small entries, the archive held a data/blobs/ folder with one folder per entry prefix, and was 578 bytes.
2. Restore it into a new volume
To check it, I deleted the container and the volume, then restored into a new, empty one:
docker volume create fscache-data-restored
docker run --rm -v fscache-data-restored:/data -v "$PWD":/backup:ro ubuntu:24.04 \
sh -c 'tar xzf /backup/fscache-data.tgz -C /data'
ls -ln /data # inside the helper: the files are owned by 65532
Listing the restored volume showed the data folder still owned by user and group 65532, which is what the server runs as. If you restore as a different user, the server will not be able to write.
3. Start the server on the restored volume
docker run -d --name fscache -p 127.0.0.1:8080:8080 \
-v fscache-data-restored:/home/nonroot ghcr.io/fosterstack/cache:0.2.1
The status page and the entries were all back:
$ curl -s localhost:8080/statusz | grep -E '"store_entries"|"store_bytes"'
"store_bytes": 32,
"store_entries": 3,
$ curl -s localhost:8080/alpha
value-alpha
$ curl -s -o /dev/null -w '%{http_code}\n' localhost:8080/nothere
404
What I did not test
- Backing up while the server is running.
- Restoring into a different version of the server than the one that wrote the data.
- Kubernetes or Compose. The same idea applies to the volume behind the claim, but I only ran plain Docker.
Related: server sizing and Gradle build cache with Docker Compose.