
:latest means “whatever the maintainer pushed most recently”. Your next docker compose pull can jump several major versions without warning, and you won’t know which version you were on before.
Pin a version tag
In your Compose file, set an explicit version (services reference):
services:
vaultwarden:
image: vaultwarden/server:1.37.4
Updating becomes a one-line diff you can commit to Git. Rolling back is the same edit in reverse.
Or pin by digest
A tag can be re-pushed; a digest can’t. Find the digest you’re running:
docker image inspect --format '{{index .RepoDigests 0}}' vaultwarden/server:1.37.4
Then reference image: vaultwarden/server@sha256:<digest>. docker image pull supports pulling by digest. Digests are best for “this exact build must never change”. Version tags are easier to read.
Back up named volumes
Docker’s volumes docs show the pattern: start a throwaway container that mounts the volume and tar it to the host.
docker compose stop vaultwarden
docker run --rm -v vaultwarden_data:/data -v "$PWD":/backup alpine \
tar czf /backup/vaultwarden_data-$(date +%F).tgz -C /data .
docker compose start vaultwarden
Stopping the container first keeps the files consistent.
Databases: dump, don’t copy
For Postgres-backed apps (Immich, Paperless-ngx, authentik, Nextcloud…) also take a logical dump. See pg_dumpall:
docker compose exec -T database pg_dumpall -U postgres > db-$(date +%F).sql
(Use your stack’s real service and user names.)
Test a restore once
A backup you’ve never restored is a hope, not a backup. Restore into a scratch volume or VM once a quarter.