Ravindra BagaleCourses & study guides मराठी

Chapter 50: Docker Volumes and Storage: Named Volumes, Bind Mounts, tmpfs, Backup and Every Volume Command

50.5 Backup and restore a volume

Friends, a volume saves data from the container. But what if the server itself breaks? That is why we back up. Today we take a volume backup, restore it on another server and test it, all by hand. Three examples each.

1. Start from a story

At a Bengaluru startup that builds on AWS, the orders database runs in Docker with a named volume. One night an engineer runs docker volume prune -a on the wrong server. The volume is gone, and so are three days of orders.

They had a backup script, but nobody had ever tried to restore from it. The backup file was empty. That night the team learned two rules: take backups every day, and test the restore every week.

Think of a photocopy of your passport. Keeping a copy is good. But if the copy is blank, it does not help at the airport. A backup you have never restored is like an unchecked photocopy.

In this lesson we use two methods. The first copies the raw files of a volume into a tar file using a helper container. The second uses the database's own dump tool while it runs. Then we restore both and prove the data is back.

volume: ordersthe live datahelper containertar the volume into a fileorders.tar.gzcopy to S3 or another servernew volumeuntar, start the app, check rows
Picture 1: backup and restore flow

2. Get ready

Step 1: Make data to protect

Why: We need real data so the test means something.

What: Start Postgres with a named volume and add a few rows.

Example 1: Start the database

Type this:

docker run -d --name odb -e POSTGRES_PASSWORD=example -v orders:/var/lib/postgresql/data postgres:16

You will see:

2b7f...

What it means: Practice password only.

Example 2: Add rows

Type this:

sleep 5; docker exec odb psql -U postgres -c "CREATE TABLE o(id int, item text); INSERT INTO o VALUES (1,'Biryani'),(2,'Dosa'),(3,'Thali');"

You will see:

CREATE TABLE
INSERT 0 3

What it means: Three orders.

Example 3: Count them

Type this:

docker exec odb psql -U postgres -tAc 'SELECT count(*) FROM o'

You will see:

3

What it means: Remember this number. After restore it must be 3 again.

Step 2: Make a backup folder

Why: Backups need a safe place on the host first.

What: Create a folder with tight permissions so only you can read the backups.

Example 4: Create it

Type this:

mkdir -p ~/backups && chmod 0700 ~/backups

You will see:

(no output)

What it means: Only your user can enter.

Example 5: Check

Type this:

stat -c '%a %U' ~/backups

You will see:

700 ravi

What it means: Correct.

Example 6: Date in names

Type this:

date +%F

You will see:

2026-10-25

What it means: We will put the date in every file name.

3. Method 1: tar the volume

Step 3: Stop the app first

Why: Copying files while a database writes can give a broken copy.

What: For a raw file copy, stop the container so the files are quiet. The volume stays.

Example 7: Stop

Type this:

docker stop odb

You will see:

odb

What it means: Writes have stopped.

Example 8: Check it is stopped

Type this:

docker ps -a --filter name=odb --format '{{.Status}}'

You will see:

Exited (0) 2 seconds ago

What it means: Clean stop, exit 0.

Example 9: Volume still exists

Type this:

docker volume ls -q | grep orders

You will see:

orders

What it means: Stopping never touches the volume.

Step 4: tar with a helper container

Why: The volume folder is owned by root inside Docker's area; a helper container reaches it easily.

What: Run a small container that mounts the volume read-only and a host folder, then tar one into the other.

Example 10: Back up

Type this:

docker run --rm -v orders:/from:ro -v ~/backups:/to alpine:3.20 tar czf /to/orders-$(date +%F).tar.gz -C /from .

You will see:

(no output)

What it means: The volume is packed into one file.

Example 11: Check size

Type this:

ls -lh ~/backups

You will see:

-rw-r--r-- 1 root root 6.1M Oct 25 06:10 orders-2026-10-25.tar.gz

What it means: Not empty. That was the startup's mistake.

Example 12: Peek inside

Type this:

tar tzf ~/backups/orders-2026-10-25.tar.gz | head -3

You will see:

./
./PG_VERSION
./base/

What it means: Real Postgres files.

Step 5: Start the app again

Why: Downtime should be short.

What: Start the same container after the backup finishes.

Example 13: Start

Type this:

docker start odb

You will see:

odb

What it means: Back online.

Example 14: Measure downtime

Type this:

docker inspect odb --format '{{.State.StartedAt}}'

You will see:

2026-10-25T00:40:31Z

What it means: Compare with the stop time; here about 10 seconds.

Example 15: Data is fine

Type this:

