Skip to content

How to Back Up Docker Volumes

Back up Docker named volumes the reliable way: tar a volume via a temp container, restore it, dump databases properly, schedule it, and move data between hosts.

SDSysadmin Desk July 19, 2026 8 min read
Diagram-style cover showing a temporary container archiving a Docker named volume to a tar file on the host

Named volumes are where your container data actually lives — the database, the uploads, anything that has to survive a container being recreated. They’re managed by Docker and don’t map to a folder you can just copy in Explorer, so backing them up needs a small trick: mount the volume into a throwaway container and archive its contents from there.

This guide covers the whole loop. You’ll back a volume up to a tarball, restore it, and — importantly — learn when a tar copy is the wrong tool and a proper database dump is what you want. Then scheduling backups so they happen on their own, and moving a volume to another host.

Everything uses the standard docker run with a temporary alpine container, so there’s nothing extra to install. The commands are written for a Linux/bash host; on Windows use the equivalent path syntax for the host side.

Why you can’t just copy the folder

On Linux, named volumes do sit on disk, under Docker’s data directory:

/var/lib/docker/volumes/<volume-name>/_data

You can see the exact path for any volume:

docker volume inspect db-data

So why not just cp that folder? Two reasons. First, on Docker Desktop (Windows and Mac) there is no such folder on your machine — the volume lives inside Docker’s Linux VM, out of reach of Explorer or Finder. Second, even on Linux, copying a live volume’s files as root can trip over permissions and catch a database mid-write. Going through a container sidesteps both problems and works identically everywhere. If you want the deeper background on how volumes are stored, the bind mount vs named volume guide covers it.

Back up a volume to a tarball

The core pattern: run a tiny alpine container, mount the volume you want to back up at /data, mount your current host folder at /backup, and tar the contents across.

docker run --rm \
  -v db-data:/data \
  -v "$PWD":/backup \
  alpine tar czf /backup/db-data.tar.gz -C /data .

Reading it left to right: --rm removes the container as soon as it finishes, -v db-data:/data mounts the named volume read side, -v "$PWD":/backup mounts your current directory so the archive lands on the host, and tar czf ... -C /data . archives everything inside the volume. When it’s done you have db-data.tar.gz in your current folder.

That file is portable. Copy it to backup storage, another server, or wherever your retention lives.

Restore a volume from a tarball

Restoring reverses the process: mount the target volume and the backup folder, then extract the archive into the volume.

# Create the target volume first if it doesn't exist
docker volume create db-data

# Extract the backup into it
docker run --rm \
  -v db-data:/data \
  -v "$PWD":/backup \
  alpine sh -c "tar xzf /backup/db-data.tar.gz -C /data"

Restore into a fresh volume when you can. Extracting over a volume that already has data mixes old and new files, which for a database is a recipe for corruption. If you’re restoring to recover, remove or recreate the volume first so you start clean — and make sure no container is using it while you extract.

Databases: dump, don’t just tar

This is the distinction that saves you from a backup that looks fine and fails when you need it. A running database writes to its files constantly. A raw tar of those files can capture them mid-transaction, producing an archive that won’t restore into a working database.

For databases, use the engine’s own dump tool against the running container. That produces a consistent logical backup the engine knows how to read back.

For MySQL or MariaDB:

# Dump all databases to a .sql file on the host
docker exec mysql-container \
  sh -c 'exec mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" --all-databases' \
  > backup-$(date +%F).sql

For PostgreSQL:

# Dump every database with pg_dumpall
docker exec -t postgres-container \
  pg_dumpall -U postgres > backup-$(date +%F).sql

Restoring a dump feeds the .sql file back into the running database:

# MySQL / MariaDB
docker exec -i mysql-container \
  sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD"' < backup-2026-07-19.sql

# PostgreSQL
docker exec -i postgres-container \
  psql -U postgres < backup-2026-07-19.sql

File copy (tar) vs database dump — which to use

Static files, uploads, config tar method — fast and exact for data that isn't being written.
Running database (MySQL/Postgres) Dump tool (mysqldump / pg_dump) — consistent, restorable.
Stopped database Either works; tar is fine once nothing is writing.
Whole-volume migration to a new host tar method — moves the raw data as-is.
Point-in-time DB recovery Dump — restores into a clean running engine.

Schedule backups with cron

A backup you have to remember to run isn’t a backup. On a Linux host, put the command in a small script and let cron run it.

#!/usr/bin/env bash
set -euo pipefail

BACKUP_DIR=/srv/backups
DATE=$(date +%F)

# Tar a static-data volume
docker run --rm \
  -v wp-content:/data \
  -v "$BACKUP_DIR":/backup \
  alpine tar czf "/backup/wp-content-$DATE.tar.gz" -C /data .

# Dump the database properly
docker exec mysql-container \
  sh -c 'exec mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" --all-databases' \
  > "$BACKUP_DIR/db-$DATE.sql"

# Delete backups older than 14 days
find "$BACKUP_DIR" -type f -mtime +14 -delete

