How to Backup and Restore Docker Volumes
Learn how to backup and restore Docker volumes. Specifically, we will backup a Postgres Database using Docker volumes.
Table of Contents 📖
- Docker Volumes and Backups
- Creating a Postgres Volume to Backup
- Creating a Tarball of the Volume Data
- Creating a Volume from the Backup
- Verifying the Backup Worked
Docker Volumes and Backups
Docker volumes are useful for backups, restores, and migrations. For example, we can use them to back up and restore a Postgres database.
Creating a Postgres Volume to Backup
To start, lets create a Postgres container/volume and fill it with some default data using an initialization script.
CREATE TABLE subscriber (
subscriber_id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL
);
INSERT INTO subscriber (name, email) VALUES
('wittcode', 'a@a.com'),
('Sabin', 'b@b.com'),
('Greg', 'c@c.com'),
('Spencer', 'd@d.com');
INFO: Initialization scripts are SQL or script files that are placed inside the docker-entrypoint-initdb.d folder in the docker image. They are ran after the default postgres user and database are created.
Now lets create a Dockerfile to initialize our database.
FROM postgres
ENV POSTGRES_HOST=p-c
ENV POSTGRES_PORT=5432
ENV POSTGRES_DB=my-db
ENV POSTGRES_USER=wittcepter
ENV POSTGRES_PASSWORD=bestChromeExtension
COPY subscriber.sql /docker-entrypoint-initdb.d/
Note that we set some necessary environment variables for the postgres image to work properly. Now we just need to build the Docker image with the docker build command.
docker build -t p-i .
Next lets create a docker container from this image using the docker run command.
docker run --name p-c -p 5432:5432 -v postgres-data:/var/lib/postgresql/data p-i
Now we have a Postgres Docker volume called postgres-data that contains all our Postgres data. This is because, by default, the /var/lib/postgresql/data directory is where the database files for postgres are stored.
Creating a Tarball of the Volume Data
Now that we have our Postgres Docker volume, lets create a tarball of it. We can do this using the tar command.
INFO: A tar is a software utility for collecting many files into an acrhive file. They are used for distribution and backup purposes.
docker run --rm --volumes-from p-c -v $(pwd):/backup busybox tar cf /backup/postgres-backup.tar var/lib/postgresql/data
Here we are creating a tarball of the data referenced by the postgres-data volume. Specifically, we spin up a postgres container and then tear it down after we performed the backup of the Postgres volume.
- --rm - Removes the container after it is stopped.
- --volumes-from - Allows you to mount the volumes of another container. Here we are mounting our postgres-data volume.
- -v $(pwd):/backup - Maps the current directory to /backup inside the container. This is where we will place our backup tar file.
- busybox - A small image containing many common UNIX utilities. Here we use it to run the tar command.
- tar cf /backup/postgres-backup.tar var/lib/postgresql/data - Create a new archive file called postgres-backup.tar from the data our postgres-data volume creates. The c flag tells tar to create a new archive and the f flag points to the filename to give the archive.
INFO: The tar command never moves or deletes any of the original directories and files, it only makes archived copies.
Because of our host volume, the postgres-backup.tar file will appear in the current working directory.
Creating a Volume from the Backup
Now that we have a tarball of our volume data, lets create a volume from it. To do this, we will run another busybox container and then use the tar command to extract the backup tarball into a volume.
docker run --rm -v postgres-data-2:/var/lib/postgresql/data -v ./postgres-backup.tar:/postgres-backup.tar busybox tar xvf /postgres-backup.tar
Here we are creating a new volume from our postgres-backup.tar file. After this volume is created, we can apply it to another container.
- --rm - Removes the container after it is stopped.
- -v postgres-data-2:/var/lib/postgresql/data - Maps the postgres-data-2 volume to /var/lib/postgresql/data inside the container. This will fill the postgres-data-2 volume with the data from the postgres-backup.tar file.
- -v ./postgres-backup.tar:/postgres-backup.tar - Copies the postgres-backup.tar into the container.
- busybox - A small image containing many common UNIX utilities. Here we use it to run the tar command.
- tar xf /postgres-backup.tar - Extract the postgres-backup.tar. This will fill the postgres-data-2 volume.
INFO: tar xf is the basic untar command where x means extract and f means file.
Verifying the Backup Worked
Now that we have our backup volume, lets create another Postgres container from it.
docker run --name p-c-2 -p 5433:5432 -v postgres-data-2:/var/lib/postgresql/data p-i
Now lets use psql to check that the data we initialized our p-c container with is present in our p-c-2 container.
docker exec -it p-c-2 bash
psql -U wittcepter my-db
SELECT * FROM subscriber;
subscriber_id | name | email
---------------+----------+---------
1 | wittcode | a@a.com
2 | Sabin | b@b.com
3 | Greg | c@c.com
4 | Spencer | d@d.com
(4 rows)