Postgres with Docker Compose
When running containerized services on a homelab server, many call for a Postgres database in the cluster. These are the defaults I’m using for configuring the database, health checks, backups to NAS, and a restore script.
Docker Compose Configuration
In docker-compose.yml
:
services:
db:
image: postgres:17-alpine
restart: unless-stopped
shm_size: 256mb
healthcheck:
test: ['CMD', 'pg_isready', '-U', "${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5
volumes:
- ${POSTGRES_DATA_DIR}:/var/lib/postgresql/data
- ${BACKUP_PATH}:/backups
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
This defines a db
service using the latest version of Postgres, including volume mounts for data persistence and backups.
Environment File
In .env
:
# PostgreSQL Variables
POSTGRES_DB=mydatabase
POSTGRES_USER=myuser
POSTGRES_PASSWORD=mypassword
# SSD mount for working postgresql data
POSTGRES_DATA_DIR=/path/to/postgres/data/dir
# NAS mount for persisted backups
BACKUP_PATH=/mnt/nas/PostgreSQLBackups
The .env
file is automatically loaded by docker-compose.
Backup Script
In backup.sh
:
#!/bin/bash
# Load environment variables
source .env
# Format for the backup filename
BACKUP_DATE=$(date +%F)
BACKUP_FILENAME="/backups/${POSTGRES_DB}_${BACKUP_DATE}.dump"
# Perform the backup
docker-compose exec db pg_dump -U ${POSTGRES_USER} ${POSTGRES_DB} > ${BACKUP_FILENAME}
# Optional: Clean up old backups
# find /backups/* -mtime +30 -exec rm {} \;
Make the script executable: chmod +x backup.sh
.
Cron Schedule for Backup
Add to crontab (crontab -e
) to run the backup at 3 a.m. daily:
0 3 * * * /path/to/backup.sh
Restore Script
For restoring a database, use restore.sh
:
#!/bin/bash
# Load environment variables
source .env
# Ensure there's a filename argument
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <backup_filename>"
exit 1
fi
BACKUP_FILENAME=$1
# Check the backup file exists
if [ ! -f "$BACKUP_PATH/$BACKUP_FILENAME" ]; then
echo "Backup file not found: $BACKUP_PATH/$BACKUP_FILENAME"
exit 1
fi
# Restore the database
cat $BACKUP_PATH/$BACKUP_FILENAME | docker-compose exec db psql -U $POSTGRES_USER -d $POSTGRES_DB
echo "Database restored from $BACKUP_FILENAME"
Make the script executable: chmod +x restore.sh
.
Run a restore like this:
./restore.sh mydatabase_YYYY-MM-DD.dump