Skip to content

Commit

Permalink
Reorganise and improve database images
Browse files Browse the repository at this point in the history
- specify the database to backup (only mysql)
- specify the source variable in which to store the database dumps
- use env check globally
- add support for docker secrets (see #9, includes database passwords,
 gpg private key and passphrase)
- remove mysql restore script since it does not work and is obsolete
 because of restore command

see #5
  • Loading branch information
sargreal committed Sep 6, 2020
1 parent cc4d440 commit edc1fa6
Show file tree
Hide file tree
Showing 15 changed files with 193 additions and 95 deletions.
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@
- [Enforcing Full Backups Periodically](#enforcing-full-backups-periodically)
- [Automatically remove old backups](#automatically-remove-old-backups)
- [Post scripts and pre scripts (prepost strategies)](#post-scripts-and-pre-scripts-prepost-strategies)
- [Provided PrePost-Strategies](#provided-prepost-strategies)
- [Container Scripts](#container-scripts)
- [Build The Project](#build-the-project)
- [Multiple Backups](#multiple-backups)
- [Docker Secrets](#docker-secrets)
- [Build the Image](#build-the-image)
- [Run the Image](#run-the-image)

Expand Down Expand Up @@ -508,7 +510,12 @@ All `.sh` files located in the `$duplicity_action` folder will be executed in al

When using prepost strategies, this will be the execution flow: `pre-scripts -> stop containers -> duplicity action -> start containers -> post-scripts`.

Some premade strategies are available at [prepost strategies](prepost_strategies).
### Provided PrePost-Strategies
Some premade strategies are available at [prepost strategies](prepost_strategies). These are

- [mongodb](prepost_strategies/mongodb/README.md)
- [mysql](prepost_strategies/mysql/README.md)


## Container Scripts

Expand Down Expand Up @@ -602,6 +609,13 @@ $ docker run -d \
fekide/volumerize
~~~~

## Docker Secrets

The following variables are supported to be stored in files, the location specified in variables ending with `_FILE`. See [Docker Secrets Documentation](https://docs.docker.com/engine/swarm/secrets/) for more info.

- `VOLUMERIZE_GPG_PRIVATE_KEY`
- `PASSPHRASE`

## Build the Image

~~~~
Expand Down
2 changes: 2 additions & 0 deletions imagescripts/base.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ DUPLICITY_TARGET=${VOLUMERIZE_TARGET}
DUPLICITY_MODE=""

function resolveOptions() {
file_env "PASSPHRASE"
file_env "VOLUMERIZE_GPG_PRIVATE_KEY"
DUPLICITY_OPTIONS="--allow-source-mismatch --archive-dir=${VOLUMERIZE_CACHE}"
if [ -n "${VOLUMERIZE_DUPLICITY_OPTIONS}" ]; then
DUPLICITY_OPTIONS=$DUPLICITY_OPTIONS" "${VOLUMERIZE_DUPLICITY_OPTIONS}
Expand Down
3 changes: 3 additions & 0 deletions imagescripts/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ set -o errexit

[[ ${DEBUG} == true ]] && set -x

source /opt/volumerize/env.sh

function pipeEnvironmentVariables() {
local environmentfile="/etc/profile.d/jobber.sh"
cat > ${environmentfile} <<EOF
Expand All @@ -16,6 +18,7 @@ GPG_KEY_ID=""

# Install GPG Key
if [ ! -f "/root/.gnupg/pubring.kbx" ]; then
file_env "VOLUMERIZE_GPG_PRIVATE_KEY"
if [ -n "${VOLUMERIZE_GPG_PRIVATE_KEY}" ]; then
gpg --allow-secret-key-import --import ${VOLUMERIZE_GPG_PRIVATE_KEY}
GPG_KEY_ID=$(gpg2 --list-secret-keys --keyid-format LONG | grep sec | awk 'NR==1{print $2; exit}')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash

##
# @private
Expand Down Expand Up @@ -27,9 +27,9 @@ function _check_env_ok {
##
function check_env {
echo "Checking environment variables for $1."
shift

for e_var in ""$@""; do
if [ $e_var = $1 ]; then continue; fi # Jump first arg

# Check if env var is setted, if not raise error
if [ "${!e_var}" = "" ]; then
Expand All @@ -41,3 +41,24 @@ function check_env {
done
echo "Environment variables ok."
}

# usage: file_env VAR [DEFAULT]
# ie: file_env 'XYZ_DB_PASSWORD' 'example'
# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of
# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature)
file_env() {
local var="$1"
local fileVar="${var}_FILE"
local def="${2:-}"
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
echo "Both $var and $fileVar are set (but are exclusive)"
fi
local val="$def"
if [ "${!var:-}" ]; then
val="${!var}"
elif [ "${!fileVar:-}" ]; then
val="$(< "${!fileVar}")"
fi
export "$var"="$val"
unset "$fileVar"
}
23 changes: 15 additions & 8 deletions prepost_strategies/mongodb/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ With this prepost strategy you can create dump of your MongoDB containers and sa
## Environment Variables

Aside of the required environment variables by Volumerize, this prepost strategy will require a couple of extra variables.
MONGO_USERNAME MONGO_PASSWORD MONGO_HOST MONGO_PORT
| Name | Description |
| -------------- | ---------------------------------------------------------- |
| MONGO_USERNAME | Username of the user who will perform the restore or dump. |
| MONGO_PASSWORD | Password of the user who will perform the restore or dump. |
| MONGO_HOST | MongoDB IP or domain. |
| MONGO_PORT | MongoDB port. |

| Name | Description |
| ----------------------- | ---------------------------------------------------------------------------------- |
| MONGO_USERNAME | Username of the user who will perform the restore or dump. |
| MONGO_PASSWORD | Password of the user who will perform the restore or dump. |
| MONGO_HOST | MongoDB IP or domain. |
| MONGO_PORT | MongoDB port. |
| VOLUMERIZE_MONGO_SOURCE | Variable name of source where dumps are to be stored (default `VOLUMERIZE_SOURCE`) |

## Example with Docker Compose

Expand Down Expand Up @@ -52,4 +53,10 @@ volumes:
backup:
```

Then execute `docker-compose exec volumerize backup` to create a backup of your database and `docker-compose exec volumerize restore` to restore it from your backup.
Then execute `docker-compose exec volumerize backup` to create a backup of your database and `docker-compose exec volumerize restore` to restore it from your backup.

## Docker Secrets

The following additional variables are supported to be stored in files, the location specified in variables ending with `_FILE`. See [Docker Secrets Documentation](https://docs.docker.com/engine/swarm/secrets/) for more info.

- `MONGO_PASSWORD`
32 changes: 32 additions & 0 deletions prepost_strategies/mongodb/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
version: "3"

services:
mongodb:
image: mongo
ports:
- 27017:27017
environment:
- MONGO_INITDB_ROOT_USERNAME=root
- MONGO_INITDB_ROOT_PASSWORD=1234
volumes:
- mongodb:/data/db

volumerize:
image: fekide/volumerize:mongodb
environment:
- VOLUMERIZE_SOURCE=/source
- VOLUMERIZE_TARGET=file:///backup
- MONGO_USERNAME=root
- MONGO_PASSWORD=1234
- MONGO_PORT=27017
- MONGO_HOST=mongodb
volumes:
- volumerize-cache:/volumerize-cache
- backup:/backup
depends_on:
- mongodb

volumes:
volumerize-cache:
mongodb:
backup:
16 changes: 13 additions & 3 deletions prepost_strategies/mongodb/postexecute/restore/mongorestore.sh
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
source /preexecute/utils/check-env.sh
#!/bin/bash

check_env "mongorestore" "MONGO_USERNAME" "MONGO_PASSWORD" "MONGO_HOST" "MONGO_PORT"
set -o errexit

source /opt/volumerize/env.sh

VOLUMERIZE_MONGO_SOURCE=${VOLUMERIZE_MONGO_SOURCE:-VOLUMERIZE_SOURCE}
export MONGO_SOURCE=${!VOLUMERIZE_MONGO_SOURCE}

file_env "MONGO_PASSWORD"
check_env "mongorestore" "MONGO_USERNAME" "MONGO_PASSWORD" "MONGO_HOST" "MONGO_PORT" "MONGO_SOURCE"

MONGO_SOURCE=${MONGO_SOURCE}/volumerize-mongo

echo "mongorestore starts"
mongorestore --host ${MONGO_HOST} --port ${MONGO_PORT} --username ${MONGO_USERNAME} --password "${MONGO_PASSWORD}" ${VOLUMERIZE_SOURCE}
mongorestore --host ${MONGO_HOST} --port ${MONGO_PORT} --username ${MONGO_USERNAME} --password "${MONGO_PASSWORD}" ${MONGO_SOURCE}
echo "Import done"
20 changes: 15 additions & 5 deletions prepost_strategies/mongodb/preexecute/backup/mongodump.sh
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
source /preexecute/utils/check-env.sh
#!/bin/bash

check_env "mongodump" "MONGO_USERNAME" "MONGO_PASSWORD" "MONGO_HOST" "MONGO_PORT"
set -o errexit

echo "Creating $VOLUMERIZE_SOURCE folder if not exists"
mkdir -p $VOLUMERIZE_SOURCE
source /opt/volumerize/env.sh

VOLUMERIZE_MONGO_SOURCE=${VOLUMERIZE_MONGO_SOURCE:-VOLUMERIZE_SOURCE}
export MONGO_SOURCE=${!VOLUMERIZE_MONGO_SOURCE}

file_env "MONGO_PASSWORD"
check_env "mongodump" "MONGO_USERNAME" "MONGO_PASSWORD" "MONGO_HOST" "MONGO_PORT" "MONGO_SOURCE"

MONGO_SOURCE=${MONGO_SOURCE}/volumerize-mongo

echo "Creating $MONGO_SOURCE folder if not exists"
mkdir -p $MONGO_SOURCE

echo "mongodump starts"
mongodump --host ${MONGO_HOST} --port ${MONGO_PORT} --username ${MONGO_USERNAME} --password "${MONGO_PASSWORD}" --out ${VOLUMERIZE_SOURCE}
mongodump --host ${MONGO_HOST} --port ${MONGO_PORT} --username ${MONGO_USERNAME} --password "${MONGO_PASSWORD}" --out ${MONGO_SOURCE}
1 change: 0 additions & 1 deletion prepost_strategies/mysql/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,3 @@ RUN apk add --no-cache \

COPY postexecute /postexecute
COPY preexecute /preexecute
COPY scripts /etc/volumerize
19 changes: 13 additions & 6 deletions prepost_strategies/mysql/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ With this prepost strategy you can create a .sql backup of your MySQL containers

Aside of the required environment variables by Volumerize, this prepost strategy will require a couple of extra variables.

| Name | Description |
| -------------- | ---------------------------------------------------------- |
| MYSQL_USERNAME | Username of the user who will perform the restore or dump. |
| MYSQL_PASSWORD | Password of the user who will perform the restore or dump. |
| MYSQL_HOST | IP or domain of the host machine. |
| MYSQL_DATABASE | Database to restore. (only available for restore) |
| Name | Description |
| ------------------------- | -------------------------------------------------------------------------------------- |
| `MYSQL_USERNAME` | Username of the user who will perform the restore or dump. |
| `MYSQL_PASSWORD` | Password of the user who will perform the restore or dump. |
| `MYSQL_HOST` | IP or domain of the host machine. |
| `MYSQL_DATABASE` | Database to backup/restore. |
| `VOLUMERIZE_MYSQL_SOURCE` | Variable name of source where dumps are to be stored (default `VOLUMERIZE_SOURCE`) |

## Example with Docker Compose

Expand Down Expand Up @@ -52,3 +53,9 @@ volumes:
```

Then execute `docker-compose exec volumerize backup` to create a backup of your database and `docker-compose exec volumerize restore` to restore it from your backup.

## Docker Secrets

The following additional variables are supported to be stored in files, the location specified in variables ending with `_FILE`. See [Docker Secrets Documentation](https://docs.docker.com/engine/swarm/secrets/) for more info.

- `MYSQL_PASSWORD`
34 changes: 34 additions & 0 deletions prepost_strategies/mysql/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
version: "3"

services:
mariadb:
image: mariadb
ports:
- 3306:3306
environment:
- MYSQL_ROOT_PASSWORD=1234
- MYSQL_DATABASE=somedatabase
volumes:
- mariadb:/var/lib/mysql

volumerize:
image: fekide/volumerize:mysql
environment:
- VOLUMERIZE_SOURCE1=/source
- VOLUMERIZE_TARGET1=file:///backup
- MYSQL_USERNAME=root
- MYSQL_PASSWORD=1234
- MYSQL_HOST=mariadb
- MYSQL_DATABASE=somedatabase
- VOLUMERIZE_MYSQL_SOURCE=VOLUMERIZE_SOURCE1
- DEBUG=true
volumes:
- volumerize-cache:/volumerize-cache
- backup:/backup
depends_on:
- mariadb

volumes:
volumerize-cache:
mariadb:
backup:
12 changes: 10 additions & 2 deletions prepost_strategies/mysql/postexecute/restore/mysqlimport.sh
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
source /preexecute/utils/check-env.sh
#!/bin/bash

set -o errexit

source /opt/volumerize/env.sh

VOLUMERIZE_MYSQL_SOURCE=${VOLUMERIZE_MYSQL_SOURCE:-VOLUMERIZE_SOURCE}
export MYSQL_SOURCE=${!VOLUMERIZE_MYSQL_SOURCE}

file_env "MYSQL_PASSWORD"
check_env "mysqlimport" "MYSQL_PASSWORD" "MYSQL_USERNAME" "MYSQL_HOST" "MYSQL_DATABASE"

echo "mysql import starts"
pv ${VOLUMERIZE_SOURCE}/volumerize-mysql/dump-${MYSQL_DATABASE}.sql | mysql -u ${MYSQL_USERNAME} -p${MYSQL_PASSWORD} $MYSQL_DATABASE
pv ${MYSQL_SOURCE}/volumerize-mysql/dump-${MYSQL_DATABASE}.sql | mysql -u ${MYSQL_USERNAME} -p${MYSQL_PASSWORD} $MYSQL_DATABASE
echo "Import done"
31 changes: 18 additions & 13 deletions prepost_strategies/mysql/preexecute/backup/mysqldump.sh
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
source /preexecute/utils/check-env.sh
#!/bin/bash

check_env "Mysqldump" "MYSQL_PASSWORD" "MYSQL_USERNAME" "MYSQL_HOST"
set -o errexit

echo "Creating $VOLUMERIZE_SOURCE folder if not exists"
mkdir -p $VOLUMERIZE_SOURCE/volumerize-mysql/
source /opt/volumerize/env.sh

log "Starting automatic repair and optimize for all databases..."
mysqlcheck -h ${MYSQL_HOST} -u${MYSQL_USERNAME} -p${MYSQL_PASSWORD} --all-databases --optimize --auto-repair --silent 2>&1
VOLUMERIZE_MYSQL_SOURCE=${VOLUMERIZE_MYSQL_SOURCE:-VOLUMERIZE_SOURCE}
export MYSQL_SOURCE=${!VOLUMERIZE_MYSQL_SOURCE}

file_env "MYSQL_PASSWORD"
check_env "Mysqldump" "MYSQL_PASSWORD" "MYSQL_USERNAME" "MYSQL_HOST" "MYSQL_SOURCE" "MYSQL_DATABASE"

for MYSQL_DATABASE in `mysql -h ${MYSQL_HOST} -u${MYSQL_USERNAME} -p${MYSQL_PASSWORD} -Bse 'show databases'`; do
echo "Creating ${MYSQL_SOURCE}/volumerize-mysql folder if not exists"
mkdir -p ${MYSQL_SOURCE}/volumerize-mysql

echo "Starting automatic repair and optimize for all databases..."
mysqlcheck -h ${MYSQL_HOST} -u${MYSQL_USERNAME} -p${MYSQL_PASSWORD} --all-databases --optimize --auto-repair --silent 2>&1

# Based on this answer https://stackoverflow.com/a/32361604
SIZE_BYTES=$(mysql --skip-column-names -u ${MYSQL_USERNAME} -p${MYSQL_PASSWORD} ${MYSQL_DATABASE} -e "SELECT ROUND(SUM(data_length * 0.8), 0) FROM information_schema.TABLES WHERE table_schema='${MYSQL_DATABASE}';")
# Based on this answer https://stackoverflow.com/a/32361604
SIZE_BYTES=$(mysql --skip-column-names -u ${MYSQL_USERNAME} -p${MYSQL_PASSWORD} ${MYSQL_DATABASE} -e "SELECT ROUND(SUM(data_length * 0.8), 0) FROM information_schema.TABLES WHERE table_schema='${MYSQL_DATABASE}';")
[[ ${SIZE_BYTES} == NULL ]] && SIZE_BYTES=0

echo "mysqldump starts (Progress is aproximated)"
mysqldump --databases "${MYSQL_DATABASE}" --single-transaction --add-drop-database --user="${MYSQL_USERNAME}" --password="${MYSQL_PASSWORD}" --host="${MYSQL_HOST}" | pv --progress --size "$SIZE_BYTES" > ${VOLUMERIZE_SOURCE}/volumerize-mysql/dump-${MYSQL_DATABASE}.sql

done
echo "mysqldump starts for database ${MYSQL_DATABASE} (Progress is aproximated)"
mysqldump --single-transaction --add-drop-database --user="${MYSQL_USERNAME}" --password="${MYSQL_PASSWORD}" --host="${MYSQL_HOST}" --databases "${MYSQL_DATABASE}" | pv --progress --size "${SIZE_BYTES:-0}" > ${MYSQL_SOURCE}/volumerize-mysql/dump-${MYSQL_DATABASE}.sql
43 changes: 0 additions & 43 deletions prepost_strategies/mysql/preexecute/utils/check-env.sh

This file was deleted.

Loading

0 comments on commit edc1fa6

Please sign in to comment.