Giter Club home page Giter Club logo

docker-volume-backup's Introduction

docker-volume-backup

Docker image for performing simple backups of Docker volumes. Main features:

  • Mount volumes into the container, and they'll get backed up
  • Use full cron expressions for scheduling the backups
  • Backs up to local disk, to remote host available via scp, to AWS S3, or to all of them
  • Allows triggering a backup manually if needed
  • Optionally stops containers for the duration of the backup, and starts them again afterward, to ensure consistent backups
  • Optionally docker execs commands before/after backing up a container, to allow easy integration with database backup tools, for example
  • Optionally executes commands before/after backing up inside docker-volume-backup container and/or on remote host
  • Optionally ships backup metrics to InfluxDB, for monitoring
  • Optionally encrypts backups with gpg before uploading

Examples

Backing up locally

Say you're running some dashboards with Grafana and want to back them up:

version: "3"

services:

  dashboard:
    image: grafana/grafana:7.4.5
    volumes:
      - grafana-data:/var/lib/grafana           # This is where Grafana keeps its data

  backup:
    image: jareware/docker-volume-backup
    volumes:
      - grafana-data:/backup/grafana-data:ro    # Mount the Grafana data volume (as read-only)
      - ./backups:/archive                      # Mount a local folder as the backup archive

volumes:
  grafana-data:

This will back up the Grafana data volume, once per day, and write it to ./backups with a filename like backup-2018-11-27T16-51-56.tar.gz.

Backing up to S3

Off-site backups are better, though:

version: "3"

services:

  dashboard:
    image: grafana/grafana:7.4.5
    volumes:
      - grafana-data:/var/lib/grafana           # This is where Grafana keeps its data

  backup:
    image: jareware/docker-volume-backup
    environment:
      AWS_S3_BUCKET_NAME: my-backup-bucket      # S3 bucket which you own, and already exists
      AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}   # Read AWS secrets from environment (or a .env file)
      AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
    volumes:
      - grafana-data:/backup/grafana-data:ro    # Mount the Grafana data volume (as read-only)

volumes:
  grafana-data:

This configuration will back up to AWS S3 instead. See below for additional tips about S3 Bucket setup.

Restoring from S3

Downloading backups from S3 can be done however you usually interact with S3, e.g. via the aws s3 CLI or the AWS Web Console.

However, if you're on the host that's running this image, you can also download the latest backup with:

$ docker-compose exec -T backup bash -c 'aws s3 cp s3://$AWS_S3_BUCKET_NAME/$BACKUP_FILENAME -' > restore.tar.gz

From here on out the restore process will depend on a variety of things, like whether you've encrypted the backups, how your volumes are configured, and what application it is exactly that you're restoring.

But for the sake of example, to finish the restore for the above Grafana setup, you would:

  1. Extract the contents of the backup, with e.g. tar -xf restore.tar.gz. This would leave you with a new directory called backup in the current dir.
  2. Figure out the mount point of the grafana-data volume, with e.g. docker volume ls and then docker volume inspect. Let's say it ends up being /var/lib/docker/volumes/bla-bla/_data. This is where your live Grafana keeps its data on the host file system.
  3. Stop Grafana, with docker-compose stop dashboard.
  4. Move any existing data aside, with e.g. sudo mv /var/lib/docker/volumes/bla-bla/_data{,_replaced_during_restore}. You can also just remove it, if you like to live dangerously.
  5. Move the backed up data to where the live Grafana can find it, with e.g. sudo cp -r backup/grafana-data /var/lib/docker/volumes/bla-bla/_data.
  6. Depending on the Grafana version, you may need to set some permissions manually, e.g. sudo chown -R 472:472 /var/lib/docker/volumes/bla-bla/_data.
  7. Start Grafana back up, with docker-compose start dashboard. Your Grafana instance should now have travelled back in time to its latest backup.

Backing up to remote host by means of SCP

You can also upload to your backups to a remote host by means of secure copy (SCP) based on SSH. To do so, create an SSH key pair if you do not have one yet and copy the public key to the remote host where your backups should be stored. Then, start the backup container by setting the variables SCP_HOST, SCP_USER, SCP_DIRECTORY, and provide the private SSH key by mounting it into /ssh/id_rsa.

