From bcc8f68f723070a10ead5e67a62df0d6ea6ce0e9 Mon Sep 17 00:00:00 2001 From: Manuel Date: Thu, 8 Nov 2018 11:15:00 +0100 Subject: [PATCH 1/3] Create a link to the latest backup The symlink is not considered a backup itself and never deleted according to the backup quota --- backup.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/backup.sh b/backup.sh index 4278fcd..2d7fcdd 100755 --- a/backup.sh +++ b/backup.sh @@ -11,9 +11,12 @@ do then echo "Dumping database: $db" FILENAME=/backup/$DATE.$db.sql + LATEST=/backup/latest.$db.sql.gz if mysqldump -h "$MYSQL_HOST" -P "$MYSQL_PORT" -u "$MYSQL_USER" -p"$MYSQL_PASS" --databases "$db" $MYSQLDUMP_OPTS > "$FILENAME" then gzip -f "$FILENAME" + rm "$LATEST" + ln -s "$FILENAME" "$LATEST" else rm -rf "$FILENAME" fi @@ -22,9 +25,9 @@ done if [ -n "$MAX_BACKUPS" ] then - while [ "$(find /backup -maxdepth 1 -name "*.sql.gz" | wc -l)" -gt "$MAX_BACKUPS" ] + while [ "$(find /backup -maxdepth 1 -name "*.sql.gz" -type f | wc -l)" -gt "$MAX_BACKUPS" ] do - TARGET=$(find /backup -maxdepth 1 -name "*.sql.gz" | sort | head -n 1) + TARGET=$(find /backup -maxdepth 1 -name "*.sql.gz" -type f | sort | head -n 1) echo "Backup $TARGET is deleted" rm -rf "$TARGET" done From f6e189e931e6a74b09614c46baf299889b6c8d32 Mon Sep 17 00:00:00 2001 From: Manuel Date: Thu, 8 Nov 2018 11:28:04 +0100 Subject: [PATCH 2/3] Aesthetics improvements and docker-compose example --- README.md | 80 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 1a649b5..f95276f 100644 --- a/README.md +++ b/README.md @@ -6,32 +6,76 @@ This docker image runs mysqldump to backup your databases periodically using cro ## Usage: - docker container run -d \ - --env MYSQL_USER=root \ - --env MYSQL_PASS=my_password \ - --link mysql - --volume /path/to/my/backup/folder:/backup - fradelg/mysql-cron-backup +```bash +docker container run -d \ + --env MYSQL_USER=root \ + --env MYSQL_PASS=my_password \ + --link mysql + --volume /path/to/my/backup/folder:/backup + fradelg/mysql-cron-backup +``` ## Variables - MYSQL_HOST the host/ip of your mysql database - MYSQL_PORT the port number of your mysql database - MYSQL_USER the username of your mysql database - MYSQL_PASS the password of your mysql database - MYSQL_DB the database name to dump. Default: `--all-databases` - MYSQLDUMP_OPTS command line arguments to pass to mysqldump. Example: `--single-transaction` - CRON_TIME the interval of cron job to run mysqldump. `0 0 * * *` by default, which is every day at 00:00 - MAX_BACKUPS the number of backups to keep. When reaching the limit, the old backup will be discarded. No limit by default - INIT_BACKUP if set, create a backup when the container starts - INIT_RESTORE_LATEST if set, restores latest backup +- `MYSQL_HOST`: The host/ip of your mysql database. +- `MYSQL_PORT`: The port number of your mysql database. +- `MYSQL_USER`: The username of your mysql database. +- `MYSQL_PASS`: The password of your mysql database. +- `MYSQL_DB`: The database name to dump. Default: `--all-databases`. +- `MYSQLDUMP_OPTS`: Command line arguments to pass to mysqldump. Example: `--single-transaction`. +- `CRON_TIME`: The interval of cron job to run mysqldump. `0 3 * * sun` by default, which is every Sunday at 03:00. +- `MAX_BACKUPS`: The number of backups to keep. When reaching the limit, the old backup will be discarded. No limit by default. +- `INIT_BACKUP`: If set, create a backup when the container starts. +- `INIT_RESTORE_LATEST`: Ff set, restores latest backup. + +If you want to make this image the perfect companion of your MySQL container, use [docker-compose](https://docs.docker.com/compose/). You can add more services that will be able to connect to the MySQL image using the name `my_mariadb`, note that you only expose the port `3306` internally to the servers and not to the host: + +```yaml +version: "2" +services: + mariadb: + image: mariadb + container_name: my_mariadb + expose: + - 3306 + volumes: + # If there is not scheme, restore the last created backup (if exists) + - ${VOLUME_PATH}/backup/latest.${DATABASE_NAME}.sql.gz:/docker-entrypoint-initdb.d/database.sql.gz + environment: + - MYSQL_ROOT_PASSWORD=${MARIADB_ROOT_PASSWORD} + - MYSQL_DATABASE=${DATABASE_NAME} + - MYSQL_USER=${WORDPRESS_DB_USER} + - MYSQL_PASSWORD=${WORDPRESS_DB_PASSWORD} + restart: unless-stopped + + mysql-cron-backup: + image: fradelg/mysql-cron-backup + depends_on: + - my_mariadb + volumes: + - ${VOLUME_PATH}/backup:/backup + environment: + - MYSQL_HOST=my_mariadb + - MYSQL_USER=root + - MYSQL_PASS=${MARIADB_ROOT_PASSWORD} + - MAX_BACKUPS=15 + - INIT_BACKUP=0 + # Every day at 03:00 + - CRON_TIME=* 3 * * * + restart: unless-stopped + +``` ## Restore from a backup See the list of backups in your running docker container, just write in your favorite terminal: - docker container exec backup ls /backup +```bash +docker container exec backup ls /backup +``` To restore a database from a certain backup, simply run: - docker container exec backup /restore.sh /backup/201708060500.my_db.sql.gz +```bash +docker container exec backup /restore.sh /backup/201708060500.my_db.sql.gz +``` From 1bd0e144c97318ac697269303511d9f3f4bceb51 Mon Sep 17 00:00:00 2001 From: Manuel Date: Thu, 8 Nov 2018 14:34:29 +0100 Subject: [PATCH 3/3] Ignore error if file does not exist --- backup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backup.sh b/backup.sh index 2d7fcdd..d331f58 100755 --- a/backup.sh +++ b/backup.sh @@ -15,7 +15,7 @@ do if mysqldump -h "$MYSQL_HOST" -P "$MYSQL_PORT" -u "$MYSQL_USER" -p"$MYSQL_PASS" --databases "$db" $MYSQLDUMP_OPTS > "$FILENAME" then gzip -f "$FILENAME" - rm "$LATEST" + rm "$LATEST" 2> /dev/null ln -s "$FILENAME" "$LATEST" else rm -rf "$FILENAME"