From c3ac7942082c097910e1cce4a63ec6e21d34f767 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Tue, 2 Aug 2016 16:34:28 +0700 Subject: [PATCH 01/42] update to xenial --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 29008b0..dee22a2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:trusty +FROM ubuntu:xenial MAINTAINER Tutum Labs RUN apt-get update && \ From e77aa2fd52eff53399df42b2d1c7b8389a957315 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 3 Aug 2016 14:11:50 +0700 Subject: [PATCH 02/42] The last available mysql-client is installed - from official distro - version is fixed - run under user `mysql` - also cron is installed --- Dockerfile | 37 ++++++++++++++++++++++++++++++++++--- run.sh | 4 ++-- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index dee22a2..34da9ff 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,40 @@ FROM ubuntu:xenial MAINTAINER Tutum Labs -RUN apt-get update && \ - apt-get install -y --no-install-recommends mysql-client && \ - mkdir /backup +# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added +RUN mkdir -p /var/lib/mysql/ \ + && groupadd -r mysql \ + && useradd -r -g mysql -d /var/lib/mysql/ mysql \ + && chown mysql:mysql /var/lib/mysql \ + && chmod 700 /var/lib/mysql + +# add gosu for easy step-down from root +ENV GOSU_VERSION 1.7 +RUN set -x \ + && apt-get update && apt-get install -y --no-install-recommends ca-certificates wget && rm -rf /var/lib/apt/lists/* \ + && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture)" \ + && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture).asc" \ + && export GNUPGHOME="$(mktemp -d)" \ + && gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \ + && gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \ + && rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc \ + && chmod +x /usr/local/bin/gosu \ + && gosu nobody true \ + && apt-get purge -y --auto-remove ca-certificates wget + +# gpg: key 5072E1F5: public key "MySQL Release Engineering " imported +RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys A4A9406876FCBD3C456770C88C718D3B5072E1F5 + +ENV MYSQL_MAJOR 5.7 +ENV MYSQL_VERSION 5.7.14-1ubuntu16.04 + +RUN echo "deb http://repo.mysql.com/apt/ubuntu/ xenial mysql-${MYSQL_MAJOR}" > /etc/apt/sources.list.d/mysql.list + +RUN apt-get update \ + && apt-get install -y \ + mysql-client="${MYSQL_VERSION}" \ + cron \ + && rm -rf /var/lib/apt/lists/* ENV CRON_TIME="0 0 * * *" \ MYSQL_DB="--all-databases" diff --git a/run.sh b/run.sh index 1116ef3..1e87111 100755 --- a/run.sh +++ b/run.sh @@ -16,7 +16,7 @@ MYSQL_PASS=${MYSQL_PASS:-${MYSQL_ENV_MYSQL_PASS}} [ -z "${MYSQL_USER}" ] && { echo "=> MYSQL_USER cannot be empty" && exit 1; } [ -z "${MYSQL_PASS}" ] && { echo "=> MYSQL_PASS cannot be empty" && exit 1; } -BACKUP_CMD="mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} > /backup/"'${BACKUP_NAME}' +BACKUP_CMD="exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} > /backup/"'${BACKUP_NAME}' echo "=> Creating backup script" rm -f /backup.sh @@ -51,7 +51,7 @@ rm -f /restore.sh cat <> /restore.sh #!/bin/bash echo "=> Restore database from \$1" -if mysql -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} < \$1 ;then +if exec gosu mysql mysql -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} < \$1 ;then echo " Restore succeeded" else echo " Restore failed" From a2c77f1db76b8764575099dd23e33c247208df55 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 3 Aug 2016 14:29:03 +0700 Subject: [PATCH 03/42] use gzip/gunzip to save disk space --- run.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/run.sh b/run.sh index 1e87111..60a150e 100755 --- a/run.sh +++ b/run.sh @@ -16,22 +16,23 @@ MYSQL_PASS=${MYSQL_PASS:-${MYSQL_ENV_MYSQL_PASS}} [ -z "${MYSQL_USER}" ] && { echo "=> MYSQL_USER cannot be empty" && exit 1; } [ -z "${MYSQL_PASS}" ] && { echo "=> MYSQL_PASS cannot be empty" && exit 1; } -BACKUP_CMD="exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} > /backup/"'${BACKUP_NAME}' - echo "=> Creating backup script" rm -f /backup.sh cat <> /backup.sh #!/bin/bash MAX_BACKUPS=${MAX_BACKUPS} -BACKUP_NAME=\$(date +\%Y.\%m.\%d.\%H\%M\%S).sql +BACKUP_NAME_NOEXT=$(date +\%Y.\%m.\%d.\%H\%M\%S) +BACKUP_NAME=\$(BACKUP_NAME_NOEXT).sql +BACKUP_GZ_NAME=\$(BACKUP_NAME_NOEXT).gz + +BACKUP_CMD="exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} | gzip -c -9 > /backup/${BACKUP_GZ_NAME}" echo "=> Backup started: \${BACKUP_NAME}" if ${BACKUP_CMD} ;then echo " Backup succeeded" else echo " Backup failed" - rm -rf /backup/\${BACKUP_NAME} fi if [ -n "\${MAX_BACKUPS}" ]; then @@ -51,7 +52,7 @@ rm -f /restore.sh cat <> /restore.sh #!/bin/bash echo "=> Restore database from \$1" -if exec gosu mysql mysql -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} < \$1 ;then +if gunzip -c \$1 | exec gosu mysql mysql -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ;then echo " Restore succeeded" else echo " Restore failed" From ac6b0849d154008b5e07296f626d95ccb6bb47a1 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 3 Aug 2016 16:45:13 +0700 Subject: [PATCH 04/42] fix --- run.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/run.sh b/run.sh index 60a150e..0d82d93 100755 --- a/run.sh +++ b/run.sh @@ -23,13 +23,13 @@ cat <> /backup.sh MAX_BACKUPS=${MAX_BACKUPS} BACKUP_NAME_NOEXT=$(date +\%Y.\%m.\%d.\%H\%M\%S) -BACKUP_NAME=\$(BACKUP_NAME_NOEXT).sql -BACKUP_GZ_NAME=\$(BACKUP_NAME_NOEXT).gz +BACKUP_NAME=\${BACKUP_NAME_NOEXT}.sql +BACKUP_GZ_NAME=\${BACKUP_NAME_NOEXT}.gz BACKUP_CMD="exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} | gzip -c -9 > /backup/${BACKUP_GZ_NAME}" echo "=> Backup started: \${BACKUP_NAME}" -if ${BACKUP_CMD} ;then +if ${BACKUP_CMD}; then echo " Backup succeeded" else echo " Backup failed" From da620a46c02e202e7cdc8b1a3c350f0f8068a18a Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 3 Aug 2016 16:50:15 +0700 Subject: [PATCH 05/42] fix --- run.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/run.sh b/run.sh index 0d82d93..1ca2422 100755 --- a/run.sh +++ b/run.sh @@ -26,10 +26,8 @@ BACKUP_NAME_NOEXT=$(date +\%Y.\%m.\%d.\%H\%M\%S) BACKUP_NAME=\${BACKUP_NAME_NOEXT}.sql BACKUP_GZ_NAME=\${BACKUP_NAME_NOEXT}.gz -BACKUP_CMD="exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} | gzip -c -9 > /backup/${BACKUP_GZ_NAME}" - echo "=> Backup started: \${BACKUP_NAME}" -if ${BACKUP_CMD}; then +if exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} | gzip -c -9 > /backup/${BACKUP_GZ_NAME}; then echo " Backup succeeded" else echo " Backup failed" From 19b676009d93744a5a2c217651c496decc191213 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 3 Aug 2016 17:03:06 +0700 Subject: [PATCH 06/42] fix --- run.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/run.sh b/run.sh index 1ca2422..ddf702d 100755 --- a/run.sh +++ b/run.sh @@ -26,8 +26,10 @@ BACKUP_NAME_NOEXT=$(date +\%Y.\%m.\%d.\%H\%M\%S) BACKUP_NAME=\${BACKUP_NAME_NOEXT}.sql BACKUP_GZ_NAME=\${BACKUP_NAME_NOEXT}.gz +BACKUP_CMD="exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} | gzip -c -9 > /backup/"'${BACKUP_GZ_NAME}' + echo "=> Backup started: \${BACKUP_NAME}" -if exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} | gzip -c -9 > /backup/${BACKUP_GZ_NAME}; then +if ${BACKUP_CMD}; then echo " Backup succeeded" else echo " Backup failed" From 9a7b6cc02718406a0daf5c10c08fee681b1e0a3d Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 3 Aug 2016 17:11:59 +0700 Subject: [PATCH 07/42] fix --- run.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/run.sh b/run.sh index ddf702d..d9f11a7 100755 --- a/run.sh +++ b/run.sh @@ -22,14 +22,14 @@ cat <> /backup.sh #!/bin/bash MAX_BACKUPS=${MAX_BACKUPS} -BACKUP_NAME_NOEXT=$(date +\%Y.\%m.\%d.\%H\%M\%S) +BACKUP_CMD="exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} | gzip -c -9 > /backup/"'${BACKUP_GZ_NAME}' + +BACKUP_NAME_NOEXT=\$(date +\%Y.\%m.\%d.\%H\%M\%S) BACKUP_NAME=\${BACKUP_NAME_NOEXT}.sql BACKUP_GZ_NAME=\${BACKUP_NAME_NOEXT}.gz -BACKUP_CMD="exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} | gzip -c -9 > /backup/"'${BACKUP_GZ_NAME}' - echo "=> Backup started: \${BACKUP_NAME}" -if ${BACKUP_CMD}; then +if ${BACKUP_CMD} ;then echo " Backup succeeded" else echo " Backup failed" From 85cf55e3e9c8a587b10287eeae30aa7dc202762a Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 3 Aug 2016 17:16:31 +0700 Subject: [PATCH 08/42] fix --- run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run.sh b/run.sh index d9f11a7..7c26d3e 100755 --- a/run.sh +++ b/run.sh @@ -22,7 +22,7 @@ cat <> /backup.sh #!/bin/bash MAX_BACKUPS=${MAX_BACKUPS} -BACKUP_CMD="exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} | gzip -c -9 > /backup/"'${BACKUP_GZ_NAME}' +BACKUP_CMD="exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} | gzip -c -9 > /backup/\${BACKUP_GZ_NAME}" BACKUP_NAME_NOEXT=\$(date +\%Y.\%m.\%d.\%H\%M\%S) BACKUP_NAME=\${BACKUP_NAME_NOEXT}.sql From 9f150395c16e192d214c25dbc05c1c9f2d785011 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 3 Aug 2016 17:20:49 +0700 Subject: [PATCH 09/42] fix --- run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run.sh b/run.sh index 7c26d3e..a62879e 100755 --- a/run.sh +++ b/run.sh @@ -29,7 +29,7 @@ BACKUP_NAME=\${BACKUP_NAME_NOEXT}.sql BACKUP_GZ_NAME=\${BACKUP_NAME_NOEXT}.gz echo "=> Backup started: \${BACKUP_NAME}" -if ${BACKUP_CMD} ;then +if exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} | gzip -c -9 > /backup/\${BACKUP_GZ_NAME} ;then echo " Backup succeeded" else echo " Backup failed" From 9e9f0dcfab69b566e707ed27caf430c2b29b63b0 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 3 Aug 2016 17:24:57 +0700 Subject: [PATCH 10/42] cleanup --- run.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/run.sh b/run.sh index a62879e..95260aa 100755 --- a/run.sh +++ b/run.sh @@ -22,8 +22,6 @@ cat <> /backup.sh #!/bin/bash MAX_BACKUPS=${MAX_BACKUPS} -BACKUP_CMD="exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} | gzip -c -9 > /backup/\${BACKUP_GZ_NAME}" - BACKUP_NAME_NOEXT=\$(date +\%Y.\%m.\%d.\%H\%M\%S) BACKUP_NAME=\${BACKUP_NAME_NOEXT}.sql BACKUP_GZ_NAME=\${BACKUP_NAME_NOEXT}.gz From 3de4a1834aa7ad33ad2b4c4577afbcf2dda0d0b5 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Tue, 9 Aug 2016 12:56:10 +0700 Subject: [PATCH 11/42] timezone support --- Dockerfile | 3 +++ run.sh | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Dockerfile b/Dockerfile index 34da9ff..e3f6db7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -36,6 +36,9 @@ RUN apt-get update \ cron \ && rm -rf /var/lib/apt/lists/* +# timezone +ENV TIMEZONE="Etc/UTC" + ENV CRON_TIME="0 0 * * *" \ MYSQL_DB="--all-databases" ADD run.sh /run.sh diff --git a/run.sh b/run.sh index 95260aa..21a2fca 100755 --- a/run.sh +++ b/run.sh @@ -16,6 +16,9 @@ MYSQL_PASS=${MYSQL_PASS:-${MYSQL_ENV_MYSQL_PASS}} [ -z "${MYSQL_USER}" ] && { echo "=> MYSQL_USER cannot be empty" && exit 1; } [ -z "${MYSQL_PASS}" ] && { echo "=> MYSQL_PASS cannot be empty" && exit 1; } +echo ${TIMEZONE} > /etc/timezone +ln -sf /usr/share/zoneinfo/${TIMEZONE} /etc/localtime + echo "=> Creating backup script" rm -f /backup.sh cat <> /backup.sh From 966592dcef83381e7adbf88ec59641570ed32868 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Tue, 9 Aug 2016 15:50:25 +0700 Subject: [PATCH 12/42] duplicity + sftp support --- Dockerfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Dockerfile b/Dockerfile index e3f6db7..8c02c18 100644 --- a/Dockerfile +++ b/Dockerfile @@ -34,6 +34,10 @@ RUN apt-get update \ && apt-get install -y \ mysql-client="${MYSQL_VERSION}" \ cron \ + openssh-client \ + python-paramiko \ + duplicity \ + python \ && rm -rf /var/lib/apt/lists/* # timezone From c4faca0b9ce3ab922781eaa74ab9ac9920d96df1 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Tue, 9 Aug 2016 16:16:35 +0700 Subject: [PATCH 13/42] duplicity support These evironment variables are used to turn on and tune duplicity to work on sftp: SFTP_USER SFTP_HOST SFTP_DIR --- run.sh | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/run.sh b/run.sh index 21a2fca..00dce33 100755 --- a/run.sh +++ b/run.sh @@ -26,14 +26,24 @@ cat <> /backup.sh MAX_BACKUPS=${MAX_BACKUPS} BACKUP_NAME_NOEXT=\$(date +\%Y.\%m.\%d.\%H\%M\%S) -BACKUP_NAME=\${BACKUP_NAME_NOEXT}.sql BACKUP_GZ_NAME=\${BACKUP_NAME_NOEXT}.gz -echo "=> Backup started: \${BACKUP_NAME}" -if exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} | gzip -c -9 > /backup/\${BACKUP_GZ_NAME} ;then - echo " Backup succeeded" +if [[ ! -z ${SFTP_USER} && ! -z ${SFTP_HOST} && ! -z ${SFTP_DIR} ]]; then + echo "=> Backup started: ${MYSQL_DB}.sql" + + if exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} > /backup/${MYSQL_DB}.sql && duplicity --ssh-options="-oProtocol=2 -oIdentityFile=’/root/.ssh/id_rsa’" /backup sftp://\${SFTP_USER}@\${SFTP_HOST}/\${SFTP_DIR} ;then + echo " Backup succeeded" + else + echo " Backup failed" + fi else - echo " Backup failed" + echo "=> Backup started: \${BACKUP_GZ_NAME}" + + if exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} | gzip -c -9 > /backup/\${BACKUP_GZ_NAME} ;then + echo " Backup succeeded" + else + echo " Backup failed" + fi fi if [ -n "\${MAX_BACKUPS}" ]; then From 223bd81880cc077756764a699923ae6c40410827 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Tue, 9 Aug 2016 16:31:04 +0700 Subject: [PATCH 14/42] DUPLICITY_EXTRA_OPTS support --- run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run.sh b/run.sh index 00dce33..589a498 100755 --- a/run.sh +++ b/run.sh @@ -31,7 +31,7 @@ BACKUP_GZ_NAME=\${BACKUP_NAME_NOEXT}.gz if [[ ! -z ${SFTP_USER} && ! -z ${SFTP_HOST} && ! -z ${SFTP_DIR} ]]; then echo "=> Backup started: ${MYSQL_DB}.sql" - if exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} > /backup/${MYSQL_DB}.sql && duplicity --ssh-options="-oProtocol=2 -oIdentityFile=’/root/.ssh/id_rsa’" /backup sftp://\${SFTP_USER}@\${SFTP_HOST}/\${SFTP_DIR} ;then + if exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} > /backup/${MYSQL_DB}.sql && duplicity --ssh-options="-oProtocol=2 -oIdentityFile=’/root/.ssh/id_rsa’" ${DUPLICITY_EXTRA_OPTS} /backup sftp://\${SFTP_USER}@\${SFTP_HOST}/\${SFTP_DIR} ;then echo " Backup succeeded" else echo " Backup failed" From 10843f6b0e722c5c7428c453979232470a14bcca Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Tue, 9 Aug 2016 17:40:39 +0700 Subject: [PATCH 15/42] SFTP_PORT support --- run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run.sh b/run.sh index 589a498..4be72e7 100755 --- a/run.sh +++ b/run.sh @@ -31,7 +31,7 @@ BACKUP_GZ_NAME=\${BACKUP_NAME_NOEXT}.gz if [[ ! -z ${SFTP_USER} && ! -z ${SFTP_HOST} && ! -z ${SFTP_DIR} ]]; then echo "=> Backup started: ${MYSQL_DB}.sql" - if exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} > /backup/${MYSQL_DB}.sql && duplicity --ssh-options="-oProtocol=2 -oIdentityFile=’/root/.ssh/id_rsa’" ${DUPLICITY_EXTRA_OPTS} /backup sftp://\${SFTP_USER}@\${SFTP_HOST}/\${SFTP_DIR} ;then + if exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} > /backup/${MYSQL_DB}.sql && duplicity --ssh-options="-oProtocol=2 -oIdentityFile=’/root/.ssh/id_rsa’" ${DUPLICITY_EXTRA_OPTS} /backup sftp://\${SFTP_USER}@\${SFTP_HOST}:${SFTP_PORT}/\${SFTP_DIR} ;then echo " Backup succeeded" else echo " Backup failed" From 59cd8f1304f44bcf244840ff681232e5600525c3 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Tue, 9 Aug 2016 18:06:13 +0700 Subject: [PATCH 16/42] DUPLICITY_ENCRYPT_PASSPHRASE support The passphrase used to encrypt data --- run.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/run.sh b/run.sh index 4be72e7..2896b35 100755 --- a/run.sh +++ b/run.sh @@ -23,15 +23,19 @@ echo "=> Creating backup script" rm -f /backup.sh cat <> /backup.sh #!/bin/bash + +# Setting the pass phrase to encrypt the backup files. +export PASSPHRASE=\$DUPLICITY_ENCRYPT_PASSPHRASE + MAX_BACKUPS=${MAX_BACKUPS} BACKUP_NAME_NOEXT=\$(date +\%Y.\%m.\%d.\%H\%M\%S) BACKUP_GZ_NAME=\${BACKUP_NAME_NOEXT}.gz -if [[ ! -z ${SFTP_USER} && ! -z ${SFTP_HOST} && ! -z ${SFTP_DIR} ]]; then +if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then echo "=> Backup started: ${MYSQL_DB}.sql" - if exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} > /backup/${MYSQL_DB}.sql && duplicity --ssh-options="-oProtocol=2 -oIdentityFile=’/root/.ssh/id_rsa’" ${DUPLICITY_EXTRA_OPTS} /backup sftp://\${SFTP_USER}@\${SFTP_HOST}:${SFTP_PORT}/\${SFTP_DIR} ;then + if exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} > /backup/${MYSQL_DB}.sql && duplicity --ssh-options="-oProtocol=2 -oIdentityFile=’/root/.ssh/id_rsa’" ${DUPLICITY_EXTRA_OPTS} /backup sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} ;then echo " Backup succeeded" else echo " Backup failed" From 96482875f273656be83f7fedd226f1744bedbd15 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 10 Aug 2016 13:22:10 +0700 Subject: [PATCH 17/42] fix --- run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run.sh b/run.sh index 2896b35..b79b7a1 100755 --- a/run.sh +++ b/run.sh @@ -35,7 +35,7 @@ BACKUP_GZ_NAME=\${BACKUP_NAME_NOEXT}.gz if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then echo "=> Backup started: ${MYSQL_DB}.sql" - if exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} > /backup/${MYSQL_DB}.sql && duplicity --ssh-options="-oProtocol=2 -oIdentityFile=’/root/.ssh/id_rsa’" ${DUPLICITY_EXTRA_OPTS} /backup sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} ;then + if /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} > /backup/${MYSQL_DB}.sql && duplicity --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" ${DUPLICITY_EXTRA_OPTS} /backup sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} ;then echo " Backup succeeded" else echo " Backup failed" From 897aa6cbf49b0591673646aa78ce113e68ed90db Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 10 Aug 2016 14:50:28 +0700 Subject: [PATCH 18/42] fix second run --- run.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/run.sh b/run.sh index b79b7a1..96fb7cc 100755 --- a/run.sh +++ b/run.sh @@ -32,6 +32,10 @@ MAX_BACKUPS=${MAX_BACKUPS} BACKUP_NAME_NOEXT=\$(date +\%Y.\%m.\%d.\%H\%M\%S) BACKUP_GZ_NAME=\${BACKUP_NAME_NOEXT}.gz +SFTP_USER=${SFTP_USER} +SFTP_HOST=${SFTP_HOST} +SFTP_DIR=${SFTP_DIR} + if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then echo "=> Backup started: ${MYSQL_DB}.sql" From 504ec554e4435c755e0d2ad725d52fb0a58352ec Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 10 Aug 2016 14:56:36 +0700 Subject: [PATCH 19/42] MAX_BACKUPS applyed only if SFTP is not used --- run.sh | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/run.sh b/run.sh index 96fb7cc..fb63ac6 100755 --- a/run.sh +++ b/run.sh @@ -52,16 +52,17 @@ else else echo " Backup failed" fi -fi -if [ -n "\${MAX_BACKUPS}" ]; then - while [ \$(ls /backup -N1 | wc -l) -gt \${MAX_BACKUPS} ]; - do - BACKUP_TO_BE_DELETED=\$(ls /backup -N1 | sort | head -n 1) - echo " Backup \${BACKUP_TO_BE_DELETED} is deleted" - rm -rf /backup/\${BACKUP_TO_BE_DELETED} - done + if [ -n "\${MAX_BACKUPS}" ]; then + while [ \$(ls /backup -N1 | wc -l) -gt \${MAX_BACKUPS} ]; + do + BACKUP_TO_BE_DELETED=\$(ls /backup -N1 | sort | head -n 1) + echo " Backup \${BACKUP_TO_BE_DELETED} is deleted" + rm -rf /backup/\${BACKUP_TO_BE_DELETED} + done + fi fi + echo "=> Backup done" EOF chmod +x /backup.sh @@ -72,9 +73,9 @@ cat <> /restore.sh #!/bin/bash echo "=> Restore database from \$1" if gunzip -c \$1 | exec gosu mysql mysql -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ;then - echo " Restore succeeded" + echo " Restore succeeded" else - echo " Restore failed" + echo " Restore failed" fi echo "=> Done" EOF From 16fecde121a5c2133ed28a7e3a956e2c7ec91e71 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 10 Aug 2016 15:11:54 +0700 Subject: [PATCH 20/42] fix --- run.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/run.sh b/run.sh index fb63ac6..0431450 100755 --- a/run.sh +++ b/run.sh @@ -34,6 +34,7 @@ BACKUP_GZ_NAME=\${BACKUP_NAME_NOEXT}.gz SFTP_USER=${SFTP_USER} SFTP_HOST=${SFTP_HOST} +SFTP_PORT=${SFTP_PORT} SFTP_DIR=${SFTP_DIR} if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then From d729ffe22270f5109adb96e00d8fc24d53f1ebcc Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 10 Aug 2016 15:34:43 +0700 Subject: [PATCH 21/42] fix --- run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run.sh b/run.sh index 0431450..8698c11 100755 --- a/run.sh +++ b/run.sh @@ -25,7 +25,7 @@ cat <> /backup.sh #!/bin/bash # Setting the pass phrase to encrypt the backup files. -export PASSPHRASE=\$DUPLICITY_ENCRYPT_PASSPHRASE +export PASSPHRASE=$DUPLICITY_ENCRYPT_PASSPHRASE MAX_BACKUPS=${MAX_BACKUPS} From 312879450fbb06450b0a561b47784d23c8f6eb6b Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 10 Aug 2016 16:03:45 +0700 Subject: [PATCH 22/42] first restore draft --- run.sh | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/run.sh b/run.sh index 8698c11..c1a7ab9 100755 --- a/run.sh +++ b/run.sh @@ -72,11 +72,19 @@ echo "=> Creating restore script" rm -f /restore.sh cat <> /restore.sh #!/bin/bash -echo "=> Restore database from \$1" -if gunzip -c \$1 | exec gosu mysql mysql -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ;then - echo " Restore succeeded" +if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then + if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1}D --file-to-restore ${MYSQL_DB}.sql sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/${MYSQL_DB}-\${1}D.sql && gosu mysql mysql -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} < /restore/${MYSQL_DB}-\${1}D.sql ;then + echo " Restore succeeded" + else + echo " Restore failed" + fi else - echo " Restore failed" + echo "=> Restore database from \$1" + if gunzip -c \$1 | exec gosu mysql mysql -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ;then + echo " Restore succeeded" + else + echo " Restore failed" + fi fi echo "=> Done" EOF From 6d7e28580bfefb970bb6872df8da79770bad4ca0 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 10 Aug 2016 16:07:57 +0700 Subject: [PATCH 23/42] specify any time value, no only in days --- run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run.sh b/run.sh index c1a7ab9..f840a7f 100755 --- a/run.sh +++ b/run.sh @@ -73,7 +73,7 @@ rm -f /restore.sh cat <> /restore.sh #!/bin/bash if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then - if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1}D --file-to-restore ${MYSQL_DB}.sql sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/${MYSQL_DB}-\${1}D.sql && gosu mysql mysql -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} < /restore/${MYSQL_DB}-\${1}D.sql ;then + if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1} --file-to-restore ${MYSQL_DB}.sql sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/${MYSQL_DB}-\${1}D.sql && gosu mysql mysql -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} < /restore/${MYSQL_DB}-\${1}.sql ;then echo " Restore succeeded" else echo " Restore failed" From 46468955046f0fe318e91a47951d7a511c4b5150 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 10 Aug 2016 16:17:37 +0700 Subject: [PATCH 24/42] DUPLICITY_ENCRYPT_PASSPHRASE for restore script --- run.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/run.sh b/run.sh index f840a7f..4f6db49 100755 --- a/run.sh +++ b/run.sh @@ -72,6 +72,10 @@ echo "=> Creating restore script" rm -f /restore.sh cat <> /restore.sh #!/bin/bash + +# Setting the pass phrase to encrypt the backup files. +export PASSPHRASE=$DUPLICITY_ENCRYPT_PASSPHRASE + if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1} --file-to-restore ${MYSQL_DB}.sql sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/${MYSQL_DB}-\${1}D.sql && gosu mysql mysql -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} < /restore/${MYSQL_DB}-\${1}.sql ;then echo " Restore succeeded" From 358d7dcbe6ff7d40864274f6fd003ab435417594 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 10 Aug 2016 16:26:00 +0700 Subject: [PATCH 25/42] specify any time value, no only in days --- run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run.sh b/run.sh index 4f6db49..6abf321 100755 --- a/run.sh +++ b/run.sh @@ -77,7 +77,7 @@ cat <> /restore.sh export PASSPHRASE=$DUPLICITY_ENCRYPT_PASSPHRASE if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then - if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1} --file-to-restore ${MYSQL_DB}.sql sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/${MYSQL_DB}-\${1}D.sql && gosu mysql mysql -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} < /restore/${MYSQL_DB}-\${1}.sql ;then + if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1} --file-to-restore ${MYSQL_DB}.sql sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/${MYSQL_DB}-\${1}.sql && gosu mysql mysql -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} < /restore/${MYSQL_DB}-\${1}.sql ;then echo " Restore succeeded" else echo " Restore failed" From 31efcdf5ea15ef025b959709408062238ace5957 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 10 Aug 2016 16:30:46 +0700 Subject: [PATCH 26/42] restore-file-only.sh added --- run.sh | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/run.sh b/run.sh index 6abf321..c04202e 100755 --- a/run.sh +++ b/run.sh @@ -94,6 +94,31 @@ echo "=> Done" EOF chmod +x /restore.sh +rm -f /restore-file-only.sh +cat <> /restore-file-only.sh +#!/bin/bash + +# Setting the pass phrase to encrypt the backup files. +export PASSPHRASE=$DUPLICITY_ENCRYPT_PASSPHRASE + +if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then + if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1} --file-to-restore ${MYSQL_DB}.sql sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/${MYSQL_DB}-\${1}.sql ;then + echo " Restore succeeded" + else + echo " Restore failed" + fi +else + echo "=> Restore database from \$1" + if gunzip -c \$1 > /restore/\${1}.sql ;then + echo " Restore succeeded" + else + echo " Restore failed" + fi +fi +echo "=> Done" +EOF +chmod +x /restore-file-only.sh + touch /mysql_backup.log tail -F /mysql_backup.log & From 9291f6723275a1ef25f2316d748d91097f1b8f83 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 10 Aug 2016 17:24:07 +0700 Subject: [PATCH 27/42] docs --- README.md | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bf9e75f..b5534a4 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ This image runs mysqldump to backup data using cronjob to folder `/backup` --env MYSQL_PORT=27017 \ --env MYSQL_USER=admin \ --env MYSQL_PASS=password \ - --volume host.folder:/backup + --volume host.folder:/backup \ tutum/mysql-backup Moreover, if you link `tutum/mysql-backup` to a mysql container(e.g. `tutum/mysql`) with an alias named mysql, this image will try to auto load the `host`, `port`, `user`, `pass` if possible. @@ -19,6 +19,7 @@ Moreover, if you link `tutum/mysql-backup` to a mysql container(e.g. `tutum/mysq ## Parameters + TIMEZONE e.g. Europe/Moscow 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 @@ -30,6 +31,64 @@ Moreover, if you link `tutum/mysql-backup` to a mysql container(e.g. `tutum/mysq INIT_BACKUP if set, create a backup when the container starts INIT_RESTORE_LATEST if set, restores latest backup +## Duplicity over sftp parameters + + SFTP_USER user to connect over sftp + SFTP_HOST host to connect to by sftp + SFTP_PORT port to connect to by sftp + SFTP_DIR remote directory to place files over sftp + DUPLICITY_EXTRA_OPTS usefull value: --full-if-older-than 1M --allow-source-mismatch + DUPLICITY_ENCRYPT_PASSPHRASE the encryption passphrase. keep it in a secret + +## Usage with duplicity over sftp + + docker run -d \ + --env MYSQL_HOST=mysql.host \ + --env MYSQL_PORT=27017 \ + --env MYSQL_USER=admin \ + --env MYSQL_PASS=password \ + --env MYSQL_DB=mydatabase \ + --env EXTRA_OPTS=--skip-lock-tables --single-transaction --flush-logs --hex-blob --master-data=2 \ + --env CRON_TIME=0 6 * * * \ + --env INIT_BACKUP=1 \ + --env MAX_BACKUPS=30 \ + --env TIMEZONE=Europe/Moscow \ + --env SFTP_USER=username \ + --env SFTP_HOST=12.34.56.78 \ + --env SFTP_PORT=22 \ + --env SFTP_DIR=backup/ \ + --env DUPLICITY_EXTRA_OPTS=--full-if-older-than 1M --allow-source-mismatch \ + --env DUPLICITY_ENCRYPT_PASSPHRASE=12345676543212345676543234567654 \ + --volume /backup:/backup \ + --volume /restore:/restore \ + --volume /root/.ssh/id_rsa:/root/.ssh/id_rsa \ + --volume /root/.ssh/id_rsa.pub:/root/.ssh/id_rsa.pub \ + --volume /root/.ssh/known_hosts:/root/.ssh/known_hosts \ + tutum/mysql-backup + +You need to connect to the backup server at least once from your host system in order to have a valid record for it in the known_hosts file. + +On your host machine run this command and press Enter for all questions: + + ssh-keygen + +It would generate `/root/.ssh/id_rsa` and `/root/.ssh/id_rsa.pub` files. + +Then copy this pub key to the backup server. Be sure to allow password access first. + + cd /root/.ssh + ssh-copy-id -p 22 -i id_rsa.pub username@12.34.56.78 + +> Not forget to disallow password authentication on the backup server after pub key copying. + +It would ask for your username's password. if this command complete, try to connect: + + sftp -P 22 username@12.34.56.78 + +If this command succeeds and have not asked you for password, then you can be sure this image would function too. + +Use this [Guide](www.jscape.com/blog/setting-up-sftp-public-key-authentication-caommand-line) if you need more details about sftp configuration. + ## Restore from a backup See the list of backups, you can run: @@ -39,3 +98,20 @@ See the list of backups, you can run: To restore database from a certain backup, simply run: docker exec tutum-backup /restore.sh /backup/2015.08.06.171901 + +## Restore from a backup if using duplicity + +To restore database from a yesterday backup, simply run: + + docker exec tutum-backup /restore.sh 1D + +If you want restore only sql dump file without replacing actual database state, do it with: + + docker exec tutum-backup /restore-file-only.sh 1D + +if you have used same options for backup container startup as in the example above, +after executing it you would find file named /restore/mydatabase-1D.sql restored. + +Instead of 1D you can use 1h for hours, 15m for minutes, 1W for weeks or 1Y for years. +You canb use an exact date in a format like YYYY/MM/DD. See the full list of formats there: +[Duplicity Time Formats](http://duplicity.nongnu.org/duplicity.1.html#sect8) From d199410377f6aefda5ba0db8d3c811e1e17f8483 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 10 Aug 2016 17:27:14 +0700 Subject: [PATCH 28/42] fix --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b5534a4..57f2f96 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Moreover, if you link `tutum/mysql-backup` to a mysql container(e.g. `tutum/mysq ## Parameters - TIMEZONE e.g. Europe/Moscow + TIMEZONE e.g. Europe/Moscow 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 @@ -113,5 +113,5 @@ if you have used same options for backup container startup as in the example abo after executing it you would find file named /restore/mydatabase-1D.sql restored. Instead of 1D you can use 1h for hours, 15m for minutes, 1W for weeks or 1Y for years. -You canb use an exact date in a format like YYYY/MM/DD. See the full list of formats there: +You can use an exact date in a format like YYYY/MM/DD. See the full list of formats there: [Duplicity Time Formats](http://duplicity.nongnu.org/duplicity.1.html#sect8) From b5fe0eb2dadf31c18400287bd1fd79649910bbbd Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Mon, 19 Sep 2016 16:54:17 +0700 Subject: [PATCH 29/42] mysql version up --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 8c02c18..588a6a7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,7 +26,7 @@ RUN set -x \ RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys A4A9406876FCBD3C456770C88C718D3B5072E1F5 ENV MYSQL_MAJOR 5.7 -ENV MYSQL_VERSION 5.7.14-1ubuntu16.04 +ENV MYSQL_VERSION 5.7.15-1ubuntu16.04 RUN echo "deb http://repo.mysql.com/apt/ubuntu/ xenial mysql-${MYSQL_MAJOR}" > /etc/apt/sources.list.d/mysql.list From 8d318fe2305510b79fd7df37f1d7ec30c1e2bfdc Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Fri, 14 Oct 2016 15:28:08 +0700 Subject: [PATCH 30/42] mysql version up 5.7.16 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 588a6a7..30029f3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,7 +26,7 @@ RUN set -x \ RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys A4A9406876FCBD3C456770C88C718D3B5072E1F5 ENV MYSQL_MAJOR 5.7 -ENV MYSQL_VERSION 5.7.15-1ubuntu16.04 +ENV MYSQL_VERSION 5.7.16-1ubuntu16.04 RUN echo "deb http://repo.mysql.com/apt/ubuntu/ xenial mysql-${MYSQL_MAJOR}" > /etc/apt/sources.list.d/mysql.list From 51cdb6b7642bcf06bb0acf1b08a00c0ef0ab64af Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Thu, 24 Nov 2016 17:47:18 +0700 Subject: [PATCH 31/42] fix ssh config and duplicity cache dir 1. sometimes docker replaces mounted file with directory with the same name. mount the /root/.ssh directory to avoid that. 2. duplicity uses /root/.cache/duplicity directory for it's cache. mount it from host to prevent cache re-download after each container re-creation. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 57f2f96..a19edad 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ Moreover, if you link `tutum/mysql-backup` to a mysql container(e.g. `tutum/mysq ## Usage with duplicity over sftp + mkdir -p /root/.cache/duplicity docker run -d \ --env MYSQL_HOST=mysql.host \ --env MYSQL_PORT=27017 \ @@ -61,9 +62,8 @@ Moreover, if you link `tutum/mysql-backup` to a mysql container(e.g. `tutum/mysq --env DUPLICITY_ENCRYPT_PASSPHRASE=12345676543212345676543234567654 \ --volume /backup:/backup \ --volume /restore:/restore \ - --volume /root/.ssh/id_rsa:/root/.ssh/id_rsa \ - --volume /root/.ssh/id_rsa.pub:/root/.ssh/id_rsa.pub \ - --volume /root/.ssh/known_hosts:/root/.ssh/known_hosts \ + --volume /root/.ssh:/root/.ssh \ + --volume /root/.cache/duplicity:/root/.cache/duplicity \ tutum/mysql-backup You need to connect to the backup server at least once from your host system in order to have a valid record for it in the known_hosts file. From a20e5dfe2f0f1c4b09c64a37a3ba24245567df7a Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 21 Dec 2016 12:27:38 +0700 Subject: [PATCH 32/42] Ability to override all environment variables using docker exec tutum-backup /bin/bash -c "export SFTP_DIR=backup/1d && export MYSQL_USER=root && export MYSQL_PASS=123456 && /restore.sh 1D" --- run.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/run.sh b/run.sh index c04202e..a3b6804 100755 --- a/run.sh +++ b/run.sh @@ -38,9 +38,9 @@ SFTP_PORT=${SFTP_PORT} SFTP_DIR=${SFTP_DIR} if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then - echo "=> Backup started: ${MYSQL_DB}.sql" + echo "=> Backup started: \${MYSQL_DB}.sql" - if /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} > /backup/${MYSQL_DB}.sql && duplicity --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" ${DUPLICITY_EXTRA_OPTS} /backup sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} ;then + if /usr/local/bin/gosu mysql mysqldump -h\${MYSQL_HOST} -P\${MYSQL_PORT} -u\${MYSQL_USER} -p\${MYSQL_PASS} \${EXTRA_OPTS} \${MYSQL_DB} > /backup/\${MYSQL_DB}.sql && duplicity --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" \${DUPLICITY_EXTRA_OPTS} /backup sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} ;then echo " Backup succeeded" else echo " Backup failed" @@ -48,7 +48,7 @@ if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then else echo "=> Backup started: \${BACKUP_GZ_NAME}" - if exec /usr/local/bin/gosu mysql mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} | gzip -c -9 > /backup/\${BACKUP_GZ_NAME} ;then + if exec /usr/local/bin/gosu mysql mysqldump -h\${MYSQL_HOST} -P\${MYSQL_PORT} -u\${MYSQL_USER} -p\${MYSQL_PASS} \${EXTRA_OPTS} \${MYSQL_DB} | gzip -c -9 > /backup/\${BACKUP_GZ_NAME} ;then echo " Backup succeeded" else echo " Backup failed" @@ -74,17 +74,17 @@ cat <> /restore.sh #!/bin/bash # Setting the pass phrase to encrypt the backup files. -export PASSPHRASE=$DUPLICITY_ENCRYPT_PASSPHRASE +export PASSPHRASE=\$DUPLICITY_ENCRYPT_PASSPHRASE if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then - if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1} --file-to-restore ${MYSQL_DB}.sql sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/${MYSQL_DB}-\${1}.sql && gosu mysql mysql -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} < /restore/${MYSQL_DB}-\${1}.sql ;then + if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1} --file-to-restore \${MYSQL_DB}.sql sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/\${MYSQL_DB}-\${1}.sql && gosu mysql mysql -h\${MYSQL_HOST} -P\${MYSQL_PORT} -u\${MYSQL_USER} -p\${MYSQL_PASS} < /restore/\${MYSQL_DB}-\${1}.sql ;then echo " Restore succeeded" else echo " Restore failed" fi else echo "=> Restore database from \$1" - if gunzip -c \$1 | exec gosu mysql mysql -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ;then + if gunzip -c \$1 | exec gosu mysql mysql -h\${MYSQL_HOST} -P\${MYSQL_PORT} -u\${MYSQL_USER} -p\${MYSQL_PASS} ;then echo " Restore succeeded" else echo " Restore failed" @@ -99,10 +99,10 @@ cat <> /restore-file-only.sh #!/bin/bash # Setting the pass phrase to encrypt the backup files. -export PASSPHRASE=$DUPLICITY_ENCRYPT_PASSPHRASE +export PASSPHRASE=\$DUPLICITY_ENCRYPT_PASSPHRASE if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then - if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1} --file-to-restore ${MYSQL_DB}.sql sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/${MYSQL_DB}-\${1}.sql ;then + if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1} --file-to-restore \${MYSQL_DB}.sql sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/\${MYSQL_DB}-\${1}.sql ;then echo " Restore succeeded" else echo " Restore failed" From dfc57e7e37afaa99f0196f9fa0c9df749d8f479f Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 21 Dec 2016 13:32:53 +0700 Subject: [PATCH 33/42] fix for previous commit --- run.sh | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/run.sh b/run.sh index a3b6804..34dfef3 100755 --- a/run.sh +++ b/run.sh @@ -37,6 +37,14 @@ SFTP_HOST=${SFTP_HOST} SFTP_PORT=${SFTP_PORT} SFTP_DIR=${SFTP_DIR} +MYSQL_HOST=$(MYSQL_HOST) +MYSQL_PORT=$(MYSQL_PORT) +MYSQL_USER=$(MYSQL_USER) +MYSQL_PASS=$(MYSQL_PASS) +MYSQL_DB=$(MYSQL_DB) +EXTRA_OPTS=$(EXTRA_OPTS) +DUPLICITY_EXTRA_OPTS=$(DUPLICITY_EXTRA_OPTS) + if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then echo "=> Backup started: \${MYSQL_DB}.sql" @@ -76,6 +84,17 @@ cat <> /restore.sh # Setting the pass phrase to encrypt the backup files. export PASSPHRASE=\$DUPLICITY_ENCRYPT_PASSPHRASE +SFTP_USER=${SFTP_USER} +SFTP_HOST=${SFTP_HOST} +SFTP_PORT=${SFTP_PORT} +SFTP_DIR=${SFTP_DIR} + +MYSQL_HOST=$(MYSQL_HOST) +MYSQL_PORT=$(MYSQL_PORT) +MYSQL_USER=$(MYSQL_USER) +MYSQL_PASS=$(MYSQL_PASS) +MYSQL_DB=$(MYSQL_DB) + if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1} --file-to-restore \${MYSQL_DB}.sql sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/\${MYSQL_DB}-\${1}.sql && gosu mysql mysql -h\${MYSQL_HOST} -P\${MYSQL_PORT} -u\${MYSQL_USER} -p\${MYSQL_PASS} < /restore/\${MYSQL_DB}-\${1}.sql ;then echo " Restore succeeded" @@ -101,6 +120,13 @@ cat <> /restore-file-only.sh # Setting the pass phrase to encrypt the backup files. export PASSPHRASE=\$DUPLICITY_ENCRYPT_PASSPHRASE +SFTP_USER=${SFTP_USER} +SFTP_HOST=${SFTP_HOST} +SFTP_PORT=${SFTP_PORT} +SFTP_DIR=${SFTP_DIR} + +MYSQL_DB=$(MYSQL_DB) + if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1} --file-to-restore \${MYSQL_DB}.sql sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/\${MYSQL_DB}-\${1}.sql ;then echo " Restore succeeded" From cdaa4dab1d8823e5af8e71a3e24596b1a5823cf2 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 21 Dec 2016 13:45:55 +0700 Subject: [PATCH 34/42] fix --- run.sh | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/run.sh b/run.sh index 34dfef3..30b107f 100755 --- a/run.sh +++ b/run.sh @@ -37,13 +37,13 @@ SFTP_HOST=${SFTP_HOST} SFTP_PORT=${SFTP_PORT} SFTP_DIR=${SFTP_DIR} -MYSQL_HOST=$(MYSQL_HOST) -MYSQL_PORT=$(MYSQL_PORT) -MYSQL_USER=$(MYSQL_USER) -MYSQL_PASS=$(MYSQL_PASS) -MYSQL_DB=$(MYSQL_DB) -EXTRA_OPTS=$(EXTRA_OPTS) -DUPLICITY_EXTRA_OPTS=$(DUPLICITY_EXTRA_OPTS) +MYSQL_HOST=${MYSQL_HOST} +MYSQL_PORT=${MYSQL_PORT} +MYSQL_USER=${MYSQL_USER} +MYSQL_PASS=${MYSQL_PASS} +MYSQL_DB=${MYSQL_DB} +EXTRA_OPTS=${EXTRA_OPTS} +DUPLICITY_EXTRA_OPTS=${DUPLICITY_EXTRA_OPTS} if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then echo "=> Backup started: \${MYSQL_DB}.sql" @@ -89,11 +89,11 @@ SFTP_HOST=${SFTP_HOST} SFTP_PORT=${SFTP_PORT} SFTP_DIR=${SFTP_DIR} -MYSQL_HOST=$(MYSQL_HOST) -MYSQL_PORT=$(MYSQL_PORT) -MYSQL_USER=$(MYSQL_USER) -MYSQL_PASS=$(MYSQL_PASS) -MYSQL_DB=$(MYSQL_DB) +MYSQL_HOST=${MYSQL_HOST} +MYSQL_PORT=${MYSQL_PORT} +MYSQL_USER=${MYSQL_USER} +MYSQL_PASS=${MYSQL_PASS} +MYSQL_DB=${MYSQL_DB} if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1} --file-to-restore \${MYSQL_DB}.sql sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/\${MYSQL_DB}-\${1}.sql && gosu mysql mysql -h\${MYSQL_HOST} -P\${MYSQL_PORT} -u\${MYSQL_USER} -p\${MYSQL_PASS} < /restore/\${MYSQL_DB}-\${1}.sql ;then @@ -125,7 +125,7 @@ SFTP_HOST=${SFTP_HOST} SFTP_PORT=${SFTP_PORT} SFTP_DIR=${SFTP_DIR} -MYSQL_DB=$(MYSQL_DB) +MYSQL_DB=${MYSQL_DB} if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1} --file-to-restore \${MYSQL_DB}.sql sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/\${MYSQL_DB}-\${1}.sql ;then From 1400b149612abb591c46e58d9f77893edbd0bcbd Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 21 Dec 2016 14:15:23 +0700 Subject: [PATCH 35/42] restore from non-default directory --- README.md | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index a19edad..33bf776 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ This image runs mysqldump to backup data using cronjob to folder `/backup` --env MYSQL_USER=admin \ --env MYSQL_PASS=password \ --volume host.folder:/backup \ + --name tutum-backup \ tutum/mysql-backup Moreover, if you link `tutum/mysql-backup` to a mysql container(e.g. `tutum/mysql`) with an alias named mysql, this image will try to auto load the `host`, `port`, `user`, `pass` if possible. @@ -48,22 +49,23 @@ Moreover, if you link `tutum/mysql-backup` to a mysql container(e.g. `tutum/mysq --env MYSQL_PORT=27017 \ --env MYSQL_USER=admin \ --env MYSQL_PASS=password \ - --env MYSQL_DB=mydatabase \ - --env EXTRA_OPTS=--skip-lock-tables --single-transaction --flush-logs --hex-blob --master-data=2 \ - --env CRON_TIME=0 6 * * * \ - --env INIT_BACKUP=1 \ - --env MAX_BACKUPS=30 \ - --env TIMEZONE=Europe/Moscow \ - --env SFTP_USER=username \ - --env SFTP_HOST=12.34.56.78 \ - --env SFTP_PORT=22 \ - --env SFTP_DIR=backup/ \ - --env DUPLICITY_EXTRA_OPTS=--full-if-older-than 1M --allow-source-mismatch \ - --env DUPLICITY_ENCRYPT_PASSPHRASE=12345676543212345676543234567654 \ + --env MYSQL_DB=mydatabase \ + --env EXTRA_OPTS=--skip-lock-tables --single-transaction --flush-logs --hex-blob --master-data=2 \ + --env CRON_TIME=0 6 * * * \ + --env INIT_BACKUP=1 \ + --env MAX_BACKUPS=30 \ + --env TIMEZONE=Europe/Moscow \ + --env SFTP_USER=username \ + --env SFTP_HOST=12.34.56.78 \ + --env SFTP_PORT=22 \ + --env SFTP_DIR=backup/ \ + --env DUPLICITY_EXTRA_OPTS=--full-if-older-than 1M --allow-source-mismatch \ + --env DUPLICITY_ENCRYPT_PASSPHRASE=12345676543212345676543234567654 \ --volume /backup:/backup \ - --volume /restore:/restore \ - --volume /root/.ssh:/root/.ssh \ - --volume /root/.cache/duplicity:/root/.cache/duplicity \ + --volume /restore:/restore \ + --volume /root/.ssh:/root/.ssh \ + --volume /root/.cache/duplicity:/root/.cache/duplicity \ + --name tutum-backup \ tutum/mysql-backup You need to connect to the backup server at least once from your host system in order to have a valid record for it in the known_hosts file. @@ -94,6 +96,8 @@ Use this [Guide](www.jscape.com/blog/setting-up-sftp-public-key-authentication-c See the list of backups, you can run: docker exec tutum-backup ls /backup + +> Note that `tutum-backup` is a docker container name assigned previously with `--name` option. To restore database from a certain backup, simply run: @@ -115,3 +119,7 @@ after executing it you would find file named /restore/mydatabase-1D.sql restored Instead of 1D you can use 1h for hours, 15m for minutes, 1W for weeks or 1Y for years. You can use an exact date in a format like YYYY/MM/DD. See the full list of formats there: [Duplicity Time Formats](http://duplicity.nongnu.org/duplicity.1.html#sect8) + +If you have used your backup server for backup from several servers, e.g. `master` and `slave`, and defined the environment variable `SFTP_DIR` as `backup/1d` on `master` and to `backup/15m` on `slave`, you can use this comand to restore master backup on a slave: + + docker exec tutum-backup /bin/bash -c "export SFTP_DIR=backup/1d && export MYSQL_USER=root && export MYSQL_PASS=123456 && /restore.sh 1D" From 8a9671c27c7ae355144d04404751ac8eef2521b4 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Wed, 21 Dec 2016 14:22:23 +0700 Subject: [PATCH 36/42] fix for spaces --- run.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/run.sh b/run.sh index 30b107f..8f89276 100755 --- a/run.sh +++ b/run.sh @@ -35,15 +35,15 @@ BACKUP_GZ_NAME=\${BACKUP_NAME_NOEXT}.gz SFTP_USER=${SFTP_USER} SFTP_HOST=${SFTP_HOST} SFTP_PORT=${SFTP_PORT} -SFTP_DIR=${SFTP_DIR} +SFTP_DIR="${SFTP_DIR}" MYSQL_HOST=${MYSQL_HOST} MYSQL_PORT=${MYSQL_PORT} MYSQL_USER=${MYSQL_USER} -MYSQL_PASS=${MYSQL_PASS} +MYSQL_PASS="${MYSQL_PASS}" MYSQL_DB=${MYSQL_DB} -EXTRA_OPTS=${EXTRA_OPTS} -DUPLICITY_EXTRA_OPTS=${DUPLICITY_EXTRA_OPTS} +EXTRA_OPTS="${EXTRA_OPTS}" +DUPLICITY_EXTRA_OPTS="${DUPLICITY_EXTRA_OPTS}" if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then echo "=> Backup started: \${MYSQL_DB}.sql" @@ -87,12 +87,12 @@ export PASSPHRASE=\$DUPLICITY_ENCRYPT_PASSPHRASE SFTP_USER=${SFTP_USER} SFTP_HOST=${SFTP_HOST} SFTP_PORT=${SFTP_PORT} -SFTP_DIR=${SFTP_DIR} +SFTP_DIR="${SFTP_DIR}" MYSQL_HOST=${MYSQL_HOST} MYSQL_PORT=${MYSQL_PORT} MYSQL_USER=${MYSQL_USER} -MYSQL_PASS=${MYSQL_PASS} +MYSQL_PASS="${MYSQL_PASS}" MYSQL_DB=${MYSQL_DB} if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then @@ -123,7 +123,7 @@ export PASSPHRASE=\$DUPLICITY_ENCRYPT_PASSPHRASE SFTP_USER=${SFTP_USER} SFTP_HOST=${SFTP_HOST} SFTP_PORT=${SFTP_PORT} -SFTP_DIR=${SFTP_DIR} +SFTP_DIR="${SFTP_DIR}" MYSQL_DB=${MYSQL_DB} From 9af8c634b040a9b78e93a9b2bf6777e430b8a662 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Fri, 23 Dec 2016 12:32:27 +0700 Subject: [PATCH 37/42] workaround for long incremental backups It seems that paramiko backend is buggy. at least in the 1.16 version ubuntu:xenial has. pexpect+sftp:// scheme is recommended --- run.sh | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/run.sh b/run.sh index 8f89276..b22eda0 100755 --- a/run.sh +++ b/run.sh @@ -48,7 +48,9 @@ DUPLICITY_EXTRA_OPTS="${DUPLICITY_EXTRA_OPTS}" if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then echo "=> Backup started: \${MYSQL_DB}.sql" - if /usr/local/bin/gosu mysql mysqldump -h\${MYSQL_HOST} -P\${MYSQL_PORT} -u\${MYSQL_USER} -p\${MYSQL_PASS} \${EXTRA_OPTS} \${MYSQL_DB} > /backup/\${MYSQL_DB}.sql && duplicity --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" \${DUPLICITY_EXTRA_OPTS} /backup sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} ;then + # using pexpect+sftp because of a bug in paramiko backend. + # @see https://lists.gnu.org/archive/html/duplicity-talk/2016-10/msg00010.html + if /usr/local/bin/gosu mysql mysqldump -h\${MYSQL_HOST} -P\${MYSQL_PORT} -u\${MYSQL_USER} -p\${MYSQL_PASS} \${EXTRA_OPTS} \${MYSQL_DB} > /backup/\${MYSQL_DB}.sql && duplicity --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" \${DUPLICITY_EXTRA_OPTS} /backup pexpect+sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} ;then echo " Backup succeeded" else echo " Backup failed" @@ -96,7 +98,9 @@ MYSQL_PASS="${MYSQL_PASS}" MYSQL_DB=${MYSQL_DB} if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then - if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1} --file-to-restore \${MYSQL_DB}.sql sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/\${MYSQL_DB}-\${1}.sql && gosu mysql mysql -h\${MYSQL_HOST} -P\${MYSQL_PORT} -u\${MYSQL_USER} -p\${MYSQL_PASS} < /restore/\${MYSQL_DB}-\${1}.sql ;then + # using pexpect+sftp because of a bug in paramiko backend. + # @see https://lists.gnu.org/archive/html/duplicity-talk/2016-10/msg00010.html + if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1} --file-to-restore \${MYSQL_DB}.sql pexpect+sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/\${MYSQL_DB}-\${1}.sql && gosu mysql mysql -h\${MYSQL_HOST} -P\${MYSQL_PORT} -u\${MYSQL_USER} -p\${MYSQL_PASS} < /restore/\${MYSQL_DB}-\${1}.sql ;then echo " Restore succeeded" else echo " Restore failed" @@ -128,7 +132,9 @@ SFTP_DIR="${SFTP_DIR}" MYSQL_DB=${MYSQL_DB} if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then - if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1} --file-to-restore \${MYSQL_DB}.sql sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/\${MYSQL_DB}-\${1}.sql ;then + # using pexpect+sftp because of a bug in paramiko backend. + # @see https://lists.gnu.org/archive/html/duplicity-talk/2016-10/msg00010.html + if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1} --file-to-restore \${MYSQL_DB}.sql pexpect+sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/\${MYSQL_DB}-\${1}.sql ;then echo " Restore succeeded" else echo " Restore failed" From 2f2f75e65fd4ec2e386634ea5636608d88f595d6 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Fri, 23 Dec 2016 12:49:36 +0700 Subject: [PATCH 38/42] pexpect+sftp scheme support --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 30029f3..9fc42bc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -36,6 +36,7 @@ RUN apt-get update \ cron \ openssh-client \ python-paramiko \ + python-pexpect \ duplicity \ python \ && rm -rf /var/lib/apt/lists/* From 54572cde850c4320cddc079a7f98e8d5a0f7b597 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Fri, 23 Dec 2016 13:16:49 +0700 Subject: [PATCH 39/42] mysql version up --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 9fc42bc..390445d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,7 +26,7 @@ RUN set -x \ RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys A4A9406876FCBD3C456770C88C718D3B5072E1F5 ENV MYSQL_MAJOR 5.7 -ENV MYSQL_VERSION 5.7.16-1ubuntu16.04 +ENV MYSQL_VERSION 5.7.17-1ubuntu16.04 RUN echo "deb http://repo.mysql.com/apt/ubuntu/ xenial mysql-${MYSQL_MAJOR}" > /etc/apt/sources.list.d/mysql.list From f16a3a950a19c957e8a2deef8264f623f52eddbf Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Mon, 26 Dec 2016 14:02:19 +0700 Subject: [PATCH 40/42] duplicity scheme is made tunable. sftp by default. --- README.md | 1 + run.sh | 11 +++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 33bf776..2dceeda 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ Moreover, if you link `tutum/mysql-backup` to a mysql container(e.g. `tutum/mysq SFTP_DIR remote directory to place files over sftp DUPLICITY_EXTRA_OPTS usefull value: --full-if-older-than 1M --allow-source-mismatch DUPLICITY_ENCRYPT_PASSPHRASE the encryption passphrase. keep it in a secret + DUPLICITY_SCHEME the scheme for duplicity to work with backup server. the default value is sftp. pexpect+sftp is also supported. ## Usage with duplicity over sftp diff --git a/run.sh b/run.sh index b22eda0..1df089a 100755 --- a/run.sh +++ b/run.sh @@ -36,6 +36,8 @@ SFTP_USER=${SFTP_USER} SFTP_HOST=${SFTP_HOST} SFTP_PORT=${SFTP_PORT} SFTP_DIR="${SFTP_DIR}" +DUPLICITY_EXTRA_OPTS="${DUPLICITY_EXTRA_OPTS}" +DUPLICITY_SCHEME="${DUPLICITY_SCHEME:-sftp}" MYSQL_HOST=${MYSQL_HOST} MYSQL_PORT=${MYSQL_PORT} @@ -43,14 +45,13 @@ MYSQL_USER=${MYSQL_USER} MYSQL_PASS="${MYSQL_PASS}" MYSQL_DB=${MYSQL_DB} EXTRA_OPTS="${EXTRA_OPTS}" -DUPLICITY_EXTRA_OPTS="${DUPLICITY_EXTRA_OPTS}" if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then echo "=> Backup started: \${MYSQL_DB}.sql" # using pexpect+sftp because of a bug in paramiko backend. # @see https://lists.gnu.org/archive/html/duplicity-talk/2016-10/msg00010.html - if /usr/local/bin/gosu mysql mysqldump -h\${MYSQL_HOST} -P\${MYSQL_PORT} -u\${MYSQL_USER} -p\${MYSQL_PASS} \${EXTRA_OPTS} \${MYSQL_DB} > /backup/\${MYSQL_DB}.sql && duplicity --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" \${DUPLICITY_EXTRA_OPTS} /backup pexpect+sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} ;then + if /usr/local/bin/gosu mysql mysqldump -h\${MYSQL_HOST} -P\${MYSQL_PORT} -u\${MYSQL_USER} -p\${MYSQL_PASS} \${EXTRA_OPTS} \${MYSQL_DB} > /backup/\${MYSQL_DB}.sql && duplicity --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" \${DUPLICITY_EXTRA_OPTS} /backup \${DUPLICITY_SCHEME}://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} ;then echo " Backup succeeded" else echo " Backup failed" @@ -90,6 +91,7 @@ SFTP_USER=${SFTP_USER} SFTP_HOST=${SFTP_HOST} SFTP_PORT=${SFTP_PORT} SFTP_DIR="${SFTP_DIR}" +DUPLICITY_SCHEME="${DUPLICITY_SCHEME:-sftp}" MYSQL_HOST=${MYSQL_HOST} MYSQL_PORT=${MYSQL_PORT} @@ -100,7 +102,7 @@ MYSQL_DB=${MYSQL_DB} if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then # using pexpect+sftp because of a bug in paramiko backend. # @see https://lists.gnu.org/archive/html/duplicity-talk/2016-10/msg00010.html - if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1} --file-to-restore \${MYSQL_DB}.sql pexpect+sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/\${MYSQL_DB}-\${1}.sql && gosu mysql mysql -h\${MYSQL_HOST} -P\${MYSQL_PORT} -u\${MYSQL_USER} -p\${MYSQL_PASS} < /restore/\${MYSQL_DB}-\${1}.sql ;then + if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1} --file-to-restore \${MYSQL_DB}.sql \${DUPLICITY_SCHEME}://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/\${MYSQL_DB}-\${1}.sql && gosu mysql mysql -h\${MYSQL_HOST} -P\${MYSQL_PORT} -u\${MYSQL_USER} -p\${MYSQL_PASS} < /restore/\${MYSQL_DB}-\${1}.sql ;then echo " Restore succeeded" else echo " Restore failed" @@ -128,13 +130,14 @@ SFTP_USER=${SFTP_USER} SFTP_HOST=${SFTP_HOST} SFTP_PORT=${SFTP_PORT} SFTP_DIR="${SFTP_DIR}" +DUPLICITY_SCHEME="${DUPLICITY_SCHEME:-sftp}" MYSQL_DB=${MYSQL_DB} if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then # using pexpect+sftp because of a bug in paramiko backend. # @see https://lists.gnu.org/archive/html/duplicity-talk/2016-10/msg00010.html - if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1} --file-to-restore \${MYSQL_DB}.sql pexpect+sftp://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/\${MYSQL_DB}-\${1}.sql ;then + if duplicity --allow-source-mismatch --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" -t \${1} --file-to-restore \${MYSQL_DB}.sql ${DUPLICITY_SCHEME}://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} /restore/\${MYSQL_DB}-\${1}.sql ;then echo " Restore succeeded" else echo " Restore failed" From a7b5336887aad8f1e8301e441d4716be47fd81c9 Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Mon, 26 Dec 2016 18:18:40 +0700 Subject: [PATCH 41/42] use flock to prevent dump script runs overlap --- run.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/run.sh b/run.sh index 1df089a..73ac919 100755 --- a/run.sh +++ b/run.sh @@ -51,7 +51,7 @@ if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then # using pexpect+sftp because of a bug in paramiko backend. # @see https://lists.gnu.org/archive/html/duplicity-talk/2016-10/msg00010.html - if /usr/local/bin/gosu mysql mysqldump -h\${MYSQL_HOST} -P\${MYSQL_PORT} -u\${MYSQL_USER} -p\${MYSQL_PASS} \${EXTRA_OPTS} \${MYSQL_DB} > /backup/\${MYSQL_DB}.sql && duplicity --ssh-options="-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa" \${DUPLICITY_EXTRA_OPTS} /backup \${DUPLICITY_SCHEME}://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR} ;then + if flock -x -n /root/.cache/duplicity/backup.lock -c "/usr/local/bin/gosu mysql mysqldump -h\${MYSQL_HOST} -P\${MYSQL_PORT} -u\${MYSQL_USER} -p\${MYSQL_PASS} \${EXTRA_OPTS} \${MYSQL_DB} > /backup/\${MYSQL_DB}.sql && duplicity --ssh-options=\"-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa\" \${DUPLICITY_EXTRA_OPTS} /backup \${DUPLICITY_SCHEME}://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR}" ;then echo " Backup succeeded" else echo " Backup failed" @@ -59,7 +59,7 @@ if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then else echo "=> Backup started: \${BACKUP_GZ_NAME}" - if exec /usr/local/bin/gosu mysql mysqldump -h\${MYSQL_HOST} -P\${MYSQL_PORT} -u\${MYSQL_USER} -p\${MYSQL_PASS} \${EXTRA_OPTS} \${MYSQL_DB} | gzip -c -9 > /backup/\${BACKUP_GZ_NAME} ;then + if flock -x -n /root/.cache/duplicity/backup.lock -c "exec /usr/local/bin/gosu mysql mysqldump -h\${MYSQL_HOST} -P\${MYSQL_PORT} -u\${MYSQL_USER} -p\${MYSQL_PASS} \${EXTRA_OPTS} \${MYSQL_DB} | gzip -c -9 > /backup/\${BACKUP_GZ_NAME}" ;then echo " Backup succeeded" else echo " Backup failed" From a154facbc59e2a30a92b2b8a4ea5fd69bbb5d86e Mon Sep 17 00:00:00 2001 From: Oleg Abrosimov Date: Tue, 27 Dec 2016 10:30:29 +0700 Subject: [PATCH 42/42] Use MAX_BACKUPS to cleanup duplicity dumps e.g. set MAX_BACKUPS=1M to remove all backups older then one month --- run.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/run.sh b/run.sh index 73ac919..8be3b6c 100755 --- a/run.sh +++ b/run.sh @@ -56,6 +56,14 @@ if [[ ! -z \${SFTP_USER} && ! -z \${SFTP_HOST} && ! -z \${SFTP_DIR} ]]; then else echo " Backup failed" fi + + if [ -n "\${MAX_BACKUPS}" ]; then + if flock -x -n /root/.cache/duplicity/backup.lock -c "duplicity remove-older-than \${MAX_BACKUPS} --force --ssh-options=\"-oProtocol=2 -oIdentityFile=/root/.ssh/id_rsa\" \${DUPLICITY_SCHEME}://\${SFTP_USER}@\${SFTP_HOST}:\${SFTP_PORT}/\${SFTP_DIR}" ;then + echo " Backup succeeded" + else + echo " Backup failed" + fi + fi else echo "=> Backup started: \${BACKUP_GZ_NAME}"