docker exec odb psql -U postgres -tAc 'SELECT count(*) FROM o'

You will see:

3

What it means: Nothing changed.

Step 6: Restore into a new volume

Why: The real test: can we rebuild from the file alone?

What: Create an empty volume, untar the file into it, and start a fresh container on it.

Example 16: New volume

Type this:

docker volume create orders_restored

You will see:

orders_restored

What it means: Empty.

Example 17: Untar

Type this:

docker run --rm -v orders_restored:/to -v ~/backups:/from:ro alpine:3.20 tar xzf /from/orders-2026-10-25.tar.gz -C /to

You will see:

(no output)

What it means: Files are back in a volume.

Example 18: Prove it

Type this:

docker run -d --name odb2 -e POSTGRES_PASSWORD=example -v orders_restored:/var/lib/postgresql/data postgres:16
sleep 5; docker exec odb2 psql -U postgres -tAc 'SELECT count(*) FROM o'

You will see:

...
3

What it means: 3 rows. The backup works.

4. Method 2: database dump

odb runningno downtimepg_dumpwrites SQL textorders.sqlsmall, readable, portable
Picture 2: dump while running

Step 7: pg_dump while running

Why: Customers cannot wait while we stop the database.

What: Each database has a dump tool that makes a consistent copy while it runs. For Postgres it is pg_dump.

Example 19: Dump

Type this:

docker exec odb pg_dump -U postgres postgres > ~/backups/orders-$(date +%F).sql

You will see:

(no output)

What it means: SQL text in a host file.

Example 20: Look inside

Type this:

grep -A3 'COPY public.o' ~/backups/orders-2026-10-25.sql

You will see:

COPY public.o (id, item) FROM stdin;
1   Biryani
2   Dosa
3   Thali

What it means: Readable rows.

Example 21: Compressed

Type this:

docker exec odb pg_dump -U postgres -Fc postgres > ~/backups/orders.dump; ls -lh ~/backups/orders.dump

You will see:

-rw-r--r-- 1 ravi ravi 1.9K Oct 25 06:14 /home/ravi/backups/orders.dump

What it means: Custom format: small and restorable with pg_restore.

Step 8: Restore a dump

Why: Prove the dump is good.

What: Start an empty Postgres and feed it the SQL file with psql, or the .dump file with pg_restore.

Example 22: Empty database

Type this:

docker run -d --name odb3 -e POSTGRES_PASSWORD=example postgres:16

You will see:

9a0c...

What it means: No volume needed for the test.

Example 23: Load SQL

Type this:

sleep 5; docker exec -i odb3 psql -U postgres -q < ~/backups/orders-2026-10-25.sql

You will see:

(no output)

What it means: -i passes the file through standard input.

Example 24: Check

Type this:

docker exec odb3 psql -U postgres -tAc 'SELECT item FROM o ORDER BY id'

You will see:

Biryani
Dosa
Thali

What it means: All three orders.

Step 9: MySQL version

Why: Many Indian companies run MySQL, so learn its tool too.

What: mysqldump makes the SQL copy; mysql loads it back.

Example 25: Start MySQL

Type this:

docker run -d --name my -e MYSQL_ROOT_PASSWORD=example -v mydata:/var/lib/mysql mysql:8.4
sleep 20; docker exec my mysql -uroot -pexample -e "CREATE DATABASE shop; CREATE TABLE shop.p(n varchar(20)); INSERT INTO shop.p VALUES ('Kurta');"

You will see:

mysql: [Warning] Using a password on the command line interface can be insecure.

What it means: Practice password only.

Example 26: Dump

Type this:

docker exec my mysqldump -uroot -pexample --single-transaction shop > ~/backups/shop.sql; grep -c INSERT ~/backups/shop.sql

You will see:

1

What it means: --single-transaction gives a consistent copy without locking.

Example 27: Restore

Type this:

docker exec my mysql -uroot -pexample -e 'DROP DATABASE shop; CREATE DATABASE shop'
docker exec -i my mysql -uroot -pexample shop < ~/backups/shop.sql
docker exec my mysql -uroot -pexample -N -e 'SELECT n FROM shop.p'

You will see:

Kurta

What it means: Back.

5. Make it a habit

Step 10: Copy backups off the server

Why: If the server dies, backups on it die too.

What: Copy each file to S3 or another machine. Encrypt it on the way.

Example 28: Upload to S3

Type this:

aws s3 cp ~/backups/orders-2026-10-25.tar.gz s3://acme-db-backups/orders/ --sse AES256

You will see:

upload: backups/orders-2026-10-25.tar.gz to s3://acme-db-backups/orders/orders-2026-10-25.tar.gz

