jareware / docker-volume-backup

Utility container for periodically backing up Docker volumes
MIT License
615 stars 88 forks source link

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

Open aonurdemir opened 3 years ago

aonurdemir commented 3 years ago

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.

platanax commented 3 years ago

Hi, I'm also trying to backup a mysql database but I have another issue.

labels:
 - docker-volume-backup.exec-pre-test=mysqldump -u root -p'XXXX' dbname > /tmp/dump/dbname.sql

I have no issue with the ">" character

When I run the ./backup command from the backup container console I get something like :

Pre-exec command: d261578e6e82 mysqldump -u root -p'XXXXX' dbname > /tmp/dump/dbname.sql

mysqldump: Got error: 1045: Access denied for user 'root'@'localhost' (using password: YES) when trying to connect

I tried to run the mysqldump command from the db container's console : it's fine.

Thanks for your help.

aonurdemir commented 3 years ago

Did you try to pass your password without single quotes?

aonurdemir commented 3 years ago

I suppose I am having problems about preventing my shell to interpret '>' instead of passing it to inner shell. The behaviour still continues on both Amazon Linux AMI and MacOS.

Indeed, I suspect the backup container fails to pass the '>' character to the db container while running this: Pre-exec command: 49dcdc0e5875 /usr/bin/mysqldump -u root --password=***** --all-databases > /tmp/mysql.sql. I thnik it is not related to my docker host machine. However @platanax says the command works well. So, I am confused here.

I appreciate any help!

Digging...

platanax commented 3 years ago

Did you try to pass your password without single quotes?

Yes but I have some special chars in the password and it does not work without those :-(

platanax commented 3 years ago

I suppose I am having problems about preventing my shell to interpret '>' instead of passing it to inner shell. The behaviour still continues on both Amazon Linux AMI and MacOS.

Indeed, I suspect the backup container fails to pass the '>' character to the db container while running this: Pre-exec command: 49dcdc0e5875 /usr/bin/mysqldump -u root --password=***** --all-databases > /tmp/mysql.sql. I thnik it is not related to my docker host machine. However @platanax says the command works well. So, I am confused here.

I appreciate any help!

Digging...

Silly suggestion but did you try without the path ?

aonurdemir commented 3 years ago

Thanks anyway :) Yes, I tried. No luck :(

I removed --all-databases and give database name and the problem changed to this:

Pre-exec command: 4a907b4efb38 mysqldump -u root --password=123456* wordpress > /tmp/mysql.sql

mysqldump: [Warning] Using a password on the command line interface can be insecure.
mysqldump: Couldn't find table: ">"

It seems like it interprets > as table name rather than stdout direction. Actually, this explains --all-databases behaviour since it sees > as an argument after--all-databases argument which is a bad usage.

PS: My password contains *. Above is an example of real password.


UPDATE I think we are having this kind of problem:

riker09 commented 1 year ago

Redirecting the output of a command running inside the docker container would require setting the interactive flag on the docker exec command. I believe the issue is explained on StackOverflow.

You are almost there, you just need to add the -i flag to make the pipe work:

-i, --interactive Keep STDIN open even if not attached

docker exec -i container-name mysqldump [options] database > database.sql.xz

I replaced the pipe by a file redirection but it will work the same with a Pipe. Just make sure to don't use the -t option as this will break it.

I'm looking for a way to pg_dump a PostGreSQL database in a similar way:

    labels:
      - docker-volume-backup.exec-pre-backup=pg_dump --dbname=$POSTGRES_DB > /tmp/backup/recipes.pgsql
      - docker-volume-backup.exec-pre-backup=pg_dump --dbname=$POSTGRES_DB > /tmp/backup/recipes.pgsql

But it is throwing "file not found" errors. This is expected, as the path /tmp/backup does not exist on the host but only as a mounted volume inside the container.

riker09 commented 1 year ago

Well, now I feel stupid. I should have read the link above to the end. šŸ˜…

Here's a working configuration:

    labels:
      - docker-volume-backup.exec-pre-backup=sh -c "pg_dump --dbname=$POSTGRES_DB > /tmp/backup/recipes.pgsql"
      - docker-volume-backup.exec-post-backup=rm -rfv /tmp/backup/recipes.pgsql

The trick is to wrap the command in sh -c "{COMMAND}". šŸ‘šŸ»