Closed mholmesbeatport closed 8 months ago
The problem with rm -rf /var/lib/mysql/**
is it ignore .*
files as below (and see man bash):
$ mkdir mysql
/tmp
$ touch mysql/.my_healthcheck.cnf
/tmp
$ rm -rf mysql/**
/tmp
$ ls -la mysql
total 0
drwxr-xr-x. 2 dan dan 60 Jul 19 13:34 .
drwxrwxrwt. 29 root root 820 Jul 19 13:34 ..
-rw-r--r--. 1 dan dan 0 Jul 19 13:34 .my_healthcheck.cnf
/tmp
$ man rm
/tmp
$ rm -rf mysql/** mysql/.*
/tmp
$ ls -la mysql
total 0
drwxr-xr-x. 2 dan dan 40 Jul 19 13:36 .
drwxrwxrwt. 29 root root 820 Jul 19 13:36 ..
So to remove you'll need rm -rf /var/lib/mysql/** /var/lib/mysql/.*
Alternately enable shopt -s dotglob
like:
$ shopt -s dotglob
/tmp
$ ls -la mysql
total 0
drwxr-xr-x. 2 dan dan 60 Jul 19 13:40 .
drwxrwxrwt. 29 root root 820 Jul 19 13:42 ..
-rw-r--r--. 1 dan dan 0 Jul 19 13:40 .my_healthcheck.cnf
/tmp
$ rm -rf mysql/**
/tmp
$ ls -la mysql
total 0
drwxr-xr-x. 2 dan dan 40 Jul 19 13:42 .
drwxrwxrwt. 29 root root 820 Jul 19 13:42 ..
That said, restoring from a full backup in /docker-entrypoint-initdb.d
is a pretty common use case and requiring users like yourself to script this manual isn't a great experience. You're pretty luck your data fits in /tmp
but larger restores may not be as lucky and --move-back across filesystems is a fully copy again.
If you can come up with a good well known name mariadb-initdb{something}{compressext}
(and format - prepare needs to be already done, so just tar?) that if it exists in /docker-entrypoint-initdb.d
, and the datadir is empty, its used for the database initialization directly.
I also recommend applying prepare to before the backup was made as a version bump on the mariadb container may not support the prepare stage of the previous backup.
@grooverdan thank you for your recommendation. Adding the mysql/.*
to my remove statement has unblocked me.
I appreciate your suggestions on modifying how we are going about the restore of the backup and will look to make the modifications above to improve the process and make it less manual.
Just to ensure I understand the process you are proposing does the following sound correct:
mariadb-initdb-mybackup.tar
)/docker-entrypoint-initdb.d
Let me know if I have misunderstood any steps
Pretty much.
-mybackup
) as it doesn't really make sense to support more than one. (except Aria, maybe, consider later). Or should I just glob *.tar.*
and do them all? Supporting a standard range of compression tools available in container is easy extension, especially with tar --auto-compress
.I think I can use mariadb-backup --move-back
on detection of some mariadb-backup meta files and otherwise just assume its a full datadir.
shopt -s gotglob
for f in *.tar.*; do
mkdir -f $DATADIR/.init
tar --auto-compress -x $f -C --directory=$DATADIR/.init
if [ -f $DATADIR/.init/xtra* ]; then
gosu $USER mariabackup --target-dir=/var/lib/mysql/.init --datadir=/var/lib/mysql/.restore --move-back
mv $DATADIR/.restore/** $DATADIR/
else
mv $DATADIR/.init/** $DATADIR/
chown $USER: -R $DATADIR/
fi
Did you want to try to implement the entrypoint changes and contribute a pull request?
I have not contributed to an open source project before so I would be lying if I didn't say I am a wee bit intimidated by the prospect. But I think I would like to give it a try. I can see it being a really helpful option for a full backup restore. I will read the documentation on getting set up to contribute and get started.
Thanks for being willing. open source contributions require people to make it work. I've just got a few too many commitments this week so won't be able to give time to doing this as soon as you'd like. I really appreciate you trying and are going to test what you have well before it gets merged.
Quick guide from github on mechanics of contributing: https://docs.github.com/en/get-started/quickstart/contributing-to-projects
For this will require a change to the docker-entrypoint.sh on the top of the project.
To build/test this
./update.sh 10.6
docker buildx --tag mtest 10.6
Pick a version your backup relates to. I tend to use buildah --tag mtest 10.6
to the same effect but anything that builds from a Dockerfile.
Do a manual test:
docker run -v /path/to/xxx.tar.gz:/docker-entrypoint-initdb.d:z mtest
An easier to trace version is:
docker run -v /path/to/xxx.tar.gz:/docker-entrypoint-initdb.d:z --user mysql mtest bash -x -v docker-entrypoint.sh
If you feeling especially keen, there's a test suite in .test/run.sh that can be appended to at the bottom. Execute with .test/run.sh mtest THE_TEST_NAME
.
Some specific rules/tests to be implemented checked:
When there is a *.tar.*
:
MARIADB_AUTO_UPGRADE=1
auto-upgrading still works/docker-entrypoint-initdb.d
if there are files other than *.tar.*
.@mholmesbeatport have you had a chance to attempt this?
@grooverdan I have not yet had the time to work on this. However, I have hit the exact issue you said may happen - I have now ran out of disk space for that restore using our previous method. I will need to move on this ticket in the very near future.
I think that some version of rm
might not refuse to remove ..
(the parent directory), and therefore rm -fr .*
would be safer to write as rm -fr .[^.]* ..[^.]*
(to remove all files or directories that start with .
except for ..
). Also the expansions of the glob pattern directoryname/.*
should include directoryname/..
when using a POSIX /bin/sh
compatible shell like dash
. In bash
there is a shell option globskipdots
that is set at least on my system according to shopt -p
:
shopt -s globskipdots
Hi, there's a draft of loading mariabackup in #533. If you kindly download, build your own container and tell me if it suits your purposes (or not).
Thank you @grooverdan. Sorry work has been busy and I was not able to contribute on this as I had hoped. Thank you for picking this up. I will likely only get to testing this on Friday but will post back when I have.
ok merged now. Testing still welcome. Still a week before release.
I have ran into an issue with getting our local api development environment up and running with our mariadb 10.5 docker container.
I am successful with getting our dev environment up on versions 10.5.18, 10.5.19 and 10.5.20 but since I have 10.5 in my docker-compose file it defaults to the current 10.5.21 version of mariadb.
I have a compressed backup file and an
import.sh
bash shell file copied into the docker-entrypoint-initdb.d When the container starts the bash shell file is executed and does the following:zstd -d -c /docker-entrypoint-initdb.d/backup.zst | mbstream -x -C /tmp
rm-rf /var/lib/mysql/**
mariabackup --prepare --target-dir=/tmp
mariabackup --move-back --target-dir=/tmp
The database files are then moved into the /var/lib/mysql default data directory.
This process works flawlessly in versions <=10.5.20. In version 10.5.21 this process fails because there is now a
.my-healthcheck.cnf
file in the /var/lib/mysql data directory. I get the following error: "Original data directory /var/lib/mysql is not empty!"This causes the container to be in a repeating restart loop and fails to start successfully.
This is the docker logs with some added [DEBUG] statements:
I see the
.my-healthcheck.cnf
file has been recently implemented approximately 3 weeks ago with the following commit: https://github.com/MariaDB/mariadb-docker/pull/508/files#diff-7325bb1235108b46404c9b33b577ca3033e5d8b65a506b657e41ebccb96fcb5fMentioned in the following GitHub issue: https://github.com/MariaDB/mariadb-docker/issues/512#issuecomment-1608744838
As stated in MariaDB documentation in order to restore a backup the data directory needs to be empty: https://mariadb.com/kb/en/full-backup-and-restore-with-mariabackup/#restoring-the-backup
Any advice on how to work around this is much appreciated!