What it means: acme-db-backups is an example bucket name; use your own.

Example 29: List

Type this:

aws s3 ls s3://acme-db-backups/orders/

You will see:

2026-10-25 06:20:11    6395021 orders-2026-10-25.tar.gz

What it means: It is safe off the server.

Example 30: Keep 30 days

Type this:

find ~/backups -name 'orders-*' -mtime +30 -delete

You will see:

(no output)

What it means: Old local copies are cleaned; set an S3 lifecycle rule for the bucket too.

Step 11: A daily script with cron

Why: People forget. Machines do not.

What: Write a small script, make it executable with mode 0755, and run it from cron every night.

Example 31: Write the script

Type this:

printf '#!/bin/sh\nset -e\nd=$(date +%%F)\ndocker exec odb pg_dump -U postgres -Fc postgres > $HOME/backups/orders-$d.dump\naws s3 cp $HOME/backups/orders-$d.dump s3://acme-db-backups/orders/\n' > ~/pgbackup.sh && chmod 0755 ~/pgbackup.sh

You will see:

(no output)

What it means: printf writes the file; %% gives a literal percent sign.

Example 32: Run it once

Type this:

~/pgbackup.sh

You will see:

upload: ... to s3://acme-db-backups/orders/orders-2026-10-25.dump

What it means: Works by hand first.

Example 33: Schedule at 2 AM

Type this:

(crontab -l 2>/dev/null; echo '0 2 * * * $HOME/pgbackup.sh') | crontab -
crontab -l

You will see:

0 2 * * * $HOME/pgbackup.sh

What it means: Runs every night.

Step 12: Move a volume to another server

Why: The startup buys a bigger server and must move the database there.

What: Back up on the old server, copy the file with scp, and restore on the new one. The same tar file works on any Linux host with Docker.

Example 34: Copy the file

Type this:

scp ~/backups/orders-2026-10-25.tar.gz ubuntu@new-server:/home/ubuntu/

You will see:

orders-2026-10-25.tar.gz   100% 6245KB  41.2MB/s   00:00

What it means: Now it is on the new server.

Example 35: Restore there

Type this:

ssh ubuntu@new-server 'docker volume create orders && docker run --rm -v orders:/to -v /home/ubuntu:/from:ro alpine:3.20 tar xzf /from/orders-2026-10-25.tar.gz -C /to'

You will see:

orders

What it means: Same command as before.

Example 36: Start and check

Type this:

ssh ubuntu@new-server "docker run -d --name odb -e POSTGRES_PASSWORD=example -v orders:/var/lib/postgresql/data postgres:16; sleep 5; docker exec odb psql -U postgres -tAc 'SELECT count(*) FROM o'"

You will see:

...
3

What it means: The database moved with all three orders. Use the same Postgres major version on both sides.

Step 13: Clean up the lab

Why: Leave the machine tidy.

What: Remove the test containers and volumes; keep the backup files.

Example 37: Remove containers

Type this:

docker rm -f odb odb2 odb3 my

You will see:

odb
odb2
odb3
my

What it means: Gone.

Example 38: Remove volumes

Type this:

docker volume rm orders orders_restored mydata

You will see:

orders
orders_restored
mydata

What it means: Gone.

Example 39: Backups remain

Type this:

ls ~/backups

You will see:

orders-2026-10-25.sql
orders-2026-10-25.tar.gz
orders.dump
shop.sql

What it means: You could rebuild everything from these.

Check yourself

Q1. Why stop the database before a tar backup?

So the files are not changing during the copy.

Q2. Which method avoids downtime?

The database dump tool, like pg_dump.

Q3. How do you know a backup is good?

Restore it into a new volume or database and check the data.

Q4. Why copy backups to S3?

If the server dies, local backups die with it.

Q5. What makes mysqldump consistent without locks?

--single-transaction.

Friends, if you took a backup but never tested a restore, it is not a backup. Did you understand? Let us try it once more. Do one restore every week.

Ravindra Bagale's Tip

Always check the size of the backup file. A 0-byte file means danger.

Lab: try at home

  1. Back up a Postgres volume with tar and restore it into a new volume.
  2. Dump it with pg_dump and restore into a fresh container.
  3. Do the same with mysqldump.
  4. Upload a backup to your own S3 bucket.
  5. Schedule the script with cron and check the next morning.

Recap

  • tar via a helper container copies raw volume files; stop the app first.
  • Dump tools copy a running database safely.
  • Always restore to prove a backup.
  • Keep copies off the server, encrypted.
  • Automate with a script and cron.

Ravi Sir's Cards for this lesson

मराठी cards