mirror of
https://github.com/lobaro/restic-backup-docker.git
synced 2026-04-05 20:58:50 +00:00
Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88620c3acb | ||
|
|
b0408d66a5 | ||
|
|
d10efe97f5 | ||
|
|
29e46cad2c | ||
|
|
0f2df46b9d | ||
|
|
5f5f75f903 | ||
|
|
5c0dbbc9cc | ||
|
|
7ed9080c68 | ||
|
|
683db322d7 | ||
|
|
f99b15304f | ||
|
|
6613cd39b3 | ||
|
|
71feaad5b4 | ||
|
|
b4ed623bd4 | ||
|
|
31a9e3f328 | ||
|
|
1033900afc | ||
|
|
8aa40aa682 | ||
|
|
4cdfc85445 | ||
|
|
f4275c5aef | ||
|
|
8a49ee9a53 | ||
|
|
6bedee1ab1 | ||
|
|
5e99ccbc9f | ||
|
|
393cc232c1 | ||
|
|
99ad449822 | ||
|
|
fb54cf6906 | ||
|
|
d3c851da27 | ||
|
|
f500b08d94 | ||
|
|
fa45e05b19 | ||
|
|
527ba2dd4f | ||
|
|
effd03a102 | ||
|
|
a6a6570d78 | ||
|
|
d9246419f9 | ||
|
|
9a3bf04654 | ||
|
|
1b2d36f3c4 | ||
|
|
bb10ca8b31 | ||
|
|
f081131560 | ||
|
|
0eb6656705 | ||
|
|
918b7f656a | ||
|
|
3b400123d3 | ||
|
|
bf045a4be3 | ||
|
|
9e028df9a7 | ||
|
|
d896924040 | ||
|
|
d0cea127a5 | ||
|
|
013efd00a9 | ||
|
|
bb1d2e202b | ||
|
|
e5f81c232e |
45
Dockerfile
45
Dockerfile
@@ -1,36 +1,47 @@
|
|||||||
FROM golang:1.7-alpine
|
FROM alpine:3.10.1 as certs
|
||||||
MAINTAINER info@lobaro.com
|
RUN apk add --no-cache ca-certificates
|
||||||
|
|
||||||
RUN echo http://nl.alpinelinux.org/alpine/v3.4/community >> /etc/apk/repositories
|
# Get restic executable
|
||||||
RUN apk add --no-cache git nfs-utils openssh fuse
|
ENV RESTIC_VERSION=0.9.5
|
||||||
RUN git clone https://github.com/restic/restic \
|
ADD https://github.com/restic/restic/releases/download/v${RESTIC_VERSION}/restic_${RESTIC_VERSION}_linux_amd64.bz2 /
|
||||||
&& cd restic \
|
RUN bzip2 -d restic_${RESTIC_VERSION}_linux_amd64.bz2 && mv restic_${RESTIC_VERSION}_linux_amd64 /bin/restic && chmod +x /bin/restic
|
||||||
&& go run build.go \
|
|
||||||
&& cp restic /usr/local/bin/
|
|
||||||
RUN apk del git
|
|
||||||
|
|
||||||
RUN mkdir /mnt/restic
|
FROM alpine as rclone
|
||||||
|
|
||||||
|
# Get rclone executable
|
||||||
|
ADD https://downloads.rclone.org/rclone-current-linux-amd64.zip /
|
||||||
|
RUN unzip rclone-current-linux-amd64.zip && mv rclone-*-linux-amd64/rclone /bin/rclone && chmod +x /bin/rclone
|
||||||
|
|
||||||
|
FROM busybox:glibc
|
||||||
|
|
||||||
|
# install mailx
|
||||||
|
RUN apk add --update --no-cache heirloom-mailx
|
||||||
|
|
||||||
|
COPY --from=certs /etc/ssl/certs /etc/ssl/certs
|
||||||
|
COPY --from=certs /bin/restic /bin/restic
|
||||||
|
COPY --from=rclone /bin/rclone /bin/rclone
|
||||||
|
|
||||||
|
RUN \
|
||||||
|
mkdir -p /mnt/restic /var/spool/cron/crontabs /var/log; \
|
||||||
|
touch /var/log/cron.log;
|
||||||
|
|
||||||
ENV RESTIC_REPOSITORY=/mnt/restic
|
ENV RESTIC_REPOSITORY=/mnt/restic
|
||||||
ENV RESTIC_PASSWORD=""
|
ENV RESTIC_PASSWORD=""
|
||||||
ENV RESTIC_TAG=""
|
ENV RESTIC_TAG=""
|
||||||
ENV NFS_TARGET=""
|
ENV NFS_TARGET=""
|
||||||
# By default backup every 6 hours
|
ENV BACKUP_CRON="0 */6 * * *"
|
||||||
ENV BACKUP_CRON="* */6 * * *"
|
|
||||||
ENV RESTIC_FORGET_ARGS=""
|
ENV RESTIC_FORGET_ARGS=""
|
||||||
|
ENV RESTIC_JOB_ARGS=""
|
||||||
|
ENV MAILX_ARGS=""
|
||||||
|
|
||||||
# /data is the dir where you have to put the data to be backed up
|
# /data is the dir where you have to put the data to be backed up
|
||||||
VOLUME /data
|
VOLUME /data
|
||||||
|
|
||||||
COPY backup.sh /bin/backup
|
COPY backup.sh /bin/backup
|
||||||
RUN chmod +x /bin/backup
|
|
||||||
|
|
||||||
COPY entry.sh /entry.sh
|
COPY entry.sh /entry.sh
|
||||||
|
|
||||||
RUN touch /var/log/cron.log
|
|
||||||
|
|
||||||
WORKDIR "/"
|
WORKDIR "/"
|
||||||
|
|
||||||
#ENTRYPOINT ["ls"]
|
|
||||||
ENTRYPOINT ["/entry.sh"]
|
ENTRYPOINT ["/entry.sh"]
|
||||||
|
CMD ["tail","-fn0","/var/log/cron.log"]
|
||||||
|
|||||||
40
README.md
40
README.md
@@ -4,21 +4,23 @@ A docker container to automate [restic backups](https://restic.github.io/)
|
|||||||
This container runs restic backups in regular intervals.
|
This container runs restic backups in regular intervals.
|
||||||
|
|
||||||
* Easy setup and maintanance
|
* Easy setup and maintanance
|
||||||
* Support for different targets (currently: Local, NFS, SFTP)
|
* Support for different targets (tested with: Local, NFS, SFTP, AWS)
|
||||||
* Support `restic mount` inside the container to browse the backup files
|
* Support `restic mount` inside the container to browse the backup files
|
||||||
|
|
||||||
**Container**: [lobaro/restic-backup-docker](https://hub.docker.com/r/lobaro/restic-backup-docker/)
|
**Container**: [lobaro/restic-backup-docker](https://hub.docker.com/r/lobaro/restic-backup-docker/)
|
||||||
|
|
||||||
Stable
|
Stable
|
||||||
```
|
```
|
||||||
docker pull lobaro/restic-backup-docker:v1.0
|
docker pull lobaro/restic-backup-docker:1.2-0.9.4
|
||||||
```
|
```
|
||||||
|
|
||||||
Latest (experimental)
|
Latest (experimental)
|
||||||
```
|
```
|
||||||
docker pull lobaro/restic-backup-docker
|
docker pull lobaro/restic-backup-docker:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Please don't hesitate to report any issue you find. **Thanks.**
|
||||||
|
|
||||||
# Test the container
|
# Test the container
|
||||||
|
|
||||||
Clone this repository
|
Clone this repository
|
||||||
@@ -48,7 +50,7 @@ To enter your container execute
|
|||||||
docker exec -ti backup-test /bin/sh
|
docker exec -ti backup-test /bin/sh
|
||||||
```
|
```
|
||||||
|
|
||||||
Now you can use restic [as documented](https://restic.readthedocs.io/en/stable/Manual/), e.g. try to run `restic snapshots` to list all your snapshots.
|
Now you can use restic [as documented](https://restic.readthedocs.io/en/stable/), e.g. try to run `restic snapshots` to list all your snapshots.
|
||||||
|
|
||||||
## Logfiles
|
## Logfiles
|
||||||
Logfiles are inside the container. If needed you can create volumes for them.
|
Logfiles are inside the container. If needed you can create volumes for them.
|
||||||
@@ -58,7 +60,7 @@ docker logs
|
|||||||
```
|
```
|
||||||
Shows `/var/log/cron.log`
|
Shows `/var/log/cron.log`
|
||||||
|
|
||||||
Additionally you can see the the full log, including restic output, of the last execution in `/var/log/backup-last.log`. When the backup fails the log is copied to `/var/log/restic-error-last.log`.
|
Additionally you can see the the full log, including restic output, of the last execution in `/var/log/backup-last.log`. When the backup fails the log is copied to `/var/log/restic-error-last.log`. If configured, you can find the full output of the mail notification in `/var/log/mail-last.log`.
|
||||||
|
|
||||||
# Customize the Container
|
# Customize the Container
|
||||||
|
|
||||||
@@ -66,12 +68,16 @@ The container is setup by setting [environment variables](https://docs.docker.co
|
|||||||
|
|
||||||
## Environment variables
|
## Environment variables
|
||||||
|
|
||||||
* `RESTIC_REPOSITORY` - the location of the restic repository. Default `/mnt/restic`
|
* `RESTIC_REPOSITORY` - the location of the restic repository. Default `/mnt/restic`. For S3: `s3:https://s3.amazonaws.com/BUCKET_NAME`
|
||||||
* `RESTIC_PASSWORD` - the password for the restic repository. Will also be used for restic init during first start when the repository is not initialized.
|
* `RESTIC_PASSWORD` - the password for the restic repository. Will also be used for restic init during first start when the repository is not initialized.
|
||||||
* `RESTIC_TAG` - Optional. To tag the images created by the container.
|
* `RESTIC_TAG` - Optional. To tag the images created by the container.
|
||||||
* `NFS_TARGET` - Optional. If set the given NFS is mounted, i.e. `mount -o nolock -v ${NFS_TARGET} /mnt/restic`. `RESTIC_REPOSITORY` must remain it's default value!
|
* `NFS_TARGET` - Optional. If set the given NFS is mounted, i.e. `mount -o nolock -v ${NFS_TARGET} /mnt/restic`. `RESTIC_REPOSITORY` must remain it's default value!
|
||||||
* `BACKUP_CRON` - A cron expression to run the backup. Default: `* */6 * * *` aka every 6 hours.
|
* `BACKUP_CRON` - A cron expression to run the backup. Note: cron daemon uses UTC time zone. Default: `0 */6 * * *` aka every 6 hours.
|
||||||
* `RESTIC_FORGET_ARGS` - Optional. Only if specified `restic forget` is run with the given arguments after each backup. Example value: `-e "RESTIC_FORGET_ARGS=--prune --keep-last 10 --keep-hourly 24 --keep-daily 7 --keep-weekly 52 --keep-monthly 120 --keep-yearly 100"`
|
* `RESTIC_FORGET_ARGS` - Optional. Only if specified `restic forget` is run with the given arguments after each backup. Example value: `-e "RESTIC_FORGET_ARGS=--prune --keep-last 10 --keep-hourly 24 --keep-daily 7 --keep-weekly 52 --keep-monthly 120 --keep-yearly 100"`
|
||||||
|
* `RESTIC_JOB_ARGS` - Optional. Allows to specify extra arguments to the back up job such as limiting bandwith with `--limit-upload` or excluding file masks with `--exclude`.
|
||||||
|
* `AWS_ACCESS_KEY_ID` - Optional. When using restic with AWS S3 storage.
|
||||||
|
* `AWS_SECRET_ACCESS_KEY` - Optional. When using restic with AWS S3 storage.
|
||||||
|
* `MAILX_ARGS` - Optional. If specified, the content of `/var/log/backup-last.log` is sent via mail after each backup using an *external SMTP*. To have maximum flexibility, you have to specify the mail/smtp parameters by your own. Have a look at the [mailx manpage](https://linux.die.net/man/1/mailx) for further information. Example value: `-e "MAILX_ARGS=-r 'from@example.de' -s 'Result of the last restic backup run' -S smtp='smtp.example.com:587' -S smtp-use-starttls -S smtp-auth=login -S smtp-auth-user='username' -S smtp-auth-password='password' 'to@example.com'"`.
|
||||||
|
|
||||||
## Volumes
|
## Volumes
|
||||||
|
|
||||||
@@ -79,11 +85,11 @@ The container is setup by setting [environment variables](https://docs.docker.co
|
|||||||
|
|
||||||
## Set the hostname
|
## Set the hostname
|
||||||
|
|
||||||
Since restic saves the hostname with each snapshot and the hostname of a docker container is it's id you might want to customize this by setting the hostname of the container to another value.
|
Since restic saves the hostname with each snapshot and the hostname of a docker container is derived from it's id you might want to customize this by setting the hostname of the container to another value.
|
||||||
|
|
||||||
Either by setting the [environment variable](https://docs.docker.com/engine/reference/run/#env-environment-variables) `HOSTNAME` or with `--hostname` in the [network settings](https://docs.docker.com/engine/reference/run/#network-settings)
|
Either by setting the [environment variable](https://docs.docker.com/engine/reference/run/#env-environment-variables) `HOSTNAME` or with `--hostname` in the [network settings](https://docs.docker.com/engine/reference/run/#network-settings)
|
||||||
|
|
||||||
## Backup to SFTP
|
## Backup via SFTP
|
||||||
|
|
||||||
Since restic needs a **password less login** to the SFTP server make sure you can do `sftp user@host` from inside the container. If you can do so from your host system, the easiest way is to just mount your `.ssh` folder conaining the authorized cert into the container by specifying `-v ~/.ssh:/root/.ssh` as argument for `docker run`.
|
Since restic needs a **password less login** to the SFTP server make sure you can do `sftp user@host` from inside the container. If you can do so from your host system, the easiest way is to just mount your `.ssh` folder conaining the authorized cert into the container by specifying `-v ~/.ssh:/root/.ssh` as argument for `docker run`.
|
||||||
|
|
||||||
@@ -93,16 +99,16 @@ Now you can simply specify the restic repository to be an [SFTP repository](http
|
|||||||
-e "RESTIC_REPOSITORY=sftp:user@host:/tmp/backup"
|
-e "RESTIC_REPOSITORY=sftp:user@host:/tmp/backup"
|
||||||
```
|
```
|
||||||
|
|
||||||
# Changelog
|
## Backup via rclone
|
||||||
|
|
||||||
Versioning follows [Semantic versioning](http://semver.org/)
|
To use rclone as a backend for restic, simply add the rclone config file as a volume with `-v /absolute/path/to/rclone.conf:/root/.config/rclone/rclone.conf`.
|
||||||
|
|
||||||
! Breaking changes
|
# Versioning & Changelog
|
||||||
|
|
||||||
**:latest**
|
Starting from v1.3.0 versioning follows [Semantic versioning](http://semver.org/)
|
||||||
* ! `--prune` must be passed to `RESTIC_FORGET_ARGS` to execute prune after forget.
|
|
||||||
* Switch to base Docker container to `golang:1.7-alpine` to support latest restic build.
|
|
||||||
|
|
||||||
|
Build metadata is used to declare the Restic version.
|
||||||
|
|
||||||
**:v1.0**
|
**Example:** 1.3.0+0.9.5 (includes Restic 0.9.5)
|
||||||
* First stable version
|
|
||||||
|
For changelog see: https://github.com/lobaro/restic-backup-docker/releases
|
||||||
|
|||||||
21
backup.sh
Normal file → Executable file
21
backup.sh
Normal file → Executable file
@@ -1,6 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
lastLogfile="/var/log/backup-last.log"
|
lastLogfile="/var/log/backup-last.log"
|
||||||
|
lastMailLogfile="/var/log/mail-last.log"
|
||||||
|
|
||||||
copyErrorLog() {
|
copyErrorLog() {
|
||||||
cp ${lastLogfile} /var/log/backup-error-last.log
|
cp ${lastLogfile} /var/log/backup-error-last.log
|
||||||
@@ -11,16 +12,18 @@ logLast() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
start=`date +%s`
|
start=`date +%s`
|
||||||
rm -f ${lastLogfile}
|
rm -f ${lastLogfile} ${lastMailLogfile}
|
||||||
echo "Starting Backup at $(date +"%Y-%m-%d %H:%M:%S")"
|
echo "Starting Backup at $(date +"%Y-%m-%d %H:%M:%S")"
|
||||||
echo "Starting Backup at $(date)" >> ${lastLogfile}
|
echo "Starting Backup at $(date)" >> ${lastLogfile}
|
||||||
logLast "BACKUP_CRON: ${BACKUP_CRON}"
|
logLast "BACKUP_CRON: ${BACKUP_CRON}"
|
||||||
logLast "RESTIC_TAG: ${RESTIC_TAG}"
|
logLast "RESTIC_TAG: ${RESTIC_TAG}"
|
||||||
logLast "RESTIC_FORGET_ARGS: ${RESTIC_FORGET_ARGS}"
|
logLast "RESTIC_FORGET_ARGS: ${RESTIC_FORGET_ARGS}"
|
||||||
|
logLast "RESTIC_JOB_ARGS: ${RESTIC_JOB_ARGS}"
|
||||||
|
logLast "RESTIC_REPOSITORY: ${RESTIC_REPOSITORY}"
|
||||||
|
logLast "AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}"
|
||||||
|
|
||||||
# Do not save full backup log to logfile but to backup-last.log
|
# Do not save full backup log to logfile but to backup-last.log
|
||||||
restic backup /data --tag=${RESTIC_TAG?"Missing environment variable RESTIC_TAG"} >> ${lastLogfile} 2>&1
|
restic backup /data ${RESTIC_JOB_ARGS} --tag=${RESTIC_TAG?"Missing environment variable RESTIC_TAG"} >> ${lastLogfile} 2>&1
|
||||||
rc=$?
|
rc=$?
|
||||||
logLast "Finished backup at $(date)"
|
logLast "Finished backup at $(date)"
|
||||||
if [[ $rc == 0 ]]; then
|
if [[ $rc == 0 ]]; then
|
||||||
@@ -29,6 +32,7 @@ else
|
|||||||
echo "Backup Failed with Status ${rc}"
|
echo "Backup Failed with Status ${rc}"
|
||||||
restic unlock
|
restic unlock
|
||||||
copyErrorLog
|
copyErrorLog
|
||||||
|
kill 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "${RESTIC_FORGET_ARGS}" ]; then
|
if [ -n "${RESTIC_FORGET_ARGS}" ]; then
|
||||||
@@ -46,4 +50,13 @@ if [ -n "${RESTIC_FORGET_ARGS}" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
end=`date +%s`
|
end=`date +%s`
|
||||||
echo "Finished Backup at $(date +"%Y-%m-%d %H:%M:%S") after $((end-start)) sconds"
|
echo "Finished Backup at $(date +"%Y-%m-%d %H:%M:%S") after $((end-start)) seconds"
|
||||||
|
|
||||||
|
if [ -n "${MAILX_ARGS}" ]; then
|
||||||
|
sh -c "mailx -v -S sendwait ${MAILX_ARGS} < ${lastLogfile} > ${lastMailLogfile} 2>&1"
|
||||||
|
if [ $? == 0 ]; then
|
||||||
|
echo "Mail notification successfully sent."
|
||||||
|
else
|
||||||
|
echo "Sending mail notification FAILED. Check ${lastMailLogfile} for further information."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|||||||
21
config.yml
Normal file
21
config.yml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
schemaVersion: '2.0.0'
|
||||||
|
commandTests:
|
||||||
|
- name: "restic package installation"
|
||||||
|
setup: [["/entry.sh"]]
|
||||||
|
command: "which"
|
||||||
|
args: ["restic"]
|
||||||
|
expectedOutput: ["/bin/restic"]
|
||||||
|
fileExistenceTests:
|
||||||
|
- name: 'log directory exists'
|
||||||
|
path: '/var/log'
|
||||||
|
shouldExist: true
|
||||||
|
- name: 'cron log file exists'
|
||||||
|
path: '/var/log/cron.log'
|
||||||
|
shouldExist: true
|
||||||
|
- name: 'backup script exists'
|
||||||
|
path: '/bin/backup'
|
||||||
|
shouldExist: true
|
||||||
|
metadataTest:
|
||||||
|
volumes: ["/data"]
|
||||||
|
entrypoint: ["/entry.sh"]
|
||||||
|
cmd: ["tail","-fn0", "/var/log/cron.log"]
|
||||||
9
docker-compose.test.yml
Normal file
9
docker-compose.test.yml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
version: '2'
|
||||||
|
|
||||||
|
services:
|
||||||
|
sut:
|
||||||
|
image: gcr.io/gcp-runtimes/container-structure-test
|
||||||
|
command: ["test", "--image", "restic-backup", "--config", "config.yml"]
|
||||||
|
volumes:
|
||||||
|
- ./config.yml:/config.yml
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
27
entry.sh
27
entry.sh
@@ -1,18 +1,37 @@
|
|||||||
#!bin/sh
|
#!bin/sh
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "Starting container ..."
|
echo "Starting container ..."
|
||||||
|
|
||||||
|
RESTIC_CMD=restic
|
||||||
|
|
||||||
|
if [ -n "${ROOT_CERT}" ]; then
|
||||||
|
RESTIC_CMD="${RESTIC_CMD} --cert ${ROOT_CERT}"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -n "${NFS_TARGET}" ]; then
|
if [ -n "${NFS_TARGET}" ]; then
|
||||||
echo "Mounting NFS based on NFS_TARGET: ${NFS_TARGET}"
|
echo "Mounting NFS based on NFS_TARGET: ${NFS_TARGET}"
|
||||||
mount -o nolock -v ${NFS_TARGET} /mnt/restic
|
mount -o nolock -v ${NFS_TARGET} /mnt/restic
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -f "$RESTIC_REPOSITORY/config" ]; then
|
restic snapshots &>/dev/null
|
||||||
|
status=$?
|
||||||
|
echo "Check Repo status $status"
|
||||||
|
|
||||||
|
if [ $status != 0 ]; then
|
||||||
echo "Restic repository '${RESTIC_REPOSITORY}' does not exists. Running restic init."
|
echo "Restic repository '${RESTIC_REPOSITORY}' does not exists. Running restic init."
|
||||||
restic init | true
|
restic init
|
||||||
|
|
||||||
|
init_status=$?
|
||||||
|
echo "Repo init status $init_status"
|
||||||
|
|
||||||
|
if [ $init_status != 0 ]; then
|
||||||
|
echo "Failed to init the repository: '${RESTIC_REPOSITORY}'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
echo "Setup backup cron job with cron expression BACKUP_CRON: ${BACKUP_CRON}"
|
echo "Setup backup cron job with cron expression BACKUP_CRON: ${BACKUP_CRON}"
|
||||||
echo "${BACKUP_CRON} /bin/backup >> /var/log/cron.log 2>&1" > /var/spool/cron/crontabs/root
|
echo "${BACKUP_CRON} /bin/backup >> /var/log/cron.log 2>&1" > /var/spool/cron/crontabs/root
|
||||||
|
|
||||||
@@ -24,4 +43,4 @@ crond
|
|||||||
|
|
||||||
echo "Container started."
|
echo "Container started."
|
||||||
|
|
||||||
tail -fn0 /var/log/cron.log
|
exec "$@"
|
||||||
Reference in New Issue
Block a user