In the example, we store the backups in the remote host folder /home/pi/backups and use the default SSH key located at ~/.ssh/id_rsa:

version: "3"

services:

  dashboard:
    image: grafana/grafana:7.4.5
    volumes:
      - grafana-data:/var/lib/grafana           # This is where Grafana keeps its data

  backup:
    image: jareware/docker-volume-backup
    environment:
      SCP_HOST: 192.168.0.42                    # Remote host IP address
      SCP_USER: pi                              # Remote host user to log in
      SCP_DIRECTORY: /home/pi/backups           # Remote host directory
    volumes:
      - grafana-data:/backup/grafana-data:ro    # Mount the Grafana data volume (as read-only)
      - ~/.ssh/id_rsa:/ssh/id_rsa:ro            # Mount the SSH private key (as read-only)

volumes:
  grafana-data:

Triggering a backup manually

Sometimes it's useful to trigger a backup manually, e.g. right before making some big changes.

This is as simple as:

$ docker-compose exec backup ./backup.sh

[INFO] Backup starting

8 containers running on host in total
1 containers marked to be stopped during backup

...
...
...

[INFO] Backup finished

Will wait for next scheduled backup

If you only want to back up manually (i.e. not on a schedule), you should either:

  1. Run the image without docker-compose, override the image entrypoint to /root/backup.sh, and ensure you match your env-vars with what the default src/entrypoint.sh would normally set up for you, or
  2. Just use BACKUP_CRON_EXPRESSION="#" (to ensure scheduled backup never runs) and execute docker-compose exec backup ./backup.sh whenever you want to run a backup

Stopping containers while backing up

It's not generally safe to read files to which other processes might be writing. You may end up with corrupted copies.

You can give the backup container access to the Docker socket, and label any containers that need to be stopped while the backup runs:

version: "3"

services:

  dashboard:
    image: grafana/grafana:7.4.5
    volumes:
      - grafana-data:/var/lib/grafana           # This is where Grafana keeps its data
    labels:
      # Adding this label means this container should be stopped while it's being backed up:
      - "docker-volume-backup.stop-during-backup=true"

  backup:
    image: jareware/docker-volume-backup
    environment:
      AWS_S3_BUCKET_NAME: my-backup-bucket      # S3 bucket which you own, and already exists
      AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}   # Read AWS secrets from environment (or a .env file)
      AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro # Allow use of the "stop-during-backup" feature
      - grafana-data:/backup/grafana-data:ro    # Mount the Grafana data volume (as read-only)

volumes:
  grafana-data:

This configuration allows you to safely back up things like databases, if you can tolerate a bit of downtime.

Pre/post backup exec

If you don't want to stop the container while it's being backed up, and the container comes with a backup utility (this is true for most databases), you can label the container with commands to run before/after backing it up:

version: "3"

services:

  database:
    image: influxdb:1.5.4
    volumes:
      - influxdb-data:/var/lib/influxdb         # This is where InfluxDB keeps its data
      - influxdb-temp:/tmp/influxdb             # This is our temp space for the backup
    labels:
      # These commands will be exec'd (in the same container) before/after the backup starts:
      - docker-volume-backup.exec-pre-backup=influxd backup -portable /tmp/influxdb
      - docker-volume-backup.exec-post-backup=rm -rfv /tmp/influxdb

  backup:
    image: jareware/docker-volume-backup
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro # Allow use of the "pre/post exec" feature
      - influxdb-temp:/backup/influxdb:ro       # Mount the temp space so it gets backed up
      - ./backups:/archive                      # Mount a local folder as the backup archive

volumes:
  influxdb-data:
  influxdb-temp:

The above configuration will perform a docker exec for the database container with influxd backup, right before the backup runs. The resulting DB snapshot is written to a temp volume (influxdb-temp), which is then backed up. Note that the main InfluxDB data volume (influxdb-data) isn't used at all, as it'd be unsafe to read while the DB process is running.

Similarly, after the temp volume has been backed up, it's cleaned up with another docker exec in the database container, this time just invoking rm.

