Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions backup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ BAK_POSTGRESQL_DATABASE_ENABLED=0
BAK_POSTGRESQL_DATABASE_WARNING_IF_DOWN=0
BAK_POSTGRESQL_DATABASE_ALLOW_ALL=1

BAK_POSTGRESQL_CONTAINERS_ENABLED=0
BAK_POSTGRESQL_CONTAINERS_WARNING_IF_DOWN=0
BAK_POSTGRESQL_CONTAINERS_ALLOW_ALL=1
BAK_POSTGRESQL_CONTAINERS=()

### Configuration ##################################################

BAK_CONFIG_GENERAL_FILE="$BAK_CONFIG_PATH/general.conf"
Expand Down Expand Up @@ -270,6 +275,12 @@ berror=$?
if [ $berror -ne 0 ]; then $ECHO_BIN "ERROR : Making PostgreSQL Databases backup (error = $berror)" >> $BAK_OUTPUT; fi
if [ $backup_error -eq 0 ]; then backup_error=$berror; fi

# Backup PostgreSQL databases inside Docker containers
postgresql_containers_backup
berror=$?
if [ $berror -ne 0 ]; then $ECHO_BIN "ERROR : Making PostgreSQL Containers Databases backup (error = $berror)" >> $BAK_OUTPUT; fi
if [ $backup_error -eq 0 ]; then backup_error=$berror; fi

# Backup sources
sources_backup_loop
berror=$?
Expand Down
69 changes: 69 additions & 0 deletions config-dist/database.conf
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,72 @@ BAK_POSTGRESQL_DATABASE_PATH=$BAK_DATA_PATH/$BAK_POSTGRESQL_DATABASE_DIR
BAK_POSTGRESQL_DATABASE_ALLOW_ALL=1
BAK_POSTGRESQL_DATABASE_ALLOW=("postgres")
BAK_POSTGRESQL_DATABASE_DISALLOW=("template0" "template1")

# PostgreSQL on Docker containers
##########################################################
#
# Backup PostgreSQL databases that run inside Docker containers.
# The dump is generated by running pg_dump *inside* the container,
# so a real SQL dump is produced (instead of just a volume archive).
#
# For each container listed in BAK_POSTGRESQL_CONTAINERS the script
# will:
# 1. Check that the container is running
# 2. List databases via BAK_POSTGRESQL_CONTAINERS_LIST_CMD
# 3. Dump each allowed database via BAK_POSTGRESQL_CONTAINERS_BACKUP_CMD
#
# The semantics intentionally mirror BAK_POSTGRESQL_DATABASE_BACKUP_CMD
# but the backup function receives two arguments: <container> <database>

DOCKER_BIN=/usr/bin/docker

# List of Docker container names that run a PostgreSQL server.
# Example: BAK_POSTGRESQL_CONTAINERS=("pg-app" "pg-billing")
BAK_POSTGRESQL_CONTAINERS=()

# PostgreSQL superuser inside the container, used by the default
# list and dump commands.
BAK_POSTGRESQL_CONTAINERS_USER=postgres

# Default list / dump implementations. Override these variables in
# config/database.conf to use custom commands or credentials.
BAK_POSTGRESQL_CONTAINERS_LIST_CMD="postgresql_container_databases"
BAK_POSTGRESQL_CONTAINERS_BACKUP_CMD="postgresql_container_dump"

postgresql_container_databases() {
local container=$1

if [ -n "$container" ]; then
$ECHO_BIN " CMD : $DOCKER_BIN exec -i $container psql -U $BAK_POSTGRESQL_CONTAINERS_USER -Atc \"SELECT datname FROM pg_database WHERE datistemplate = false;\"" >> $BAK_OUTPUT_EXTENDED
$DOCKER_BIN exec -i "$container" psql -U "$BAK_POSTGRESQL_CONTAINERS_USER" -Atc "SELECT datname FROM pg_database WHERE datistemplate = false;"
fi
}

postgresql_container_dump() {
local container=$1
local database=$2

if [ -n "$container" ] && [ -n "$database" ]; then
$ECHO_BIN " CMD : $DOCKER_BIN exec -i $container pg_dump -U $BAK_POSTGRESQL_CONTAINERS_USER -Fp $database" >> $BAK_OUTPUT_EXTENDED
$DOCKER_BIN exec -i "$container" pg_dump -U "$BAK_POSTGRESQL_CONTAINERS_USER" -Fp "$database"
fi
}

