How to Back Up PostgreSQL in Docker (Local, S3, and Plakar)

nickjj1 pts0 comments

How to Back Up PostgreSQL in Docker (Local, S3, and Plakar) — Nick JanetakisLearn Docker With My Newest Course<br>Dive into Docker takes you from "What is Docker?" to confidently applying Docker to your own projects. It's packed with best practices and examples.<br>Start Learning Docker &rarr;

Updated on July 21, 2026<br>in<br>#deployment, #docker<br>How to Back Up PostgreSQL in Docker (Local, S3, and Plakar)

We'll cover doing backups and restores with and without Plakar and show how<br>you can save money along the way.<br>Quick Jump:<br>Prefer video? Here&rsquo;s a walkthrough on YouTube.<br>The data you store in your database is really important. For most businesses<br>it&rsquo;s everything and losing it could be a company ending event. Needless to say,<br>backups are good.<br>In this post we&rsquo;re going to focus on creating reliable daily backups for your<br>self-hosted web applications using PostgreSQL where everything is running in<br>Docker. We&rsquo;ll be covering restoring too since that&rsquo;s just as important!<br>Not using Postgres? No worries, switching the commands for MySQL is easy<br>Not using Docker? No problem, you can adjust those commands in a few seconds<br>This tutorial is really like 7 tutorials in 1:<br>How to perform daily backups with just Postgres and a cron job<br>How to back your database up to your file system or S3 bucket<br>How to restore your database from a backup with only Postgres<br>Understanding how the free and open source version of Plakar can save you money<br>A crash course in how to use Plakar for both local and S3 storagePlakar supports other storage engines besides S3 too, more on that later!

How to perform daily backups using Plakar<br>How to restore your database using Plakar<br>I&rsquo;m extremely skeptical of using 3rd party tools, especially for something as<br>important as backups but Plakar has a number of interesting features to help<br>reduce complexity and save you time and money.

How I Backed Up My Databases for 10+ Years<br>Maybe your story is similar? It&rsquo;s a fairly common set up. Dump and gzip the<br>database every day to either a volume mounted disk or S3 bucket.<br>On the server where PostgreSQL is running in Docker I&rsquo;d wire up a few basic<br>things.<br>Script to Perform the Backup<br>Throughout this post I&rsquo;m going to use this example Dockerized web app<br>https://github.com/nickjj/docker-flask-example since it includes running a<br>web server, PostgreSQL and more. I&rsquo;ve extended it slightly to log web requests<br>to a database table.<br>Feel free to use any project you want since the only thing that applies here is<br>having Postgres running in a container with a means to add rows to a table.<br>None of the scripts are going to be coupled to this specific project.<br>An expectation is the database container is already running. We&rsquo;re going to<br>exec into it and run a backup command. Normally that would mean you have<br>everything up and running with docker compose up somewhere. If it&rsquo;s not<br>already running you can replace exec with run in the scripts.<br>This script would be saved to /usr/local/bin/pgbackup on the server, or<br>anywhere you want on your dev box if you want to test all of this locally.<br>Don&rsquo;t forget to chmod +x /usr/local/bin/pgbackup it to make it executable:<br>#!/usr/bin/env bash<br># Create a full gzipped database backup.<br># Usage:<br># pgbackup myapp<br># pgbackup myapp --today

set -o errexit<br>set -o pipefail<br>set -o nounset

PROJECT="${1}"<br>FLAG="${2:-}"<br>DATE=""

[ "${FLAG}" = "--today" ] && DATE="-$(date +%F)"

BACKUP_PATH="${HOME}/db-backups"<br>BACKUP_FILE="${PROJECT}${DATE}.sql.gz"<br>BACKUP_TMP_FILE="${BACKUP_PATH}/${BACKUP_FILE}.tmp"

# Ensure the temp file is deleted when this script exits.<br>trap 'rm -f "${BACKUP_TMP_FILE}"' EXIT

mkdir -p "${BACKUP_PATH}"

docker compose exec --no-tty postgres pg_dumpall --username "${PROJECT}" | gzip >"${BACKUP_TMP_FILE}"<br>mv "${BACKUP_TMP_FILE}" "${BACKUP_PATH}/${BACKUP_FILE}"

The above isn&rsquo;t too crazy. It creates a complete dump of your database with<br>pg_dumpall and to keep the script general purpose it supports passing in the<br>project name since you might be backing up multiple projects.<br>Compression is used to reduce the size by a substantial amount. The exact<br>savings depend on your data, but cutting the size in half is common.<br>Backup strategy:<br>The date is optional because if you only want 1 day&rsquo;s worth of backups, you<br>would be overwriting the file which has no date.<br>Otherwise you can pass in --today and -YYYY-MM-DD will be added to the file<br>name in case you wanted to keep a week&rsquo;s worth of backups, etc..<br>Resilient backups:<br>Given the above, an important step is writing it to a temp file and then moving<br>it to the final destination. That&rsquo;s because redirecting with the shell > will<br>immediately truncate the file before the pipeline starts! If the backup failed<br>half way through, we wouldn&rsquo;t want a partial backup to overwrite the last<br>working backup. In case you&rsquo;re curious, tee has the same issue. I&rsquo;ve written<br>about this pattern in the past.<br>The...

rsquo docker backups plakar database backup

Related Articles