From 3402f802a9145333cd07d5ecaf729a33e770f986 Mon Sep 17 00:00:00 2001 From: Gilles Filippini Date: Wed, 28 Apr 2021 00:00:01 +0200 Subject: [PATCH] First version --- Dockerfile | 34 ++++++++++++++++++++ README.md | 18 ++++++++++- bin/do_backup | 29 +++++++++++++++++ bin/docker-entrypoint.sh | 29 +++++++++++++++++ docker-duplicity-backup | 67 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 Dockerfile create mode 100755 bin/do_backup create mode 100755 bin/docker-entrypoint.sh create mode 100755 docker-duplicity-backup diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8d20c94 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,34 @@ +# docker-duplicity-backup +# +# Copyright (C) 2021 Pini +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +FROM debian + +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get -y install \ + openssh-client \ + stunnel4 \ + rsync \ + duplicity + +ENTRYPOINT ["docker-entrypoint.sh"] +WORKDIR /root +CMD ["do_backup"] + +COPY bin/* /usr/local/bin/ + +VOLUME /root/.cache/duplicity +RUN mkdir init.d diff --git a/README.md b/README.md index 820ca32..ca0e7ea 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,19 @@ # docker-duplicity-backup -Docker container and script to backup a list of docker volumes to a remote duplicity target. \ No newline at end of file +Docker container and script to backup a list of docker volumes to a remote duplicity target. + +## Usage + +``` +$ ./docker-duplicity-backup +``` + +The `config_file` parameter is mandatory and must designate a script file which set these variables: + * `DOCKER_HOSTNAME`: hostname used for the container running the backup (optional; defaults to '`backup`') + This hostname should be the same through incremental backups or duplicity will complain + * `VOLUMES`: space separated lit of volumes to backup + * `DUPLICITY_REMOTE_URI`: target URI for duplicity backup (mandatory; e.g. 'rsync://backup.example.com//target/path') + * `DUPLICITY_CACHE_VOLUME`: docker volume name to use for duplicity cache persistency (optional; default to '`backup_cache`') + * `INIT_FOLDER`: local path to mount into the container as `/root/init.d` (optional) + The scripts into this folder will be sourced by the container's entrypoint before starting the backup. Useful for starting an `stunnel` service + * `DOCKER_EXTRA_OPTIONS`: docker run options such as environment variables or extra volumes. Useful for importing an ssh configuration folder diff --git a/bin/do_backup b/bin/do_backup new file mode 100755 index 0000000..563a51a --- /dev/null +++ b/bin/do_backup @@ -0,0 +1,29 @@ +#!/bin/bash +# docker-duplicity-backup +# +# Copyright (C) 2021 Pini +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +month_start=$(date -Iseconds | sed 's/..T..:..:../01T00:00:00/') + +function backup_volume () { + local volume="$1" + duplicity --no-encryption --full-if-older-than "$month_start" --file-prefix "$volume." /volumes/$volume "$DUPLICITY_REMOTE_URI" +} + +for volume in $VOLUMES; do + echo "Backuping volume '$volume'..." + backup_volume $volume +done diff --git a/bin/docker-entrypoint.sh b/bin/docker-entrypoint.sh new file mode 100755 index 0000000..445f0ee --- /dev/null +++ b/bin/docker-entrypoint.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# docker-duplicity-backup +# +# Copyright (C) 2021 Pini +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +for file in $(ls init.d); do + if [ -x init.d/$file ]; then + ./init.d/$file + fi +done + +if [ $# -gt 0 ]; then + exec "$@" +else + exec /bin/bash -l +fi diff --git a/docker-duplicity-backup b/docker-duplicity-backup new file mode 100755 index 0000000..69d4ed6 --- /dev/null +++ b/docker-duplicity-backup @@ -0,0 +1,67 @@ +#!/bin/bash +# docker-duplicity-backup +# +# Copyright (C) 2021 Pini +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +set -euo pipefail + +function usage () { + echo "Usage: $(basename "$0") " +} + +conf_file="$1" +if [ -z "$conf_file" ]; then + usage >&2 + exit 1 +fi + +if ! [ -f "$conf_file" ]; then + echo "Missing configuration file '$conf_file'" >&2 + exit 2 +fi + +echo "Sourcing configuration file '$conf_file'..." +source "$conf_file" + +echo "Running docker-duplicity-backup using this configuration: +DOCKER_HOSTNAME='${DOCKER_HOSTNAME:-}' +VOLUMES='$VOLUMES' +DUPLICITY_REMOTE_URI='$DUPLICITY_REMOTE_URI' +DUPLICITY_CACHE_VOLUME='${DUPLICITY_CACHE_VOLUME:-}' +INIT_FOLDER='${INIT_FOLDER:-}' +DOCKER_EXTRA_OPTIONS='${DOCKER_EXTRA_OPTIONS[@]:-}' +" + +DOCKER_HOSTNAME="${DOCKER_HOSTNAME:-docker-duplicity-backup}" +DUPLICITY_CACHE_VOLUME="${DUPLICITY_CACHE_VOLUME:-backup_cache}" + +declare -a docker_mounts +for volume in $VOLUMES; do + docker_mounts+=(-v "$volume:/volumes/$volume:ro") +done + +if [ -n "$INIT_FOLDER" ]; then + docker_mounts+=(-v "$INIT_FOLDER":/root/init.d) +fi + +docker run --rm -it \ + --hostname "$DOCKER_HOSTNAME" \ + -v "$DUPLICITY_CACHE_VOLUME":/root/.cache/duplicity \ + "${docker_mounts[@]}" \ + -e VOLUMES="$VOLUMES" \ + -e DUPLICITY_REMOTE_URI="$DUPLICITY_REMOTE_URI" \ + "${DOCKER_EXTRA_OPTIONS[@]:-\--}" \ + pinidh/docker-duplicity-backup