KISS: Backup Databases inside Docker Containers via bash

“Keep it simple [and] stupid!” – Not only an important principle, but also a series on this blog.

If you ever find yourself in the position of running multiple Docker containers with various databases, you will inevitably ask yourself at some point how you actually pack all that data cleverly into a backup.

Docker itself offers little out-of-box backup of the entire container, which also may not always be necessary. Most of the time it is sufficient to create backups of the database in the same way as you are used to outside of Docker – via mysqldump, mongodump, etc …

Since I often find myself in this situation, I wrote a small bash script that can run as a cron job on the appropriate server and creates backups for you and deletes old backups after a specified number of days.

If you want to use this script yourself, the first thing you should do is to adjust the “Settings” and then you can learn how to use the script under the “Main” section.

Please note, that this is not a sufficient backup of your data. You still need to copy the files to a different storage or save them elsewhere.

#!/bin/bash

# ****
# Settings
# ****

backup_dir=/root/backups
tmp_dir=/tmp/backups
retention_days=7


# ****
# Constants and Functions
# ****

TIMESTAMP=$(date +%F)
RED="\e[31m"
GREEN="\e[32m"
ENDCOLOR="\e[0m"

function log () {
   echo -e "[${GREEN}+${ENDCOLOR}] $1"
}
function err () {
   echo -e "[${RED}-${ENDCOLOR}] $1"
}

function backup_mysql () {
   # Parameters: container_name, user, password, db_name, filename
   docker exec $1 /usr/bin/mysqldump -u $2 --password=$3 $4 > $backup_dir/$5_$TIMESTAMP.sql
}

function backup_postgresql () {
   # Parameters: container_name, user, password, db_name, filename
   docker exec $1 /usr/bin/pg_dump --dbname=postgresql://$2:$3@127.0.0.1:5432/$4 > $backup_dir/$5_$TIMESTAMP.sql
}

function backup_postgresql_all () {
   # Parameters: container_name, user, password, filename
   docker exec $1 /usr/bin/pg_dumpall --dbname=postgresql://$2:$3@127.0.0.1:5432 > $backup_dir/$4_$TIMESTAMP.sql
}

function backup_mongodb () {
   # Parameters: container_name, user, password, db_name, file_name 
   docker exec -t $1 mongodump --username $2 --password $3 --authenticationDatabase admin --out /data/mongobackup_data --db $4
   docker cp $1:/data/mongobackup_data $tmp_dir
   tar cfvz $tmp_dir/$5_$TIMESTAMP.tar.gz $tmp_dir/mongobackup_data
   rm -r $tmp_dir/mongobackup_data
   docker exec $1 rm -rf /data/mongobackup_data
}

function backup_mongodb_without_auth () {
   # Paramters: container_name,db_name, file_name 
   docker exec -t $1 mongodump --out /data/mongobackup_data --db $2
   docker cp $1:/data/mongobackup_data $tmp_dir 
   tar cfvz $backup_dir/$3_$TIMESTAMP.tar.gz $tmp_dir/mongobackup_data
   rm -r $tmp_dir/mongobackup_data
   docker exec $1 rm -rf /data/mongobackup_data
}

# ****
# Main
# ****

log "Saving SMC Blog WordPress DB"
backup_mysql website_wordpress-db root SUPERSAFE_PW smclab_wordpress smclabblog

log "Saving Public Issue Data Guide DB"
backup_mongodb_without_auth pidg-cms-db payload mongodb_backup


# Handle old Backups
log "Checking and deleting old backups."
find $backup_dir/ -maxdepth 1 -type f -mtime +$retention_days -exec rm -rf {} \;

log "All Done"