If you need a more complex script for pre/post exec, consider mounting and invoking a shell script instead.

Configuration

Variable Default Notes
BACKUP_SOURCES /backup Where to read data from. This can be a space-separated list if you need to back up multiple paths, when mounting multiple volumes for example. On the other hand, you can also just mount multiple volumes under /backup to have all of them backed up.
BACKUP_CRON_EXPRESSION @daily Standard debian-flavored cron expression for when the backup should run. Use e.g. 0 4 * * * to back up at 4 AM every night. See the man page or crontab.guru for more.
BACKUP_FILENAME backup-%Y-%m-%dT%H-%M-%S.tar.gz File name template for the backup file. Is passed through date for formatting. See the man page for more.
BACKUP_ARCHIVE /archive When this path is available within the container (i.e. you've mounted a Docker volume there), a finished backup file will get archived there after each run.
PRE_BACKUP_COMMAND Commands that is executed before the backup is created.
POST_BACKUP_COMMAND Commands that is executed after the backup has been transferred.
BACKUP_UID root (0) After backup file has been moved to archive location the file user ownership is changed to this UID.
BACKUP_GID $BACKUP_UID After backup file has been moved to archive location the file group ownership is changed to this GID.
BACKUP_WAIT_SECONDS 0 The backup script will sleep this many seconds between re-starting stopped containers, and proceeding with archiving/uploading the backup. This can be useful if you don't want the load/network spike of a large upload immediately after the load/network spike of container startup.
BACKUP_HOSTNAME $(hostname) Name of the host (i.e. Docker container) in which the backup runs. Mostly useful if you want a specific hostname to be associated with backup metrics (see InfluxDB support).
BACKUP_CUSTOM_LABEL When provided, the start/stop and pre/post exec logic only applies to containers with this custom label.
CHECK_HOST When provided, the availability of the named host will be checked. The host should be the destination host of the backups. If the host is available, the backup is conducted as normal. Else, the backup is skipped.
AWS_S3_BUCKET_NAME When provided, the resulting backup file will be uploaded to this S3 bucket after the backup has ran. You may include slashes after the bucket name if you want to upload into a specific path within the bucket, e.g. your-bucket-name/backups/daily.
AWS_GLACIER_VAULT_NAME When provided, the resulting backup file will be uploaded to this AWS Glacier vault after the backup has ran.
AWS_ACCESS_KEY_ID Required when using AWS_S3_BUCKET_NAME.
AWS_SECRET_ACCESS_KEY Required when using AWS_S3_BUCKET_NAME.
AWS_DEFAULT_REGION Optional when using AWS_S3_BUCKET_NAME. Allows you to override the AWS CLI default region. Usually not needed.
AWS_EXTRA_ARGS Optional additional args for the AWS CLI. Useful for e.g. providing --endpoint-url <url> for S3-compatible systems, such as DigitalOcean Spaces, MinIO and the like.
SCP_HOST When provided, the resulting backup file will be uploaded by means of scp to the host stated.
SCP_USER User name to log into SCP_HOST.
SCP_DIRECTORY Directory on SCP_HOST where backup file is stored.
PRE_SCP_COMMAND Commands that is executed on SCP_HOST before the backup is transferred.
POST_SCP_COMMAND Commands that is executed on SCP_HOST after the backup has been transferred.
GPG_PASSPHRASE When provided, the backup will be encrypted with gpg using this passphrase.
INFLUXDB_URL Required when sending metrics to InfluxDB.
INFLUXDB_MEASUREMENT docker_volume_backup Required when sending metrics to InfluxDB.
INFLUXDB_API_TOKEN When provided, backup metrics will be sent to an InfluxDB instance using the API token for authorization. If API Tokens are not supported by the InfluxDB version in use, INFLUXDB_CREDENTIALS must be provided instead.
INFLUXDB_ORGANIZATION Required when using INFLUXDB_API_TOKEN; e.g. personal.
INFLUXDB_BUCKET Required when using INFLUXDB_API_TOKEN; e.g. backup_metrics
INFLUXDB_CREDENTIALS When provided, backup metrics will be sent to an InfluxDB instance using user:password authentication. This is required if INFLUXDB_API_TOKEN not provided.
INFLUXDB_DB Required when using INFLUXDB_URL; e.g. my_database.
TZ UTC Which timezone should cron use, e.g. America/New_York or Europe/Warsaw. See full list of available time zones.

Metrics

After the backup, the script will collect some metrics from the run. By default, they're just written out as logs. For example:

docker_volume_backup
host=my-demo-host
size_compressed_bytes=219984
containers_total=4
containers_stopped=1
time_wall=61.6939337253571
time_total=1.69393372535706
time_compress=0.171068429946899
time_upload=0.56016993522644

If so configured, they can also be shipped to an InfluxDB instance. This allows you to set up monitoring and/or alerts for them. Here's a sample visualization on Grafana:

Backup dashboard sample

Automatic backup rotation

You probably don't want to keep all backups forever. A more common strategy is to hold onto a few recent ones, and remove older ones as they become irrelevant. There's no built-in support for this in docker-volume-backup, but you are able to trigger an external Docker container that includes rotate-backups. In the examples, we draw on docker-rotate-backups.

In order to start an external Docker container, access to docker.sock has to be granted (as already seen in in the section on stopping containers while backing up). Then, docker-rotate-backups can be run on local directories as well as on remote directories.

The default rotation scheme implemented in docker-rotate-backups preserves seven daily, four weekly, twelve monthly, and every yearly backups. For detailed information on customizing the rotation scheme, we refer to the documentation.

Rotation for local backups

Let /home/pi/backups be the path to your local backups. Then, initialize the environmental variable POST_BACKUP_COMMAND with the following command.

environment:
  POST_BACKUP_COMMAND: "docker run --rm -e DRY_RUN=false -v /home/pi/backups:/archive ghcr.io/jan-brinkmann/docker-rotate-backups"
volumes:
  - /var/run/docker.sock:/var/run/docker.sock:ro
  - /home/pi/backups:/archive

Rotation for backups tranferred via SCP

Here, let /home/pi/backups be the backup directory on a remote host. To run docker-rotate-backups on that directory, the command in POST_BACKUP_COMMAND has to include all necessary information in order to access the remote host by means of SSH. Remember, if you transfer your backups by means of SCP, all information in SSH_USER, SSH_HOST, SSH_ARCHIVE, and the SSH public key are already available.

environment:
  SCP_HOST: 192.168.0.42
  SCP_USER: pi
  SCP_DIRECTORY: /path/to/backups
  POST_BACKUP_COMMAND: "docker run --rm -e DRY_RUN=false -e SSH_USER=pi -e SSH_HOST=192.168.0.42 -e SSH_ARCHIVE=/home/pi/backups -v /home/pi/.ssh/id_rsa:/root/.ssh/id_rsa:ro ghcr.io/jan-brinkmann/docker-rotate-backups"
volumes:
  - /var/run/docker.sock:/var/run/docker.sock:ro
  - /home/pi/.ssh/id_rsa:/ssh/id_rsa:ro

Rotation for S3 backups

Amazon S3 has Versioning and Object Lifecycle Management features that can be useful for backups.

First, you can enable versioning for your backup bucket:

S3 versioning

Then, you can change your backup filename to a static one, for example:

environment:
  BACKUP_FILENAME: latest.tar.gz

This allows you to retain previous versions of the backup file, but the most recent version is always available with the same filename:

$ aws s3 cp s3://my-backup-bucket/latest.tar.gz .
download: s3://my-backup-bucket/latest.tar.gz to ./latest.tar.gz

To make sure your bucket doesn't continue to grow indefinitely, you can enable some lifecycle rules:

S3 lifecycle

These rules will:

  • Move non-latest backups to a cheaper, long-term storage class (Glacier)
  • Permanently remove backups after a year
  • Still always keep the latest backup available (even after a year has passed)

Testing

A bunch of test cases exist under test. To run them:

cd test/backing-up-locally/
docker-compose stop && docker-compose rm -f && docker-compose build && docker-compose up

Some cases may need secrets available in the environment, e.g. for S3 uploads to work.

Releasing

  1. Draft a new release on GitHub
  2. docker buildx build --platform linux/amd64,linux/arm64 -t jareware/docker-volume-backup:latest --push .
  3. docker buildx build --platform linux/amd64,linux/arm64 -t jareware/docker-volume-backup:x.y.z --push .

docker-volume-backup's People

Contributors

bacluc avatar ercpereda avatar jan-brinkmann avatar jareware avatar leny1996 avatar makeri89 avatar tekgator avatar varhub avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

docker-volume-backup's Issues

Container exits successfully even if s3 upload fails

Hi, thanks for this project. Here's an issue I recently found. If the AWS upload fails for some reason (e.g., bad credentials), the backup script still proceeds as if nothing happened.

Here's an example where I intentionally messed up the AWS credentials:

[INFO] Uploading backup to S3

Will upload to bucket "***-backups"
upload failed: ./***-2022-11-27T17-47-09.tar.gz to s3://***-backups/***-2022-11-27T17-47-09.tar.gz An error occurred (SignatureDoesNotMatch) when calling the PutObject operation: The request signature we calculated does not match the signature you provided. Check your key and signing method.
Upload finished

...

[INFO] Backup finished

Will wait for next scheduled backup

It seems to be the expected behavior should be to fail the script.

Rotate Backups

Hey @jareware,

things addressing rotate backups got a little bit messy. That's why I open this issue to summarize what we currently have and to discuss what we want to have.

  • Since v2.5.0, we are enabled to upload backups by means of scp to a remote host and to make use of POST_SCP_COMMAND in order to execute rotate-backups directly on that remote host. Here, we have to overhand the complete configuration, e.g., POST_SCP_COMMAND: rotate-backups --daily 7 --weekly 4 --monthly 12 --yearly always /backup-directory.
  • We have #42 where we, again, execute rotate-backups directly on the remote host where we upload our backup to by means of scp. Unlike in the first option, we have a default configuration that can be customized by environmental varibales ROTATE_DAILY and so on.
  • We have #36 where we are enabled to execute rotate-backups directly inside the container on the directoy /archive. A default configuration ist given by a .rotate-backups.ini file . A custom configuration file can be mounted.

Here are my thoughts about all these stuff:

  • If we like to make use of rotate-backups without scp, we need an external solution (e.g., cron job outside of the container) or we #36.
  • All three option handle customizing configuration in some own way. Imho, it would be nice to overhand configuration in some common way. As POST_SCP_COMMAND takes some arbitrary command, we cannot improve anything here. But #42 provides most likely the most easy way to customize the configuration. These way can also used in #36. That would result in a much better user experience.
  • #36 increases the image size from round about 600MB to 900MB (on ARM64). Installing rotate-backups at runtime, if it has been activated, is not a nice idea because the package itself and some dependencies have to be downloaded everytime the container has been removed and restarted (e.g., by docker-compose down followed by docker-compose up -d).
  • If we do not merge #36, we definitely do not need #42 because the functionality is already there.

As far as I see, the first question that has to be answered is if #36 can be merged. In order to reduce the image size, maybe we can draw on #27. In the end, maybe we end up by the same image size we currently have.

What do you think?

Regards,
Jan

Cron is always in UTC

Hi,

thanks for great tool but I found out there is a small problem with setting cron expressions. I'm in UTC+2h and have set the backup to run at 4 AM.
I've also set up Influx metrics and found out that it actually runs at 6 AM instead of 4 AM. Timestamps of created backups confirm it's 6 AM.
After a while I've figured out that the container is running always in UTC timezone (looks like it's a Docker default - my other containers run on UTC as well). Not a big deal for people in Europe but imagine someone in Australia thinking his backups are created at night while in fact they are created in the middle of the day.

Anyone got the same? (see the results of docker exec -it <container_name> date command)

Ability to execute once immediately

Some workflows may want to execute the backup once immediately as opposed to on a cron schedule. I didn't see a way to do this as-is, but seems like it could be pretty easy to configure via an alternative entrypoint, or configuring the entrypoint to only do the initialization and then defaulting to the cron command but allowing an override command.

add restore backup instructions

Hi

I'm sure I can figure them out but I think would be beneficial to add restore steps in the readme

so people can jump in this git project do an quick test BACKUP/Restore and give it a thumbs up

Cheers ๐Ÿ‘

TZ env var doesn't work due to tzdata package missing

Currently setting TZ="Australia/Melbourne" has no effect on the containers timezone due to the tzdata package missing.

Before:

root@grafana-backup:~# TZ="Australia/Melbourne" date
Sun Feb  6 03:14:14 Australia 2022
root@grafana-backup:~# TZ="UTC" date
Sun Feb  6 03:14:23 UTC 2022

After tzdata install:

root@grafana-backup:~# TZ="Australia/Melbourne" date
Sun Feb  6 14:15:11 AEDT 2022
root@grafana-backup:~# TZ="UTC" date
Sun Feb  6 03:15:16 UTC 2022

Could we please add this to the container image/setup so we don't have to specify the cron expression as UTC?

error: gpg not found on container

When setting GPG_PASSPHRASE environment variable, I'm unable to do the backup due to the error that the gpg is not installed on the base machine.

The error shown on the terminal is:

./backup.sh: line 79: gpg: command not found

I'm trying to do the backup manually with docker compose exec backup ./backup.sh

awscli v2 break raspberry pi usage

Since this commit 074f2e7, the cli the image is using rolled forward to v2.

This image no longer works on raspberry pi.

I verified this by checking out v2.1.0 tag and rebuild the image locally -> working.
checking out v2.3.0 tag and rebuild the image locally -> ./backup.sh: line 95: /usr/bin/aws: cannot execute binary file: Exec format error

Is there a particular reason to move to v2 already? Maybe wait for AWS to release them in package manager? ref: aws/aws-cli#4947 (comment)


Docker hub doesn't have an arm build is also a problem but I guess I'll save it for now. (is it #5?)


BTW thanks for this great repo, I've researched a bit and by far this is the most satisfying despite the arm related issue.

arm64 support

Hi

I like your project. I have few containers running arm64 based machines. Can you add arm64 support please?

Use Swarm Secrets for receive AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY

Currently S3 documentation with compose file reports:

AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}   # Read AWS secrets from environment (or a .env file)
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}

but .env file is not supported with a Stack deployment over Swarm. Instead, Swarm implements Secrets that would be a better solution for security purpose.

Use of them have to be implemented with the application, reading for example from /run/secrets/aws_access_key_id and /run/secrets/aws_secret_access_key, because secrets are not injectable directly from docker-stack.yml into environemnt.

Add support for reporting metrics to Influx API v2

As far as I can tell setting the environment variables for configuring reporting metrics to an InfluxDB instance are only working with the older v1 API.

It would probably the easiest to support the newer v2 API by adding some new env vars:

  • INFLUXDB2_URL
  • INFLUXDB2_BUCKET
  • INFLUXDB2_ORG and/or INFLUXDB2_ORGID

I'm not sure if the data can still be written with the curl parameter --data-binary. In a quick test --data-raw did seam to to work, though.

Documentation:
https://docs.influxdata.com/influxdb/v1.8/guides/write_data/#write-data-using-the-influxdb-api
https://docs.influxdata.com/influxdb/v2.6/api/#operation/PostWrite

Pre Backup Command for MySQL with ">" character does not work

docker-compose.yml (simplified for clearity):

version: "3"

services:
  ... other services
  database:
    image: mysql:8.0
    container_name: db
    volumes:
      - dbdata:/var/lib/mysql
      - dbtemp:/tmp/mysql
    labels:
      # These commands will be exec'd (in the same container) before/after the backup starts:
      - docker-volume-backup.exec-pre-backup=/usr/bin/mysqldump -u root --password=$MYSQL_ROOT_PASSWORD --all-databases > /tmp/mysql.sql
      - docker-volume-backup.exec-post-backup=rm -rfv /tmp/mysql.sql

  backup:
    image: futurice/docker-volume-backup:2.0.0
    container_name: backup
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro # Allow use of the "pre/post exec" feature
      - dbtemp:/backup/mysql.sql:ro       # Mount the temp space so it gets backed up
      - ./backups:/archive                      # Mount a local folder as the backup archive

volumes:
  dbdata:
  dbtemp:

When I run this command: docker compose exec backup ./backup.sh

I get this:

[INFO] Pre-exec command: 49dcdc0e5875 /usr/bin/mysqldump -u root --password=***** --all-databases > /tmp/mysql.sql

mysqldump: [Warning] Using a password on the command line interface can be insecure.
Usage: mysqldump [OPTIONS] database [tables]
OR     mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]
OR     mysqldump [OPTIONS] --all-databases [OPTIONS]
For more options, use mysqldump --help

When I change pre-backup command by removing ">" character and the file, it dumps all sql to stdout and works well. However, it is useless to print all sql to stdout.

I am not sure this a bug of this repository or docker.

I appreciate any help. Thanks in advance.

Notification

Hi, is it possible to add notification (like apprise integration) after every failed/success backup? Thank you

docker: command not found

Recently, I noticed that the docker command is not available anymore when using it in POST_BACKUP_COMMAND:

/root/backup.sh: line 151: docker: command not found

@varhub, @jareware, is this in relation to #53?

manifest for jareware/docker-volume-backup not found: manifest unknown

When following your very first example from README or trying to manually pull docker-volume-backup the result is:

# docker pull jareware/docker-volume-backup
Using default tag: latest
Error response from daemon: manifest for jareware/docker-volume-backup:latest not found: manifest unknown: manifest unknown

Anybody there?

Hi,

is still anybody there maintaining this project?
There are a number of pull request that need to be done.

Regards
Jan

Support local S3

Hi, I use minio on my NAS to have S3 bucket in my LAN

Can you consider to support other S3 providers and local S3?

Thank you

Stopping containers during backup that are part of a stack replicates containers

What's the recommended way to prevent containers that are part of a service and stopped during backup from restarting and effectively scaling up those services?

i.e. PGADMIN service is stopped during backup, backup takes place, after backup is complete I now have 2 instances of PGADMIN service running when I only require 1

multiple vols on one container

hello,

How would you suggest I backup multiple volumes of one container? I have a container with 8 volumes defined. I would like to backup the image and volumes and restore from image and apply the volume backups. Does this sound feasible?

Thanks!

Include option to filter pre/post-exec containers

There should be option in env variable to select container to exec commands.
Now if I have two containers with pre/post-exec labels and I want different scheduling for them, it's calling commands on both of containers when any backup container cron is called.

There are two options:

  1. Provide regex expression in environment variable
  2. Provide custom label and then provide labels in service config, like command exec

Manifest Unknown when trying to pull docker container

Hello,

When I try to pull the container of this program for local testing, I get this:

docker pull jareware/docker-volume-backup
Using default tag: latest
Error response from daemon: manifest for jareware/docker-volume-backup:latest not found: manifest unknown: manifest unknown

This error also occurs when trying to use the image from a docker-compose file.

Add option to define labels per specific stack

I think it is a good idea to add possibility to define labels per specific stack. At the moment when multiple stacks are suing the exec-pre-backup and exec-post-backup labels then all commands are executed. For example lets say we have this two stacks:

mattermost:

version: "3.3"
...
services:
...
  db:
    image: postgres
    restart: unless-stopped
    volumes:
      - pgdata:/var/lib/postgresql/data
      - tmp:/tmp/
    environment:
      - POSTGRES_USER=mmuser
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=mattermost
    networks:
      - internal
    labels:
      - docker-volume-backup.exec-pre-backup=pg_dumpall -U mmuser -f /tmp/mattermost.dump
      - docker-volume-backup.exec-post-backup=rm -fv /tmp/mattermost.dump
...

sentry:

version: "3.3"
...
services:
...
  postgres:
    image: postgres
    volumes:
      - pgdata:/var/lib/postgresql/data
      - tmp:/tmp/
    restart: unless-stopped
    environment:
      - POSTGRES_USER: sentry
      - POSTGRES_PASSWORD: password
    networks:
      - internal
    labels:
      - docker-volume-backup.exec-pre-backup=pg_dumpall -U sentry -f /tmp/sentry.dump
      - docker-volume-backup.exec-post-backup=rm -fv /tmp/sentry.dump
...

running the ./backup.sh in the mattermost stack gives following output:

[INFO] Backup starting
...

[INFO] Pre-exec command: 7f23fe144d86 pg_dumpall -U sentry -f /tmp/sentry.dump


[INFO] Pre-exec command: 95a3c4f1ed92 pg_dumpall -U mmuser -f /tmp/mattermost.dump


[INFO] Creating backup

tar: Removing leading `/' from member names
...

which makes two dump of databases, but it should run only the mattermost db backup.

Latest change haven't been pushed to docker hub with proper tag.

Hi, per my investigation, latest change related to BACKUP_CUSTOM_LABEL hasn't been pushed to docker hub yet when pulled from tag latest.
You may want to add latest to the revision 2.3.0

root@58e5fb2cc2b5:~# cat backup.sh
#!/bin/bash

# Cronjobs don't inherit their env, so load from file
source env.sh

function info {
  bold="\033[1m"
  reset="\033[0m"
  echo -e "\n$bold[INFO] $1$reset\n"
}

info "Backup starting"
TIME_START="$(date +%s.%N)"
DOCKER_SOCK="/var/run/docker.sock"
if [ -S "$DOCKER_SOCK" ]; then
  TEMPFILE="$(mktemp)"
  docker ps --format "{{.ID}}" --filter "label=docker-volume-backup.stop-during-backup=true" > "$TEMPFILE"

Issue with writing file to /archive

Hi,

when I'm running command docker-compose exec backup ./backup.sh

it gives me following output:

[INFO] Backup starting

2 containers running on host in total
1 containers marked to be stopped during backup

[INFO] Stopping containers

d8413dc4001b

[INFO] Creating backup

tar: Removing leading `/' from member names
/backup/
/backup/prisma-volume/

[INFO] Starting containers back up

d8413dc4001b

[INFO] Waiting before processing

Sleeping 0 seconds...

[INFO] Archiving backup

copied 'backup-2023-10-30T13-52-57.tar.gz' -> '/archive/backup-2023-10-30T13-52-57.tar.gz'
mv: cannot create regular file '/archive/backup-2023-10-30T13-52-57.tar.gz': No such file or directory

[INFO] Cleaning up

removed 'backup-2023-10-30T13-52-57.tar.gz'

[INFO] Collecting metrics

docker_volume_backup
host=8927feb4ae76
size_compressed_bytes=148
containers_total=2
containers_stopped=1
time_wall=1.05225872993469
time_total=1.05225872993469
time_compress=0.0112252235412598
time_upload=0

[INFO] Backup finished

Will wait for next scheduled backup

The issue is in line: mv: cannot create regular file '/archive/backup-2023-10-30T13-52-57.tar.gz': No such file or directory

Do you maybe know what could be the reason for this issue?

Thank you in advance

mkdir: cannot create directory '.aws': File exists

If I leave this container up for a few days, it will eventually get stuck in a loop, giving this error message:
mkdir: cannot create directory '.aws': File exists

The only way I've found to break it out of this loop is to remove the container completely and create it fresh.

My docker-compose.yml file contains this:

backup:
    image: futurice/docker-volume-backup:2.0.0
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - mongotemp:/backup/mongodb:ro
      - ${BACKUP_DIR}:/archive
    environment:
      - BACKUP_CRON_EXPRESSION=${BACKUP_CRON_EXPRESSION}
    restart: always
mongodb:
    image: mongo:4.2
    ports:
      - "37017:27017"
    volumes:
      - mongodata:/data/db
      - mongotemp:/tmp/mongodb
    labels:
      # First, safely backs up from data to temp using db-specific tool.
      # Then temp is backed up externally.
      - docker-volume-backup.exec-pre-backup=mongodump --archive=/tmp/mongodb/mongo.dump
      - docker-volume-backup.exec-post-backup=rm -rfv /tmp/mongodb
      # Restore backup by cp into mongodb container, $ mongorestore --archive=mongo.dump
    restart: always

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.