diff --git a/Dockerfile b/Dockerfile index 23dc390..d83c4b1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,33 +1,30 @@ ARG REPO=library -FROM ${REPO}/ubuntu:focal +FROM ${REPO}/alpine:3.12 LABEL maintainer="ViViDboarder " -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - ca-certificates \ - cron \ - restic=0.9.6* \ - && apt-get clean \ - && rm -rf /var/apt/lists/* +RUN apk add --no-cache curl=~7 bash=~5 -VOLUME /root/.cache/restic -VOLUME /backups +ARG ARCH=amd64 +ARG RCLONE_VERSION=v1.55.1 + +COPY ./scripts/install_rclone.sh /scripts/ +RUN /scripts/install_rclone.sh "$RCLONE_VERSION" "$ARCH" + +ARG RESTIC_VERSION=0.12.0 + +COPY ./scripts/install_restic.sh /scripts/ +RUN /scripts/install_restic.sh "$RESTIC_VERSION" "$ARCH" + +# Set some default environment variables ENV BACKUP_DEST="/backups" ENV BACKUP_NAME="backup" ENV PATH_TO_BACKUP="/data" - -# Cron schedules ENV CRON_SCHEDULE="" ENV VERIFY_CRON_SCHEDULE="" -COPY backup.sh / -COPY restore.sh / -COPY start.sh / -COPY verify.sh / -COPY healthcheck.sh / -COPY cron-exec.sh / +COPY ./scripts /scripts -HEALTHCHECK CMD /healthcheck.sh +HEALTHCHECK CMD /scripts/healthcheck.sh -CMD [ "/start.sh" ] +CMD [ "/scripts/start.sh" ] diff --git a/Makefile b/Makefile index 5760609..3f33eb3 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -DOCKER_TAG ?= docker-restic-cron +DOCKER_TAG ?= docker-restic-cron-$(USER) .PHONY: all all: check test-all @@ -15,7 +15,7 @@ build-x86: .PHONY: build-arm build-arm: - docker build --build-arg REPO=arm32v7 -f ./Dockerfile -t $(DOCKER_TAG)-arm32v7 . + docker build --build-arg REPO=arm32v7 --build-arg ARCH=arm -f ./Dockerfile -t $(DOCKER_TAG)-arm . .PHONY: build-all build-all: build-x86 build-arm @@ -25,15 +25,17 @@ test-x86: build-x86 cd tests && ./test.sh $(DOCKER_TAG) cd tests && ./test-pre-scripts.sh $(DOCKER_TAG) +.PHONY: test-arm +test-arm: build-arm + cd tests && ./test.sh $(DOCKER_TAG)-arm + cd tests && ./test-pre-scripts.sh $(DOCKER_TAG)-arm + .PHONY: test-all test-all: test-x86 test-arm .PHONY: test-s3-x86 test-s3-x86: - cd tests && ./test-s3.sh ubuntu - -.PHONY: test-s3-all -test-s3-all: test-s3-x86 test-s3-arm + cd tests && ./test-s3.sh .PHONY: shell-x86 shell-x86: build-x86 @@ -44,7 +46,9 @@ shell: shell-x86 .PHONY: clean clean: - docker-compose -f docker-compose-test-s3.yml down -v + docker-compose -f ./tests/docker-compose-test-s3.yml down -v + rm -fr my-backups/ + rm -fr my-data/ .PHONY: install-hooks install-hooks: diff --git a/backup.sh b/scripts/backup.sh similarity index 100% rename from backup.sh rename to scripts/backup.sh diff --git a/cron-exec.sh b/scripts/cron-exec.sh similarity index 100% rename from cron-exec.sh rename to scripts/cron-exec.sh diff --git a/healthcheck.sh b/scripts/healthcheck.sh similarity index 100% rename from healthcheck.sh rename to scripts/healthcheck.sh diff --git a/scripts/install_rclone.sh b/scripts/install_rclone.sh new file mode 100755 index 0000000..817ae13 --- /dev/null +++ b/scripts/install_rclone.sh @@ -0,0 +1,18 @@ +#! /bin/bash +set -ex + +VERSION="$1" +ARCH="$2" + +RCLONE_NAME=rclone-${VERSION}-linux-${ARCH} + +# Download +curl -o rclone.zip "https://downloads.rclone.org/${VERSION}/${RCLONE_NAME}.zip" + +# Install +unzip rclone.zip +mv "${RCLONE_NAME}/rclone" /usr/local/bin/ + +# Clean up +rm rclone.zip +rm -fr "${RCLONE_NAME}" diff --git a/scripts/install_restic.sh b/scripts/install_restic.sh new file mode 100755 index 0000000..68060f2 --- /dev/null +++ b/scripts/install_restic.sh @@ -0,0 +1,15 @@ +#! /bin/bash +set -ex + +VERSION="$1" +ARCH="$2" + +RESTIC_NAME=restic_${VERSION}_linux_${ARCH} + +# Download +curl -L -o restic.bz2 "https://github.com/restic/restic/releases/download/v${VERSION}/${RESTIC_NAME}.bz2" + +# Install +bunzip2 -v restic.bz2 +mv restic /usr/local/bin/ +chmod +x /usr/local/bin/restic diff --git a/restore.sh b/scripts/restore.sh similarity index 100% rename from restore.sh rename to scripts/restore.sh diff --git a/start.sh b/scripts/start.sh similarity index 88% rename from start.sh rename to scripts/start.sh index f8580b0..42eb67c 100755 --- a/start.sh +++ b/scripts/start.sh @@ -16,12 +16,12 @@ restic -r "$BACKUP_DEST" snapshots || restic -r "$BACKUP_DEST" init # If set to restore on start, restore if the data volume is empty if [ "$RESTORE_ON_EMPTY_START" == "true" ] && [ -z "$(ls -A "$PATH_TO_BACKUP")" ]; then - /cron-exec.sh /restore.sh latest + /scripts/cron-exec.sh /scripts/restore.sh latest fi # Unless explicitly skipping, take a backup on startup if [ "$SKIP_ON_START" != "true" ]; then - /cron-exec.sh /backup.sh + /scripts/cron-exec.sh /scripts/backup.sh fi if [ -n "$CRON_SCHEDULE" ]; then @@ -45,8 +45,11 @@ if [ -n "$CRON_SCHEDULE" ]; then # Add to crontab crontab /crontab.conf - echo "Starting restic cron..." - cron + # List crontabs + crontab -l + + echo "Starting cron..." + crond touch /cron.log tail -f /cron.log diff --git a/verify.sh b/scripts/verify.sh similarity index 75% rename from verify.sh rename to scripts/verify.sh index d932a0e..03c51f1 100755 --- a/verify.sh +++ b/scripts/verify.sh @@ -1,6 +1,7 @@ #! /bin/bash set -e +# shellcheck disable=SC2086 restic \ -r "$BACKUP_DEST" \ $OPT_ARGUMENTS \ diff --git a/tests/docker-compose-test-s3.yml b/tests/docker-compose-test-s3.yml index 931a4ff..5537047 100644 --- a/tests/docker-compose-test-s3.yml +++ b/tests/docker-compose-test-s3.yml @@ -26,5 +26,5 @@ services: expose: - "9000" environment: - MINIO_ACCESS_KEY: SUPER_SECRET_ACCESS_KEY - MINIO_SECRET_KEY: SUPER_SECRET_SECRET_KEY + MINIO_ROOT_USER: SUPER_SECRET_ACCESS_KEY + MINIO_ROOT_PASSWORD: SUPER_SECRET_SECRET_KEY diff --git a/tests/test-pre-scripts.sh b/tests/test-pre-scripts.sh index 6397994..ba0390b 100755 --- a/tests/test-pre-scripts.sh +++ b/tests/test-pre-scripts.sh @@ -10,19 +10,20 @@ if [ "$IN_CONTAINER" != "true" ] ; then -e SKIP_ON_START=true \ -e RESTIC_PASSWORD="Correct.Horse.Battery.Staple" \ -v "$(pwd)/test-pre-scripts.sh:/test.sh" \ - -v "$(pwd)/test-pre-scripts:/scripts" \ + -v "$(pwd)/test-pre-scripts/backup:/scripts/backup" \ + -v "$(pwd)/test-pre-scripts/restore:/scripts/restore" \ + -v "$(pwd)/test-pre-scripts/create-test-data.sql:/scripts/create-test-data.sql" \ "$image" \ bash -c "/test.sh" else echo "Performing backup tests" echo "Verify cron and crontab exist" - type cron + type crond type crontab echo "Install sqlite3" - apt-get update - apt-get install -y --no-install-recommends sqlite3 + apk add sqlite echo "Create test data..." mkdir -p /data @@ -30,10 +31,10 @@ else sqlite3 /data/test_database.db < /scripts/create-test-data.sql echo "Fake a start and init repo" - CRON_SCHEDULE="" /start.sh + CRON_SCHEDULE="" /scripts/start.sh echo "Making backup..." - /backup.sh + /scripts/backup.sh echo "Verify intermediary file is gone" test -f /data/test_database.db.bak && exit 1 || echo "Gone" @@ -45,7 +46,7 @@ else test -f /data/test_database.db && exit 1 || echo "Gone" echo "Restore backup..." - /restore.sh latest + /scripts/restore.sh latest echo "Verify restored files exist..." test -f /data/test_database.db @@ -59,7 +60,7 @@ else test -f /data/test_database.db && exit 1 || echo "Gone" echo "Simulate a restart with RESTORE_ON_EMPTY_START..." - RESTORE_ON_EMPTY_START=true /start.sh + RESTORE_ON_EMPTY_START=true /scripts/start.sh echo "Verify restore happened..." test -f /data/test_database.db @@ -71,5 +72,5 @@ else echo "Verify restore with incorrect passphrase fails..." echo "Fail to restore backup..." - RESTIC_PASSWORD=Incorrect.Mule.Solar.Paperclip /restore.sh latest && exit 1 || echo "OK" + RESTIC_PASSWORD=Incorrect.Mule.Solar.Paperclip /scripts/restore.sh latest && exit 1 || echo "OK" fi diff --git a/tests/test-s3.sh b/tests/test-s3.sh index 40cbdbc..a15dff5 100755 --- a/tests/test-s3.sh +++ b/tests/test-s3.sh @@ -1,6 +1,4 @@ #! /bin/bash -export DOCKER_BASE=$1 - docker-compose -f docker-compose-test-s3.yml up \ --build --abort-on-container-exit --force-recreate diff --git a/tests/test.sh b/tests/test.sh index 5cd36e0..d749acd 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -16,23 +16,23 @@ else echo "Performing backup tests" echo "Verify cron and crontab exist" - type cron + type crond type crontab echo "Create test data..." mkdir -p /data && echo Test > /data/test.txt echo "Fake a start and init repo" - CRON_SCHEDULE="" /start.sh + CRON_SCHEDULE="" /scripts/start.sh echo "Making backup..." - /cron-exec.sh /backup.sh || { cat /cron.log && exit 1; } + /scripts/cron-exec.sh /scripts/backup.sh || { cat /cron.log && exit 1; } echo "Verify backup..." - /cron-exec.sh /verify.sh || { cat /cron.log && exit 1; } + /scripts/cron-exec.sh /scripts/verify.sh || { cat /cron.log && exit 1; } echo "Auto cleanup on second backup..." - CLEANUP_COMMAND="--prune --keep-last 1" /cron-exec.sh /backup.sh || { cat /cron.log && exit 1; } + CLEANUP_COMMAND="--prune --keep-last 1" /scripts/cron-exec.sh /scripts/backup.sh || { cat /cron.log && exit 1; } echo "Delete test data..." rm -fr /data/* @@ -41,15 +41,15 @@ else test -f /data/test.txt && exit 1 || echo "Gone" echo "Restore backup..." - /cron-exec.sh /restore.sh latest || { cat /cron.log && exit 1; } - /healthcheck.sh + /scripts/cron-exec.sh /scripts/restore.sh latest || { cat /cron.log && exit 1; } + /scripts/healthcheck.sh echo "Verify restore..." test -f /data/test.txt cat /data/test.txt echo "Verify backup..." - /verify.sh + /scripts/verify.sh echo "Delete test data again..." rm -fr /data/* @@ -58,8 +58,8 @@ else test -f /data/test.txt && exit 1 || echo "Gone" echo "Simulate a restart with RESTORE_ON_EMPTY_START..." - RESTORE_ON_EMPTY_START=true /start.sh || { cat /cron.log && exit 1; } - /healthcheck.sh || { echo "Failed healthcheck"; cat /cron.log; exit 1; } + RESTORE_ON_EMPTY_START=true /scripts/start.sh || { cat /cron.log && exit 1; } + /scripts/healthcheck.sh || { echo "Failed healthcheck"; cat /cron.log; exit 1; } echo "Verify restore happened..." test -f /data/test.txt @@ -67,8 +67,8 @@ else echo "Verify restore with incorrect passphrase fails..." echo "Fail to restore backup..." - RESTIC_PASSWORD=Incorrect.Mule.Solar.Paperclip /cron-exec.sh /restore.sh latest && exit 1 || echo "OK" + RESTIC_PASSWORD=Incorrect.Mule.Solar.Paperclip /scripts/cron-exec.sh /scripts/restore.sh latest && exit 1 || echo "OK" echo "Verify failed healthcheck" - /healthcheck.sh && exit 1 || echo "OK" + /scripts/healthcheck.sh && exit 1 || echo "OK" fi