From 5f6e60d502996fac81a9aaf90a63a9bebaee01bd Mon Sep 17 00:00:00 2001 From: "Kevin Veen-Birkenbach [aka. Frantz]" Date: Thu, 19 Aug 2021 13:09:44 +0200 Subject: [PATCH 01/12] Added recover instruction --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 6766085..bd4fd14 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,13 @@ Execute: ./docker-volume-backup.sh ``` +## Recover +Execute: + +```bash +./docker-volume-recover.sh {{volume_name}} {{backup_path}} +``` + ## Debug To checkout what's going on in the mount container type in the following command: From c303a8b452efda2cbdf0be183cc1c99ffe2c175d Mon Sep 17 00:00:00 2001 From: "Kevin Veen-Birkenbach [aka. Frantz]" Date: Thu, 19 Aug 2021 13:43:22 +0200 Subject: [PATCH 02/12] Added draft for backup by volume instead of container --- docker-volume-backup.sh | 47 +++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/docker-volume-backup.sh b/docker-volume-backup.sh index e5e3551..e2b9e3b 100644 --- a/docker-volume-backup.sh +++ b/docker-volume-backup.sh @@ -1,29 +1,34 @@ #!/bin/bash -# If rsync stucks consider: +# Just backups volumes of running containers +# If rsync stucks consider: # @see https://stackoverflow.com/questions/20773118/rsync-suddenly-hanging-indefinitely-during-transfers +# backup_time="$(date '+%Y%m%d%H%M%S')"; backups_folder="/Backups/"; -for docker_container_name in $(docker ps --format '{{.Names}}'); +for volume_name in $(docker volume ls --format '{{.Name}}'); do - echo "stop container: $docker_container_name" && docker stop "$docker_container_name" - for source_path in $(docker inspect --format '{{ range .Mounts }}{{ if eq .Type "volume" }}{{ println .Destination }}{{ end }}{{ end }}' "$docker_container_name"); + for docker_container_name in $(docker ps -a --filter volume=$volume_name --format '{{.Names}}'); do - repository_name="$(cd "$(dirname "$(readlink -f "${0}")")" && basename `git rev-parse --show-toplevel`)"; - machine_id="$(sha256sum /etc/machine-id | head -c 64)"; - backup_repository_folder="$backups_folder$machine_id/$repository_name/"; - destination_path="$backup_repository_folder""latest/$docker_container_name$source_path"; - log_path="$backup_repository_folder""log.txt"; - backup_dir_path="$backup_repository_folder""diffs/$backup_time/$docker_container_name$source_path"; - if [ -d "$destination_path" ] - then - echo "backup: $source_path"; - else - echo "first backup: $source_path" - mkdir -vp "$destination_path"; - mkdir -vp "$backup_dir_path"; - fi - docker run --rm --volumes-from "$docker_container_name" -v "$backups_folder:$backups_folder" "kevinveenbirkenbach/alpine-rsync" sh -c " - rsync -abP --delete --delete-excluded --log-file=$log_path --backup-dir=$backup_dir_path '$source_path/' $destination_path"; + echo "stop container: $docker_container_name" && docker stop "$docker_container_name" + for source_path in $(docker inspect --format '{{ range .Mounts }}{{ if eq .Type "volume" }}{{ println .Destination }}{{ end }}{{ end }}' "$docker_container_name"); + do + repository_name="$(cd "$(dirname "$(readlink -f "${0}")")" && basename `git rev-parse --show-toplevel`)"; + machine_id="$(sha256sum /etc/machine-id | head -c 64)"; + backup_repository_folder="$backups_folder$machine_id/$repository_name/"; + destination_path="$backup_repository_folder""latest/$docker_container_name$source_path"; + log_path="$backup_repository_folder""log.txt"; + backup_dir_path="$backup_repository_folder""diffs/$backup_time/$docker_container_name$source_path"; + if [ -d "$destination_path" ] + then + echo "backup: $source_path"; + else + echo "first backup: $source_path" + mkdir -vp "$destination_path"; + mkdir -vp "$backup_dir_path"; + fi + docker run --rm --volumes-from "$docker_container_name" -v "$backups_folder:$backups_folder" "kevinveenbirkenbach/alpine-rsync" sh -c " + rsync -abP --delete --delete-excluded --log-file=$log_path --backup-dir=$backup_dir_path '$source_path/' $destination_path"; + done + echo "start container: $docker_container_name" && docker start "$docker_container_name"; done - echo "start container: $docker_container_name" && docker start "$docker_container_name"; done From 660c847383fe00d93d4ee1cb1fe241b01bb931cb Mon Sep 17 00:00:00 2001 From: "Kevin Veen-Birkenbach [aka. Frantz]" Date: Thu, 19 Aug 2021 13:44:24 +0200 Subject: [PATCH 03/12] changed docker_container_name to container_name --- docker-volume-backup.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docker-volume-backup.sh b/docker-volume-backup.sh index e2b9e3b..6d012b7 100644 --- a/docker-volume-backup.sh +++ b/docker-volume-backup.sh @@ -7,17 +7,17 @@ backup_time="$(date '+%Y%m%d%H%M%S')"; backups_folder="/Backups/"; for volume_name in $(docker volume ls --format '{{.Name}}'); do - for docker_container_name in $(docker ps -a --filter volume=$volume_name --format '{{.Names}}'); + for container_name in $(docker ps -a --filter volume=$volume_name --format '{{.Names}}'); do - echo "stop container: $docker_container_name" && docker stop "$docker_container_name" - for source_path in $(docker inspect --format '{{ range .Mounts }}{{ if eq .Type "volume" }}{{ println .Destination }}{{ end }}{{ end }}' "$docker_container_name"); + echo "stop container: $container_name" && docker stop "$container_name" + for source_path in $(docker inspect --format '{{ range .Mounts }}{{ if eq .Type "volume" }}{{ println .Destination }}{{ end }}{{ end }}' "$container_name"); do repository_name="$(cd "$(dirname "$(readlink -f "${0}")")" && basename `git rev-parse --show-toplevel`)"; machine_id="$(sha256sum /etc/machine-id | head -c 64)"; backup_repository_folder="$backups_folder$machine_id/$repository_name/"; - destination_path="$backup_repository_folder""latest/$docker_container_name$source_path"; + destination_path="$backup_repository_folder""latest/$container_name$source_path"; log_path="$backup_repository_folder""log.txt"; - backup_dir_path="$backup_repository_folder""diffs/$backup_time/$docker_container_name$source_path"; + backup_dir_path="$backup_repository_folder""diffs/$backup_time/$container_name$source_path"; if [ -d "$destination_path" ] then echo "backup: $source_path"; @@ -26,9 +26,9 @@ do mkdir -vp "$destination_path"; mkdir -vp "$backup_dir_path"; fi - docker run --rm --volumes-from "$docker_container_name" -v "$backups_folder:$backups_folder" "kevinveenbirkenbach/alpine-rsync" sh -c " + docker run --rm --volumes-from "$container_name" -v "$backups_folder:$backups_folder" "kevinveenbirkenbach/alpine-rsync" sh -c " rsync -abP --delete --delete-excluded --log-file=$log_path --backup-dir=$backup_dir_path '$source_path/' $destination_path"; done - echo "start container: $docker_container_name" && docker start "$docker_container_name"; + echo "start container: $container_name" && docker start "$container_name"; done done From 862797e51afce797af5295d44af5e74147558735 Mon Sep 17 00:00:00 2001 From: "Kevin Veen-Birkenbach [aka. Frantz]" Date: Thu, 19 Aug 2021 13:46:35 +0200 Subject: [PATCH 04/12] Moved variables for better readability --- docker-volume-backup.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker-volume-backup.sh b/docker-volume-backup.sh index 6d012b7..025052f 100644 --- a/docker-volume-backup.sh +++ b/docker-volume-backup.sh @@ -5,6 +5,9 @@ # backup_time="$(date '+%Y%m%d%H%M%S')"; backups_folder="/Backups/"; +repository_name="$(cd "$(dirname "$(readlink -f "${0}")")" && basename `git rev-parse --show-toplevel`)"; +machine_id="$(sha256sum /etc/machine-id | head -c 64)"; +backup_repository_folder="$backups_folder$machine_id/$repository_name/"; for volume_name in $(docker volume ls --format '{{.Name}}'); do for container_name in $(docker ps -a --filter volume=$volume_name --format '{{.Names}}'); @@ -12,9 +15,6 @@ do echo "stop container: $container_name" && docker stop "$container_name" for source_path in $(docker inspect --format '{{ range .Mounts }}{{ if eq .Type "volume" }}{{ println .Destination }}{{ end }}{{ end }}' "$container_name"); do - repository_name="$(cd "$(dirname "$(readlink -f "${0}")")" && basename `git rev-parse --show-toplevel`)"; - machine_id="$(sha256sum /etc/machine-id | head -c 64)"; - backup_repository_folder="$backups_folder$machine_id/$repository_name/"; destination_path="$backup_repository_folder""latest/$container_name$source_path"; log_path="$backup_repository_folder""log.txt"; backup_dir_path="$backup_repository_folder""diffs/$backup_time/$container_name$source_path"; From df8afdb2ba9e88f9e85c9278e381cde47ec1550a Mon Sep 17 00:00:00 2001 From: "Kevin Veen-Birkenbach [aka. Frantz]" Date: Thu, 19 Aug 2021 14:01:38 +0200 Subject: [PATCH 05/12] Just backup volumes in actual volume loop --- docker-volume-backup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-volume-backup.sh b/docker-volume-backup.sh index 025052f..5edfb99 100644 --- a/docker-volume-backup.sh +++ b/docker-volume-backup.sh @@ -13,7 +13,7 @@ do for container_name in $(docker ps -a --filter volume=$volume_name --format '{{.Names}}'); do echo "stop container: $container_name" && docker stop "$container_name" - for source_path in $(docker inspect --format '{{ range .Mounts }}{{ if eq .Type "volume" }}{{ println .Destination }}{{ end }}{{ end }}' "$container_name"); + for source_path in $(docker inspect --format "{{ range .Mounts }}{{ if eq .Type \"volume\"}}{{ if eq .Name \"$volume_name\"}}{{ println .Destination }}{{ end }}{{ end }}{{ end }}" "$container_name"); do destination_path="$backup_repository_folder""latest/$container_name$source_path"; log_path="$backup_repository_folder""log.txt"; From 1bda32b8ff47a931153e1d77fc3b05c02655ebc3 Mon Sep 17 00:00:00 2001 From: "Kevin Veen-Birkenbach [aka. Frantz]" Date: Thu, 19 Aug 2021 14:09:34 +0200 Subject: [PATCH 06/12] Changed backup destination path --- docker-volume-backup.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-volume-backup.sh b/docker-volume-backup.sh index 5edfb99..dec1551 100644 --- a/docker-volume-backup.sh +++ b/docker-volume-backup.sh @@ -15,9 +15,9 @@ do echo "stop container: $container_name" && docker stop "$container_name" for source_path in $(docker inspect --format "{{ range .Mounts }}{{ if eq .Type \"volume\"}}{{ if eq .Name \"$volume_name\"}}{{ println .Destination }}{{ end }}{{ end }}{{ end }}" "$container_name"); do - destination_path="$backup_repository_folder""latest/$container_name$source_path"; + destination_path="$backup_repository_folder""latest/$volume_name"; log_path="$backup_repository_folder""log.txt"; - backup_dir_path="$backup_repository_folder""diffs/$backup_time/$container_name$source_path"; + backup_dir_path="$backup_repository_folder""diffs/$backup_time/$volume_name"; if [ -d "$destination_path" ] then echo "backup: $source_path"; From e494f1602e5cde0fd1df894fd14151ac590b56ae Mon Sep 17 00:00:00 2001 From: "Kevin Veen-Birkenbach [aka. Frantz]" Date: Thu, 19 Aug 2021 19:47:45 +0200 Subject: [PATCH 07/12] Optimized status messages --- docker-volume-backup.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docker-volume-backup.sh b/docker-volume-backup.sh index dec1551..26d4f34 100644 --- a/docker-volume-backup.sh +++ b/docker-volume-backup.sh @@ -10,6 +10,7 @@ machine_id="$(sha256sum /etc/machine-id | head -c 64)"; backup_repository_folder="$backups_folder$machine_id/$repository_name/"; for volume_name in $(docker volume ls --format '{{.Name}}'); do + echo "start backup routine: $volume_name"; for container_name in $(docker ps -a --filter volume=$volume_name --format '{{.Names}}'); do echo "stop container: $container_name" && docker stop "$container_name" @@ -20,9 +21,9 @@ do backup_dir_path="$backup_repository_folder""diffs/$backup_time/$volume_name"; if [ -d "$destination_path" ] then - echo "backup: $source_path"; + echo "backup volume: $volume_name"; else - echo "first backup: $source_path" + echo "first backup volume: $volume_name" mkdir -vp "$destination_path"; mkdir -vp "$backup_dir_path"; fi @@ -31,4 +32,5 @@ do done echo "start container: $container_name" && docker start "$container_name"; done + echo "end backup routine: $volume_name"; done From 9cff82fa49ee1221dac92cdf909f3c1dc8992d85 Mon Sep 17 00:00:00 2001 From: "Kevin Veen-Birkenbach [aka. Frantz]" Date: Thu, 19 Aug 2021 19:57:16 +0200 Subject: [PATCH 08/12] Differenciated between raw and prepared backup data for following mysqldump implementation --- docker-volume-backup.sh | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/docker-volume-backup.sh b/docker-volume-backup.sh index 26d4f34..03e8531 100644 --- a/docker-volume-backup.sh +++ b/docker-volume-backup.sh @@ -17,18 +17,24 @@ do for source_path in $(docker inspect --format "{{ range .Mounts }}{{ if eq .Type \"volume\"}}{{ if eq .Name \"$volume_name\"}}{{ println .Destination }}{{ end }}{{ end }}{{ end }}" "$container_name"); do destination_path="$backup_repository_folder""latest/$volume_name"; + raw_destination_path="$destination_path/raw" + prepared_destination_path="$destination_path/prepared" log_path="$backup_repository_folder""log.txt"; backup_dir_path="$backup_repository_folder""diffs/$backup_time/$volume_name"; + raw_backup_dir_path="$backup_dir_path/raw"; + prepared_backup_dir_path="$backup_dir_path/prepared"; if [ -d "$destination_path" ] then echo "backup volume: $volume_name"; else echo "first backup volume: $volume_name" - mkdir -vp "$destination_path"; - mkdir -vp "$backup_dir_path"; + mkdir -vp "$raw_destination_path"; + mkdir -vp "$raw_backup_dir_path"; + mkdir -vp "$prepared_destination_path"; + mkdir -vp "$prepared_backup_dir_path"; fi docker run --rm --volumes-from "$container_name" -v "$backups_folder:$backups_folder" "kevinveenbirkenbach/alpine-rsync" sh -c " - rsync -abP --delete --delete-excluded --log-file=$log_path --backup-dir=$backup_dir_path '$source_path/' $destination_path"; + rsync -abP --delete --delete-excluded --log-file=$log_path --backup-dir=$raw_backup_dir_path '$source_path/' $raw_destination_path"; done echo "start container: $container_name" && docker start "$container_name"; done From 5cc5a6e5e541d0a151b7c357af6288d37a36ade1 Mon Sep 17 00:00:00 2001 From: "Kevin Veen-Birkenbach [aka. Frantz]" Date: Thu, 19 Aug 2021 20:01:19 +0200 Subject: [PATCH 09/12] Solved shellcheck error --- docker-volume-backup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-volume-backup.sh b/docker-volume-backup.sh index 03e8531..8fc9ed3 100644 --- a/docker-volume-backup.sh +++ b/docker-volume-backup.sh @@ -11,7 +11,7 @@ backup_repository_folder="$backups_folder$machine_id/$repository_name/"; for volume_name in $(docker volume ls --format '{{.Name}}'); do echo "start backup routine: $volume_name"; - for container_name in $(docker ps -a --filter volume=$volume_name --format '{{.Names}}'); + for container_name in $(docker ps -a --filter volume="$volume_name" --format '{{.Names}}'); do echo "stop container: $container_name" && docker stop "$container_name" for source_path in $(docker inspect --format "{{ range .Mounts }}{{ if eq .Type \"volume\"}}{{ if eq .Name \"$volume_name\"}}{{ println .Destination }}{{ end }}{{ end }}{{ end }}" "$container_name"); From 76d32a2e5c4a338f0c57c395ccc8aff24440235b Mon Sep 17 00:00:00 2001 From: "Kevin Veen-Birkenbach [aka. Frantz]" Date: Thu, 19 Aug 2021 21:18:14 +0200 Subject: [PATCH 10/12] just backup running containers --- docker-volume-backup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-volume-backup.sh b/docker-volume-backup.sh index 8fc9ed3..4b8e3c6 100644 --- a/docker-volume-backup.sh +++ b/docker-volume-backup.sh @@ -11,7 +11,7 @@ backup_repository_folder="$backups_folder$machine_id/$repository_name/"; for volume_name in $(docker volume ls --format '{{.Name}}'); do echo "start backup routine: $volume_name"; - for container_name in $(docker ps -a --filter volume="$volume_name" --format '{{.Names}}'); + for container_name in $(docker ps --filter volume="$volume_name" --format '{{.Names}}'); do echo "stop container: $container_name" && docker stop "$container_name" for source_path in $(docker inspect --format "{{ range .Mounts }}{{ if eq .Type \"volume\"}}{{ if eq .Name \"$volume_name\"}}{{ println .Destination }}{{ end }}{{ end }}{{ end }}" "$container_name"); From 99f7b387c2a8cecaa2deb2cc4fda392fccd5c1e2 Mon Sep 17 00:00:00 2001 From: "Kevin Veen-Birkenbach [aka. Frantz]" Date: Thu, 19 Aug 2021 22:00:17 +0200 Subject: [PATCH 11/12] Highered performance by removing container loop --- docker-volume-backup.sh | 50 ++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/docker-volume-backup.sh b/docker-volume-backup.sh index 4b8e3c6..748b957 100644 --- a/docker-volume-backup.sh +++ b/docker-volume-backup.sh @@ -11,32 +11,32 @@ backup_repository_folder="$backups_folder$machine_id/$repository_name/"; for volume_name in $(docker volume ls --format '{{.Name}}'); do echo "start backup routine: $volume_name"; - for container_name in $(docker ps --filter volume="$volume_name" --format '{{.Names}}'); + containers="$(docker ps --filter volume="$volume_name" --format '{{.Names}}')"; + containers_array=($containers) + container=${containers_array[0]} + echo "stop containers: $containers" && docker stop "$containers" + for source_path in $(docker inspect --format "{{ range .Mounts }}{{ if eq .Type \"volume\"}}{{ if eq .Name \"$volume_name\"}}{{ println .Destination }}{{ end }}{{ end }}{{ end }}" "$container"); do - echo "stop container: $container_name" && docker stop "$container_name" - for source_path in $(docker inspect --format "{{ range .Mounts }}{{ if eq .Type \"volume\"}}{{ if eq .Name \"$volume_name\"}}{{ println .Destination }}{{ end }}{{ end }}{{ end }}" "$container_name"); - do - destination_path="$backup_repository_folder""latest/$volume_name"; - raw_destination_path="$destination_path/raw" - prepared_destination_path="$destination_path/prepared" - log_path="$backup_repository_folder""log.txt"; - backup_dir_path="$backup_repository_folder""diffs/$backup_time/$volume_name"; - raw_backup_dir_path="$backup_dir_path/raw"; - prepared_backup_dir_path="$backup_dir_path/prepared"; - if [ -d "$destination_path" ] - then - echo "backup volume: $volume_name"; - else - echo "first backup volume: $volume_name" - mkdir -vp "$raw_destination_path"; - mkdir -vp "$raw_backup_dir_path"; - mkdir -vp "$prepared_destination_path"; - mkdir -vp "$prepared_backup_dir_path"; - fi - docker run --rm --volumes-from "$container_name" -v "$backups_folder:$backups_folder" "kevinveenbirkenbach/alpine-rsync" sh -c " - rsync -abP --delete --delete-excluded --log-file=$log_path --backup-dir=$raw_backup_dir_path '$source_path/' $raw_destination_path"; - done - echo "start container: $container_name" && docker start "$container_name"; + destination_path="$backup_repository_folder""latest/$volume_name"; + raw_destination_path="$destination_path/raw" + prepared_destination_path="$destination_path/prepared" + log_path="$backup_repository_folder""log.txt"; + backup_dir_path="$backup_repository_folder""diffs/$backup_time/$volume_name"; + raw_backup_dir_path="$backup_dir_path/raw"; + prepared_backup_dir_path="$backup_dir_path/prepared"; + if [ -d "$destination_path" ] + then + echo "backup volume: $volume_name"; + else + echo "first backup volume: $volume_name" + mkdir -vp "$raw_destination_path"; + mkdir -vp "$raw_backup_dir_path"; + mkdir -vp "$prepared_destination_path"; + mkdir -vp "$prepared_backup_dir_path"; + fi + docker run --rm --volumes-from "$container" -v "$backups_folder:$backups_folder" "kevinveenbirkenbach/alpine-rsync" sh -c " + rsync -abP --delete --delete-excluded --log-file=$log_path --backup-dir=$raw_backup_dir_path '$source_path/' $raw_destination_path"; + echo "start containers: $containers" && docker start "$containers"; done echo "end backup routine: $volume_name"; done From aaa86b78d10878015875184b72c6c4307953152d Mon Sep 17 00:00:00 2001 From: "Kevin Veen-Birkenbach [aka. Frantz]" Date: Thu, 19 Aug 2021 22:32:23 +0200 Subject: [PATCH 12/12] solved containers bug --- docker-volume-backup.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-volume-backup.sh b/docker-volume-backup.sh index 748b957..6ee115a 100644 --- a/docker-volume-backup.sh +++ b/docker-volume-backup.sh @@ -14,7 +14,7 @@ do containers="$(docker ps --filter volume="$volume_name" --format '{{.Names}}')"; containers_array=($containers) container=${containers_array[0]} - echo "stop containers: $containers" && docker stop "$containers" + echo "stop containers:" && docker stop $containers for source_path in $(docker inspect --format "{{ range .Mounts }}{{ if eq .Type \"volume\"}}{{ if eq .Name \"$volume_name\"}}{{ println .Destination }}{{ end }}{{ end }}{{ end }}" "$container"); do destination_path="$backup_repository_folder""latest/$volume_name"; @@ -36,7 +36,7 @@ do fi docker run --rm --volumes-from "$container" -v "$backups_folder:$backups_folder" "kevinveenbirkenbach/alpine-rsync" sh -c " rsync -abP --delete --delete-excluded --log-file=$log_path --backup-dir=$raw_backup_dir_path '$source_path/' $raw_destination_path"; - echo "start containers: $containers" && docker start "$containers"; + echo "start containers:" && docker start $containers; done echo "end backup routine: $volume_name"; done