BAK_POSTGRESQL_CONTAINERS_ENABLED=1

if [ ! -x "$DOCKER_BIN" ]; then
# Disabled because no docker binary found
BAK_POSTGRESQL_CONTAINERS_ENABLED=2
fi

# BAK_POSTGRESQL_CONTAINERS_WARNING_IF_DOWN
# - If 1, write a warning (not an error) if a container is not running.
# BAK_POSTGRESQL_CONTAINERS_WARNING_IF_DOWN=0 by default
BAK_POSTGRESQL_CONTAINERS_WARNING_IF_DOWN=0

BAK_POSTGRESQL_CONTAINERS_DIR=postgresql-containers
BAK_POSTGRESQL_CONTAINERS_PATH=$BAK_DATA_PATH/$BAK_POSTGRESQL_CONTAINERS_DIR

BAK_POSTGRESQL_CONTAINERS_ALLOW_ALL=1
BAK_POSTGRESQL_CONTAINERS_ALLOW=("postgres")
BAK_POSTGRESQL_CONTAINERS_DISALLOW=("template0" "template1")
132 changes: 132 additions & 0 deletions lib/main.sh
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,115 @@ postgresql_datafiles_backup() {
return $error
}

##################################################################
# postgresql_container_check <container>
# Return 0 if the named docker container is running, 1 otherwise
##################################################################
postgresql_container_check() {
local container=$1
local error=0
local state=

$ECHO_BIN -n "PostgreSQL container '$container' status: " >> $BAK_OUTPUT
$ECHO_BIN "- PostgreSQL container '$container' Status -----------" >> $BAK_OUTPUT_EXTENDED
state=$($DOCKER_BIN inspect -f '{{.State.Running}}' "$container" 2>> $BAK_OUTPUT_EXTENDED)
if [ "$state" == "true" ]; then
error=0
$ECHO_BIN -n "OK" >> $BAK_OUTPUT
else
error=1
$ECHO_BIN -n "FAIL" >> $BAK_OUTPUT
fi
$ECHO_BIN "-----------------------------------------------" >> $BAK_OUTPUT_EXTENDED
$ECHO_BIN " ($error)" >> $BAK_OUTPUT
return $error
}

##################################################################
# postgresql_containers_backup
# Backup PostgreSQL databases that live inside Docker containers
##################################################################
postgresql_containers_backup() {
local error=0
local db_error=0
local size=0
local file=
local container=
local i=

$ECHO_BIN >> $BAK_OUTPUT
$ECHO_BIN "Backup PostgreSQL Containers Databases" >> $BAK_OUTPUT

if [ $BAK_POSTGRESQL_CONTAINERS_ENABLED -eq 0 ]; then
$ECHO_BIN " Disabled by configuration" >> $BAK_OUTPUT
return 0
fi

if [ $BAK_POSTGRESQL_CONTAINERS_ENABLED -eq 2 ]; then
$ECHO_BIN " Disabled because no docker binary found" >> $BAK_OUTPUT
return 0
fi

if [ ${#BAK_POSTGRESQL_CONTAINERS[@]} -eq 0 ]; then
$ECHO_BIN " No containers configured (BAK_POSTGRESQL_CONTAINERS empty)" >> $BAK_OUTPUT
return 0
fi

for container in "${BAK_POSTGRESQL_CONTAINERS[@]}"; do
$ECHO_BIN >> $BAK_OUTPUT
$ECHO_BIN " Container: $container" >> $BAK_OUTPUT

if ! postgresql_container_check "$container"; then
if [ $BAK_POSTGRESQL_CONTAINERS_WARNING_IF_DOWN -eq 1 ]; then
$ECHO_BIN " WARNING - Container '$container' is not running, skipping" >> $BAK_OUTPUT
continue
fi
$ECHO_BIN " FAIL - Container '$container' is not running" >> $BAK_OUTPUT
error=1
continue
fi

for i in $($BAK_POSTGRESQL_CONTAINERS_LIST_CMD "$container");
do
if $(contains "${BAK_POSTGRESQL_CONTAINERS_DISALLOW[@]}" "$i"); then
continue
fi

$ECHO_BIN -n " $i ... " >> $BAK_OUTPUT

if [ $BAK_POSTGRESQL_CONTAINERS_ALLOW_ALL -eq 1 ] || $(contains "${BAK_POSTGRESQL_CONTAINERS_ALLOW[@]}" "$i"); then
file="$BAK_POSTGRESQL_CONTAINERS_PATH/${BAK_DATE}-${container}-${i}.sql"
if [ $BAK_DEBUG -eq 1 ]; then
$ECHO_BIN -n "$BAK_POSTGRESQL_CONTAINERS_BACKUP_CMD $container $i > '$file' ... " >> $BAK_OUTPUT
else
$ECHO_BIN " CMD : $BAK_POSTGRESQL_CONTAINERS_BACKUP_CMD $container $i > '$file'" >> $BAK_OUTPUT_EXTENDED
$BAK_POSTGRESQL_CONTAINERS_BACKUP_CMD "$container" "$i" > "$file" 2>> $BAK_OUTPUT_EXTENDED
fi
db_error=$?
if [ $db_error -eq 0 ]; then
$ECHO_BIN -n "OK" >> $BAK_OUTPUT
$ECHO_BIN " CMD : file_size '$file'" >> $BAK_OUTPUT_EXTENDED
size=`file_size $file`
$ECHO_BIN " ($size)" >> $BAK_OUTPUT
$ECHO_BIN " SIZE : $size" >> $BAK_OUTPUT_EXTENDED
else
$ECHO_BIN "FAIL (error = $db_error)" >> $BAK_OUTPUT
error=1
fi
else
$ECHO_BIN "SKIPPED" >> $BAK_OUTPUT
fi
done
done

# Process this backup
if [ $error -eq 0 ]; then
backup_process "$BAK_POSTGRESQL_CONTAINERS_PATH" "${BAK_DATE}-postgresql-containers"
fi

return $error
}

##################################################################
# server_configuration_backup
# Backup server configuration files
Expand Down Expand Up @@ -1197,6 +1306,12 @@ directories_create() {
$MKDIR_BIN "$BAK_POSTGRESQL_DATABASE_PATH"
fi

# Create PostgreSQL containers database directory (if needed)
if [ $BAK_POSTGRESQL_CONTAINERS_ENABLED -ne 0 ] && [ ! -d "$BAK_POSTGRESQL_CONTAINERS_PATH" ]; then
$ECHO_BIN "INFO : Creating PostgreSQL containers database dir '$BAK_POSTGRESQL_CONTAINERS_PATH'"
$MKDIR_BIN "$BAK_POSTGRESQL_CONTAINERS_PATH"
fi

# Create server config directory (if needed)
if [ $BAK_CONFIG_ENABLED -ne 0 ] && [ ! -d "$BAK_CONFIG_SERVER_PATH" ]; then
$ECHO_BIN "INFO : Creating server config dir '$BAK_CONFIG_SERVER_PATH'"
Expand Down Expand Up @@ -1529,6 +1644,19 @@ config_show() {
done
fi

if [ $BAK_POSTGRESQL_CONTAINERS_ENABLED -eq 0 ]; then
postgresql_containers='Disabled by configuration'
elif [ $BAK_POSTGRESQL_CONTAINERS_ENABLED -eq 2 ]; then
postgresql_containers='Disabled because no docker binary found'
elif [ ${#BAK_POSTGRESQL_CONTAINERS[@]} -eq 0 ]; then
postgresql_containers='No containers configured'
else
for container in "${BAK_POSTGRESQL_CONTAINERS[@]}"; do
if [ -z "$postgresql_containers" ]; then postgresql_containers="$container";
else postgresql_containers=`$ECHO_BIN -e "${postgresql_containers}\n${container}"`; fi
done
fi

if [ $BAK_CONFIG_ENABLED -eq 0 ]; then
server='Disabled by configuration'
else
Expand Down Expand Up @@ -1628,6 +1756,10 @@ PostgreSQL Databases:
-------------------------------------------------
$postgresql_databases

PostgreSQL Containers:
-------------------------------------------------
$postgresql_containers

Data:
-------------------------------------------------
$data
Expand Down