Make it executable and add a cron entry to run it nightly:

chmod +x backup-volumes.sh

# Edit your crontab
crontab -e
# Run the backup every night at 02:30
30 2 * * * /path/to/backup-volumes.sh >> /var/log/docker-backup.log 2>&1

The find ... -mtime +14 -delete line matters as much as the backup itself — without retention cleanup, the backup folder grows until the disk fills, which can take the whole host down. Keep enough history to be useful and prune the rest.

Move a volume to another host

Because named volumes carry no host path, moving one to a different machine is just back-up, copy, restore. On the source host:

docker run --rm \
  -v db-data:/data \
  -v "$PWD":/backup \
  alpine tar czf /backup/db-data.tar.gz -C /data .

Copy the tarball to the new host:

scp db-data.tar.gz user@newhost:/tmp/

Then on the destination host, create the volume and extract into it:

docker volume create db-data

docker run --rm \
  -v db-data:/data \
  -v /tmp:/backup \
  alpine sh -c "tar xzf /backup/db-data.tar.gz -C /data"

Start your container or stack on the new host and it picks up the restored volume. For a database, prefer moving a dump instead of a raw tar, for the same consistency reason as before.

Volume backup checklist

  • Identify which volumes hold data you can't regenerate (databases, uploads)
  • Use the tar method for static files; use mysqldump/pg_dump for live databases
  • Add a date to backup filenames so you keep a history, not one snapshot
  • Schedule it with cron and include retention (delete old backups)
  • Copy backups off the host so they survive a disk failure
  • Test a restore at least once — an untested backup isn't a backup

The down -v reminder

Worth repeating because it’s how most people lose a volume in the first place. docker compose down keeps your named volumes; docker compose down -v deletes them. There’s no recycle bin. If you run down -v on a stack with a database and don’t have a backup, that data is gone. Having the backups above in place is exactly what makes that mistake recoverable instead of fatal — and the Compose beginner guide explains the down vs down -v difference in full.

Wrapping up

Backing up Docker volumes comes down to two patterns and knowing which to use. For static data — uploads, config, generated files — mount the volume into a throwaway alpine container and tar it to the host. For live databases, skip the raw copy and use mysqldump or pg_dump so the backup is consistent and actually restores. Wrap whichever you need in a script, schedule it with cron, add retention, and copy the results off the host.

The one habit that separates a real backup strategy from a false sense of security: test a restore. For more on how volumes work and the storage decisions behind them, see bind mount vs named volume and the rest of the Docker & Containers guides.

Frequently asked questions

How do I back up a Docker named volume?

Run a temporary container that mounts the volume and a host folder, then tar the volume's contents to the host. For example: docker run --rm -v myvol:/data -v $(pwd):/backup alpine tar czf /backup/myvol.tar.gz -C /data . The container exits and removes itself, leaving a tarball you can copy anywhere.

Should I tar a database volume or use a dump?

For a running database, use the engine's dump tool — mysqldump for MySQL/MariaDB, pg_dump for Postgres — not a raw tar. A live database writes constantly, so a file copy can catch it mid-write and produce a backup that won't restore cleanly. Use tar for static files, uploads, or a database you've stopped first.

Can I back up a volume while the container is running?

For static file data, usually yes — the tar method works on a running container's volume. For databases and anything that writes constantly, stop the container first or use a proper dump, otherwise you risk an inconsistent backup. When in doubt, stop the service for the few seconds the backup takes.

How do I restore a Docker volume from a backup?

Create or reuse the target volume, then run a temporary container that mounts it and extracts the tarball into it: docker run --rm -v myvol:/data -v $(pwd):/backup alpine sh -c 'tar xzf /backup/myvol.tar.gz -C /data'. Restore into a fresh volume to avoid mixing old and new files.

How do I move a Docker volume to another host?

Back the volume up to a tarball with the tar method, copy the file to the new host with scp or rsync, create the volume there, and restore the tarball into it. Because named volumes have no host path baked in, they move cleanly between machines this way.

Where do Docker named volumes live so I can back them up directly?

On Linux they're under /var/lib/docker/volumes//_data, and docker volume inspect shows the exact path. You can back them up directly from there, but it's safer to go through a container with the tar method — it avoids permission and consistency problems, and works the same on Docker Desktop where the files sit inside a VM.

Sources & further reading

Official vendor documentation referenced while writing this guide.

SD

Sysadmin Desk

Infrastructure & Cloud

Hands-on guidance for infrastructure, virtualization, and containers — Hyper-V, VMware, Docker, and the day-to-day operations work that keeps environments running.

MCSA Guru provides independent, educational IT guidance. Microsoft, Windows, Windows Server, Microsoft 365, Exchange, and Microsoft Teams are trademarks of Microsoft Corporation; Docker is a trademark of Docker, Inc. MCSA Guru is not affiliated with or endorsed by Microsoft or Docker. Always test changes in a safe environment before applying them in production.

Related guides

Fixing something right now?

Jump straight into the guide library or search for the exact error or task you are dealing with.