From 8317f50a8a315b9f66ae653d5ef9de98aa05b090 Mon Sep 17 00:00:00 2001 From: 3wc <3wc@doesthisthing.work> Date: Sat, 6 Nov 2021 19:45:39 +0200 Subject: [PATCH] Variables, Dockerfile, better syntax, etc. --- .envrc.sample | 8 ++++++++ Dockerfile | 14 ++++++++++++++ README.md | 21 +++++++++------------ backup.sh | 31 +++++++++++++++++++------------ compose.yml | 30 ++++++++++++++++++++++++++++++ 5 files changed, 80 insertions(+), 24 deletions(-) create mode 100644 .envrc.sample create mode 100644 Dockerfile create mode 100644 compose.yml diff --git a/.envrc.sample b/.envrc.sample new file mode 100644 index 0000000..adb349c --- /dev/null +++ b/.envrc.sample @@ -0,0 +1,8 @@ +export RESTIC_SFTP_HOST="user@domain.tld" +export RESTIC_PASSWORD_FILE=/run/secrets/restic-password +export BACKUP_DEST=/backups + +export SERVER_NAME=domain.tld +export DOCKER_CONTEXT=$SERVER_NAME + +#export SERVICES_OVERRIDE="ghost_domain_tld_app ghost_domain_tld_db" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8e76a61 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +FROM docker:19.03.13-dind + +RUN apk add --upgrade --no-cache \ + bash \ + curl \ + restic + +RUN curl -L https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 --output /usr/bin/jq +RUN chmod +x /usr/bin/jq + +COPY backup.sh /usr/bin/backup.sh +RUN chmod +x /usr/bin/backup.sh + +ENTRYPOINT ["/usr/bin/backup.sh"] diff --git a/README.md b/README.md index c5c4baf..ff4fa9e 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,13 @@ Automatically backup files from running Docker Swarm services based on labels. +## Background + +There are lots of Docker volume backup systems; all of them have one or both of +these problems: + - You need to define all the volumes to back up in the configuration system + - Backups require services to be stopped to take consistent copies + ## TODO - [ ] Make a Docker image of this @@ -13,8 +20,9 @@ Automatically backup files from running Docker Swarm services based on labels. (Haven't done secrets yet, here are two options) -v1: ``` +services: + db: deploy: labels: backupbot.backup: "true" @@ -24,17 +32,6 @@ v1: backupbot.backup.post-hook: "rm -rf /tmp/dump/dump.db" backupbot.backup.path: "/tmp/dump/" ``` -v2: -``` - deploy: - labels: - backupbot.backup: "true" - backupbot.backup.repos: "$some_thing" - backupbot.backup.at: "* * * * *" - backupbot.backup.post-hook: "rm -rf /tmp/dump/dump.db" - backupbot.backup.secrets": "db_root_password", - backupbot.backup.pre-hook: 'mysqldump -u root -p"$DB_ROOT_PASSWORD" -f /tmp/dump/dump.db' -``` ## Questions: diff --git a/backup.sh b/backup.sh index 43fa83f..246e47d 100755 --- a/backup.sh +++ b/backup.sh @@ -1,15 +1,20 @@ #!/bin/bash -# FIXME: just for testing -backup_path=backups +server_name="${SERVER_NAME:?SERVER_NAME not set}" -# FIXME: just for testing -export DOCKER_CONTEXT=demo.coopcloud.tech +restic_password_file="${RESTIC_PASSWORD_FILE:?RESTIC_PASSWORD_FILE not set}" -mapfile -t services < <(docker service ls --format '{{ .Name }}') +restic_sftp_host="${RESTIC_SFTP_HOST:?RESTIC_SFTP_HOST not set}" -# FIXME: just for testing -services=( "ghost_demo_app" "ghost_demo_db" ) +restic_repo="sftp:$restic_sftp_host:/$server_name" + +backup_path="${BACKUP_DEST:?BACKUP_DEST not set}" + +if [ -n "$SERVICES_OVERRIDE" ]; then + services=($SERVICES_OVERRIDE) +else + mapfile -t services < <(docker service ls --format '{{ .Name }}') +fi for service in "${services[@]}"; do echo "service: $service" @@ -32,7 +37,7 @@ for service in "${services[@]}"; do if [ "$pre" != "null" ]; then # run the precommand # shellcheck disable=SC2086 - docker exec "$container" $pre + docker exec "$container" sh -c "$pre" fi # run the backup @@ -41,10 +46,12 @@ for service in "${services[@]}"; do if [ "$post" != "null" ]; then # run the postcommand # shellcheck disable=SC2086 - docker exec "$container" $post + docker exec "$container" sh -c "$post" fi fi - restic -p restic-password \ - backup --quiet -r sftp:u272979@u272979.your-storagebox.de:/demo.coopcloud.tech \ - --tag coop-cloud "$backup_path" done + +restic -p "$restic_password_file" \ + backup --quiet -r "$restic_repo" \ + -o sftp.command="ssh $restic_sftp_host -s sftp" \ + --tag coop-cloud "$backup_path" diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..b45a723 --- /dev/null +++ b/compose.yml @@ -0,0 +1,30 @@ +--- +version: "3.8" +services: + app: + image: thecoopcloud/backup-bot-two:latest + volumes: + - "/var/run/docker.sock:/var/run/docker.sock" + - "backups:/backups" + environment: + - RESTIC_REPO + - RESTIC_PASSWORD_FILE=/run/secrets/restic_password + - BACKUP_DEST=/backups + - SERVER_NAME + secrets: + - restic_password + + deploy: + mode: replicated + replicas: 0 + labels: + - "swarm.cronjob.enable=true" + # Note(3wc): every minute, testing + - "swarm.cronjob.schedule=*/5 * * * *" + # - "swarm.cronjob.schedule=0 9 * * 1-5" # office hours + - coop-cloud.${STACK_NAME}.app.version=24.98.9-slim-d3db1c25 + restart_policy: + condition: none + +volumes: + backups: