PostgreSQL Backups with Docker


For brevity it is assumed that you will be running the below commands against local environment, however, this is by no means mandatory so feel free to switch to production.yml when needed.


  1. the project was generated with use_docker set to y;

  2. the stack is up and running: docker compose -f local.yml up -d postgres.

Creating a Backup

To create a backup, run:

$ docker compose -f local.yml exec postgres backup

Assuming your project’s database is named my_project here is what you will see:

Backing up the 'my_project' database...
SUCCESS: 'my_project' database backup 'backup_2018_03_13T09_05_07.sql.gz' has been created and placed in '/backups'.

Keep in mind that /backups is the postgres container directory.

Viewing the Existing Backups

To list existing backups,

$ docker compose -f local.yml exec postgres backups

These are the sample contents of /backups:

These are the backups you have got:
total 24K
-rw-r--r-- 1 root root 5.2K Mar 13 09:05 backup_2018_03_13T09_05_07.sql.gz
-rw-r--r-- 1 root root 5.2K Mar 12 21:13 backup_2018_03_12T21_13_03.sql.gz
-rw-r--r-- 1 root root 5.2K Mar 12 21:12 backup_2018_03_12T21_12_58.sql.gz

Copying Backups Locally

If you want to copy backups from your postgres container locally, docker cp command will help you on that.

For example, given 9c5c3f055843 is the container ID copying all the backups over to a local directory is as simple as

$ docker cp 9c5c3f055843:/backups ./backups

With a single backup file copied to . that would be

$ docker cp 9c5c3f055843:/backups/backup_2018_03_13T09_05_07.sql.gz .

You can also get the container ID using docker compose -f local.yml ps -q postgres so if you want to automate your backups, you don’t have to check the container ID manually every time. Here is the full command

$ docker cp $(docker compose -f local.yml ps -q postgres):/backups ./backups

Restoring from the Existing Backup

To restore from one of the backups you have already got (take the backup_2018_03_13T09_05_07.sql.gz for example),

$ docker compose -f local.yml exec postgres restore backup_2018_03_13T09_05_07.sql.gz

You will see something like

Restoring the 'my_project' database from the '/backups/backup_2018_03_13T09_05_07.sql.gz' backup...
INFO: Dropping the database...
INFO: Creating a new database...
INFO: Applying the backup to the new database...

(1 row)

# ...
SUCCESS: The 'my_project' database has been restored from the '/backups/backup_2018_03_13T09_05_07.sql.gz' backup.

Backup to Amazon S3

For uploading your backups to Amazon S3 you can use the aws cli container. There is an upload command for uploading the postgres /backups directory recursively and there is a download command for downloading a specific backup. The default S3 environment variables are used.

$ docker compose -f production.yml run --rm awscli upload
$ docker compose -f production.yml run --rm awscli download backup_2018_03_13T09_05_07.sql.gz

Remove Backup

To remove backup you can use the rmbackup command. This will remove the backup from the /backups directory.

$ docker compose -f local.yml exec postgres rmbackup backup_2018_03_13T09_05_07.sql.gz

Upgrading PostgreSQL

Upgrading PostgreSQL in your project requires a series of carefully executed steps. Start by halting all containers, excluding the postgres container. Following this, create a backup and proceed to remove the outdated data volume.

$ docker compose -f local.yml down
$ docker compose -f local.yml up -d postgres
$ docker compose -f local.yml run --rm postgres backup
$ docker compose -f local.yml down
$ docker volume rm my_project_postgres_data


Neglecting to remove the old data volume may lead to issues, such as the new postgres container failing to start with errors like FATAL:  database files are incompatible with server, and could not translate host name "postgres" to address: Name or service not known.

To complete the upgrade, update the PostgreSQL version in the corresponding Dockerfile (e.g. compose/production/postgres/Dockerfile) and build a new version of PostgreSQL.

$ docker compose -f local.yml build postgres
$ docker compose -f local.yml up -d postgres
$ docker compose -f local.yml run --rm postgres restore backup_2018_03_13T09_05_07.sql.gz
$ docker compose -f local.yml up -d