diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index fab409a..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,33 +0,0 @@ - -name: build docker image - -on: - push: - tags: - - "**" - -jobs: - build: - runs-on: ubuntu-22.04 - steps: - - name: Checkout the code - uses: actions/checkout@v4 - # https://github.com/docker/setup-qemu-action - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - # https://github.com/docker/setup-buildx-action - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: Get latest release version number - id: docker-tag - uses: yuya-takeyama/docker-tag-from-github-ref-action@v1 - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: fradelg - password: ${{ secrets.DOCKER_PASSWORD }} - - name: Build multiarch image - run: | - docker buildx build --push \ - --tag fradelg/mysql-cron-backup:${{ steps.docker-tag.outputs.tag }} \ - --platform linux/amd64,linux/arm/v7,linux/arm64 . diff --git a/.github/workflows/image.yml b/.github/workflows/image.yml new file mode 100644 index 0000000..7a4203a --- /dev/null +++ b/.github/workflows/image.yml @@ -0,0 +1,40 @@ +name: build docker image + +on: + workflow_dispatch: + push: + branches: + - "**" + tags: + - "**" + +jobs: + test: + runs-on: ubuntu-20.04 + steps: + - name: Checkout the code + uses: actions/checkout@v2 + - name: Test Bash scripts + run: sudo apt-get -qq update && sudo apt-get install -y devscripts shellcheck && make test + build: + runs-on: ubuntu-20.04 + needs: test + steps: + - name: Checkout the code + uses: actions/checkout@v2 + # https://github.com/docker/setup-qemu-action + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + # https://github.com/docker/setup-buildx-action + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - name: Get latest release version number + id: docker-tag + uses: yuya-takeyama/docker-tag-from-github-ref-action@v1 + - name: Login to Docker Hub + run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin + - name: Build multiarch image + run: | + docker buildx build --push \ + --tag fradelg/mysql-cron-backup:${{ steps.docker-tag.outputs.tag }} \ + --platform linux/amd64,linux/arm/v7,linux/arm64 . \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 4460983..0000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: build docker image - -on: - workflow_dispatch: - push: - branches: - - "**" - -jobs: - test: - runs-on: ubuntu-22.04 - steps: - - name: Checkout the code - uses: actions/checkout@v4 - - name: Test Bash scripts - run: sudo apt-get -qq update && sudo apt-get install -y devscripts shellcheck && make test - - name: Test image - env: - VOLUME_PATH: /tmp/mariadb - DATABASE_NAME: foo - MARIADB_ROOT_PASSWORD: abcd - run: | - docker compose up -d mariadb - docker compose run backup /backup.sh - docker compose run backup /restore.sh /backup/latest.foo.sql.gz - docker compose stop diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 6320cd2..0000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -data \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 73a2588..d19d572 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,28 +1,27 @@ -FROM golang:1.20.4-alpine3.18 AS binary +FROM golang:1.15.8-alpine3.12 AS binary RUN apk -U add openssl git -ARG DOCKERIZE_VERSION=v0.7.0 +ARG DOCKERIZE_VERSION=v0.6.1 WORKDIR /go/src/github.com/jwilder RUN git clone https://github.com/jwilder/dockerize.git && \ cd dockerize && \ git checkout ${DOCKERIZE_VERSION} WORKDIR /go/src/github.com/jwilder/dockerize -ENV GO111MODULE=on -RUN go mod tidy -RUN CGO_ENABLED=0 GOOS=linux GO111MODULE=on go build -a -o /go/bin/dockerize . +RUN go get github.com/robfig/glock +RUN glock sync -n < GLOCKFILE +RUN go install -FROM alpine:3.20.3 +FROM alpine:3.15.0 LABEL maintainer "Fco. Javier Delgado del Hoyo <frandelhoyo@gmail.com>" RUN apk add --update \ - tzdata \ - bash \ - gzip \ - openssl \ - mysql-client=~10.11 \ - mariadb-connector-c \ - fdupes && \ + tzdata \ + bash \ + mysql-client \ + gzip \ + openssl \ + mariadb-connector-c && \ rm -rf /var/cache/apk/* COPY --from=binary /go/bin/dockerize /usr/local/bin @@ -30,19 +29,15 @@ COPY --from=binary /go/bin/dockerize /usr/local/bin ENV CRON_TIME="0 3 * * sun" \ MYSQL_HOST="mysql" \ MYSQL_PORT="3306" \ - TIMEOUT="10s" \ - MYSQLDUMP_OPTS="--quick" + TIMEOUT="10s" -COPY ["run.sh", "backup.sh", "restore.sh", "/delete.sh", "/"] +COPY ["run.sh", "backup.sh", "restore.sh", "/"] RUN mkdir /backup && \ chmod 777 /backup && \ - chmod 755 /run.sh /backup.sh /restore.sh /delete.sh && \ + chmod 755 /run.sh /backup.sh /restore.sh && \ touch /mysql_backup.log && \ chmod 666 /mysql_backup.log VOLUME ["/backup"] -HEALTHCHECK --interval=2s --retries=1800 \ - CMD stat /HEALTHY.status || exit 1 - CMD dockerize -wait tcp://${MYSQL_HOST}:${MYSQL_PORT} -timeout ${TIMEOUT} /run.sh diff --git a/Makefile b/Makefile index ca5d51c..dc20422 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ test: # Checking for syntax errors set -e; for SCRIPT in *.sh; \ do \ - bash -n $$SCRIPT; \ + sh -n $$SCRIPT; \ done # Checking for bashisms (currently not failing, but only listing) diff --git a/README.md b/README.md index 16a2d65..e2cd2e8 100644 --- a/README.md +++ b/README.md @@ -13,36 +13,22 @@ docker container run -d \ fradelg/mysql-cron-backup ``` -### Healthcheck - - -Healthcheck is provided as a basic init control. -Container is **Healthy** after the database init phase, that is after `INIT_BACKUP` or `INIT_RESTORE_LATEST` happends without check if there is an error, **Starting** otherwise. Not other checks are actually provided. - ## Variables - - `MYSQL_HOST`: The host/ip of your mysql database. -- `MYSQL_HOST_FILE`: The file in container where to find the host of your mysql database (cf. docker secrets). You should use either MYSQL_HOST_FILE or MYSQL_HOST (see examples below). - `MYSQL_PORT`: The port number of your mysql database. - `MYSQL_USER`: The username of your mysql database. -- `MYSQL_USER_FILE`: The file in container where to find the user of your mysql database (cf. docker secrets). You should use either MYSQL_USER_FILE or MYSQL_USER (see examples below). - `MYSQL_PASS`: The password of your mysql database. - `MYSQL_PASS_FILE`: The file in container where to find the password of your mysql database (cf. docker secrets). You should use either MYSQL_PASS_FILE or MYSQL_PASS (see examples below). - `MYSQL_DATABASE`: The database name to dump. Default: `--all-databases`. -- `MYSQL_DATABASE_FILE`: The file in container where to find the database name(s) in your mysql database (cf. docker secrets). In that file, there can be several database names: one per line. You should use either MYSQL_DATABASE or MYSQL_DATABASE_FILE (see examples below). -- `MYSQLDUMP_OPTS`: Command line arguments to pass to mysqldump (see [mysqldump documentation](https://dev.mysql.com/doc/refman/8.0/en/mysqldump.html)). -- `MYSQL_SSL_OPTS`: Command line arguments to use [SSL](https://dev.mysql.com/doc/refman/5.6/en/using-encrypted-connections.html). +- `MYSQLDUMP_OPTS`: Command line arguments to pass to mysqldump. Example: `--single-transaction`. - `CRON_TIME`: The interval of cron job to run mysqldump. `0 3 * * sun` by default, which is every Sunday at 03:00. It uses UTC timezone. - `MAX_BACKUPS`: The number of backups to keep. When reaching the limit, the old backup will be discarded. No limit by default. - `INIT_BACKUP`: If set, create a backup when the container starts. - `INIT_RESTORE_LATEST`: If set, restores latest backup. -- `EXIT_BACKUP`: If set, create a backup when the container stops. - `TIMEOUT`: Wait a given number of seconds for the database to be ready and make the first backup, `10s` by default. After that time, the initial attempt for backup gives up and only the Cron job will try to make a backup. - `GZIP_LEVEL`: Specify the level of gzip compression from 1 (quickest, least compressed) to 9 (slowest, most compressed), default is 6. -- `USE_PLAIN_SQL`: If set, back up and restore plain SQL files without gzip. - `TZ`: Specify TIMEZONE in Container. E.g. "Europe/Berlin". Default is UTC. -- `REMOVE_DUPLICATES`: Use [fdupes](https://github.com/adrianlopezroche/fdupes) to remove duplicate database dumps If you want to make this image the perfect companion of your MySQL container, use [docker-compose](https://docs.docker.com/compose/). You can add more services that will be able to connect to the MySQL image using the name `my_mariadb`, note that you only expose the port `3306` internally to the servers and not to the host: @@ -81,8 +67,6 @@ services: - CRON_TIME=0 3 * * * # Make it small - GZIP_LEVEL=9 - # As of MySQL 8.0.21 this is needed - - MYSQLDUMP_OPTS=--no-tablespaces restart: unless-stopped volumes: @@ -93,23 +77,17 @@ volumes: The database root password passed to docker container by using [docker secrets](https://docs.docker.com/engine/swarm/). -In example below, docker is in classic 'docker engine mode' (iow. not swarm mode) and secret sources are local files on host filesystem. +In example below, docker is in classic 'docker engine mode' (iow. not swarm mode) and secret source is a local file on host filesystem. -Alternatively, secrets can be stored in docker secrets engine (iow. not in host filesystem). +Alternatively, secret can be stored in docker secrets engine (iow. not in host filesystem). ```yaml version: "3.7" secrets: - # Place your secret file somewhere on your host filesystem, with your password inside mysql_root_password: + # Place your secret file somewhere on your host filesystem, with your password inside file: ./secrets/mysql_root_password - mysql_user: - file: ./secrets/mysql_user - mysql_password: - file: ./secrets/mysql_password - mysql_database: - file: ./secrets/mysql_database services: mariadb: @@ -121,15 +99,10 @@ services: - data:/var/lib/mysql - ${VOLUME_PATH}/backup:/backup environment: + - MYSQL_DATABASE=${DATABASE_NAME} - MYSQL_ROOT_PASSWORD_FILE=/run/secrets/mysql_root_password - - MYSQL_USER_FILE=/run/secrets/mysql_user - - MYSQL_PASSWORD_FILE=/run/secrets/mysql_password - - MYSQL_DATABASE_FILE=/run/secrets/mysql_database secrets: - mysql_root_password - - mysql_user - - mysql_password - - mysql_database restart: unless-stopped backup: @@ -141,18 +114,13 @@ services: - ${VOLUME_PATH}/backup:/backup environment: - MYSQL_HOST=my_mariadb - # Alternatively to MYSQL_USER_FILE, we can use MYSQL_USER=root to use root user instead - - MYSQL_USER_FILE=/run/secrets/mysql_user - # Alternatively, we can use /run/secrets/mysql_root_password when using root user - - MYSQL_PASS_FILE=/run/secrets/mysql_password - - MYSQL_DATABASE_FILE=/run/secrets/mysql_database + - MYSQL_USER=root + - MYSQL_PASS_FILE=/run/secrets/mysql_root_password - MAX_BACKUPS=10 - INIT_BACKUP=1 - CRON_TIME=0 0 * * * secrets: - - mysql_user - - mysql_password - - mysql_database + - mysql_root_password restart: unless-stopped volumes: @@ -194,65 +162,4 @@ mysql-cron-backup: docker container exec <your_mysql_backup_container_name> /restore.sh /backup/<your_sql_backup_gz_file> ``` -if no database name is specified, `restore.sh` will try to find the database name from the backup file. - -### Automatic backup and restore on container starts and stops - -Set `INIT_RESTORE_LATEST` to automatic restore the last backup on startup. -Set `EXIT_BACKUP` to automatic create a last backup on shutdown. - -```yaml - mysql-cron-backup: - image: fradelg/mysql-cron-backup - depends_on: - - mariadb - volumes: - - ${VOLUME_PATH}/backup:/backup - environment: - - MYSQL_HOST=my_mariadb - - MYSQL_USER=${MYSQL_USER} - - MYSQL_PASS=${MYSQL_PASSWORD} - - MAX_BACKUPS=15 - - INIT_RESTORE_LATEST=1 - - EXIT_BACKUP=1 - # Every day at 03:00 - - CRON_TIME=0 3 * * * - # Make it small - - GZIP_LEVEL=9 - restart: unless-stopped - -volumes: - data: -``` - -Docker database image could expose a directory you could add files as init sql script. - -```yaml - mysql: - image: mysql - expose: - - 3306 - volumes: - - data:/var/lib/mysql - # If there is not scheme, restore using the init script (if exists) - - ./init-script.sql:/docker-entrypoint-initdb.d/database.sql.gz - environment: - - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} - - MYSQL_DATABASE=${DATABASE_NAME} - restart: unless-stopped -``` - -```yaml - mariadb: - image: mariadb - expose: - - 3306 - volumes: - - data:/var/lib/mysql - # If there is not scheme, restore using the init script (if exists) - - ./init-script.sql:/docker-entrypoint-initdb.d/database.sql.gz - environment: - - MYSQL_ROOT_PASSWORD=${MARIADB_ROOT_PASSWORD} - - MYSQL_DATABASE=${DATABASE_NAME} - restart: unless-stopped -``` \ No newline at end of file +if no database name is specified, `restore.sh` will try to find the database name from the backup file. \ No newline at end of file diff --git a/backup.sh b/backup.sh index 499575d..6b75964 100755 --- a/backup.sh +++ b/backup.sh @@ -1,23 +1,15 @@ #!/bin/bash -# Get hostname: try read from file, else get from env -[ -z "${MYSQL_HOST_FILE}" ] || { MYSQL_HOST=$(head -1 "${MYSQL_HOST_FILE}"); } -[ -z "${MYSQL_HOST}" ] && { echo "=> MYSQL_HOST cannot be empty" && exit 1; } -# Get username: try read from file, else get from env -[ -z "${MYSQL_USER_FILE}" ] || { MYSQL_USER=$(head -1 "${MYSQL_USER_FILE}"); } [ -z "${MYSQL_USER}" ] && { echo "=> MYSQL_USER cannot be empty" && exit 1; } -# Get password: try read from file, else get from env, else get from MYSQL_PASSWORD env +# If provided, take password from file [ -z "${MYSQL_PASS_FILE}" ] || { MYSQL_PASS=$(head -1 "${MYSQL_PASS_FILE}"); } +# Alternatively, take it from env var [ -z "${MYSQL_PASS:=$MYSQL_PASSWORD}" ] && { echo "=> MYSQL_PASS cannot be empty" && exit 1; } -# Get database name(s): try read from file, else get from env -# Note: when from file, there can be one database name per line in that file -[ -z "${MYSQL_DATABASE_FILE}" ] || { MYSQL_DATABASE=$(cat "${MYSQL_DATABASE_FILE}"); } -# Get level from env, else use 6 [ -z "${GZIP_LEVEL}" ] && { GZIP_LEVEL=6; } DATE=$(date +%Y%m%d%H%M) echo "=> Backup started at $(date "+%Y-%m-%d %H:%M:%S")" -DATABASES=${MYSQL_DATABASE:-${MYSQL_DB:-$(mysql -h "$MYSQL_HOST" -P "$MYSQL_PORT" -u "$MYSQL_USER" -p"$MYSQL_PASS" $MYSQL_SSL_OPTS -e "SHOW DATABASES;" | tr -d "| " | grep -v Database)}} +DATABASES=${MYSQL_DATABASE:-${MYSQL_DB:-$(mysql -h "$MYSQL_HOST" -P "$MYSQL_PORT" -u "$MYSQL_USER" -p"$MYSQL_PASS" -e "SHOW DATABASES;" | tr -d "| " | grep -v Database)}} for db in ${DATABASES} do if [[ "$db" != "information_schema" ]] \ @@ -28,36 +20,22 @@ do then echo "==> Dumping database: $db" FILENAME=/backup/$DATE.$db.sql - LATEST=/backup/latest.$db.sql - BASIC_OPTS="--single-transaction" - if [ -n "$REMOVE_DUPLICATES" ] + LATEST=/backup/latest.$db.sql.gz + if mysqldump --single-transaction -h "$MYSQL_HOST" -P "$MYSQL_PORT" -u "$MYSQL_USER" -p"$MYSQL_PASS" "$db" $MYSQLDUMP_OPTS > "$FILENAME" then - BASIC_OPTS="$BASIC_OPTS --skip-dump-date" - fi - if mysqldump $BASIC_OPTS $MYSQLDUMP_OPTS -h "$MYSQL_HOST" -P "$MYSQL_PORT" -u "$MYSQL_USER" -p"$MYSQL_PASS" $MYSQL_SSL_OPTS "$db" > "$FILENAME" - then - EXT= - if [ -z "${USE_PLAIN_SQL}" ] - then - echo "==> Compressing $db with LEVEL $GZIP_LEVEL" - gzip "-$GZIP_LEVEL" -n -f "$FILENAME" - EXT=.gz - FILENAME=$FILENAME$EXT - LATEST=$LATEST$EXT - fi - BASENAME=$(basename "$FILENAME") - echo "==> Creating symlink to latest backup: $BASENAME" + gzip "-$GZIP_LEVEL" -f "$FILENAME" + echo "==> Creating symlink to latest backup: $(basename "$FILENAME".gz)" rm "$LATEST" 2> /dev/null - cd /backup || exit && ln -s "$BASENAME" "$(basename "$LATEST")" - if [ -n "$REMOVE_DUPLICATES" ] - then - echo "==> Removing duplicate database dumps" - fdupes -idN /backup/ - fi + cd /backup || exit && ln -s "$(basename "$FILENAME".gz)" "$(basename "$LATEST")" if [ -n "$MAX_BACKUPS" ] then - # Execute the delete script, delete older backup or other custom delete script - /delete.sh "$db" $EXT + while [ "$(find /backup -maxdepth 1 -name "*.$db.sql.gz" -type f | wc -l)" -gt "$MAX_BACKUPS" ] + do + TARGET=$(find /backup -maxdepth 1 -name "*.$db.sql.gz" -type f | sort | head -n 1) + echo "==> Max number of backups ($MAX_BACKUPS) reached. Deleting ${TARGET} ..." + rm -rf "${TARGET}" + echo "==> Backup ${TARGET} deleted" + done fi else rm -rf "$FILENAME" diff --git a/delete.sh b/delete.sh deleted file mode 100755 index 929ed7b..0000000 --- a/delete.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -db=$1 -EXT=$2 - -# This file could be customized to create custom delete strategy - -while [ "$(find /backup -maxdepth 1 -name "*.$db.sql$EXT" -type f | wc -l)" -gt "$MAX_BACKUPS" ] -do - TARGET=$(find /backup -maxdepth 1 -name "*.$db.sql$EXT" -type f | sort | head -n 1) - echo "==> Max number of ($MAX_BACKUPS) backups reached. Deleting ${TARGET} ..." - rm -rf "${TARGET}" - echo "==> Backup ${TARGET} deleted" -done \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index 5ac0e9d..d0b693f 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,9 +1,8 @@ +version: "2" services: mariadb: - image: mariadb:10.11 + image: mariadb:10 container_name: my_mariadb - security_opt: - - seccomp:unconfined expose: - 3306 volumes: @@ -12,19 +11,13 @@ services: environment: - MYSQL_DATABASE=${DATABASE_NAME} - MYSQL_ROOT_PASSWORD=${MARIADB_ROOT_PASSWORD} - - MYSQL_ALLOW_EMPTY_ROOT_PASSWORD=yes restart: unless-stopped - healthcheck: - test: [ "CMD", "healthcheck.sh", "--su-mysql", "--connect" ] - timeout: 5s - retries: 10 backup: build: . image: fradelg/mysql-cron-backup depends_on: - mariadb: - condition: service_healthy + - mariadb volumes: - ${VOLUME_PATH}/backup:/backup environment: @@ -35,6 +28,6 @@ services: - INIT_BACKUP=1 - CRON_TIME=0 0 * * * restart: unless-stopped - -volumes: - data: + +volumes: + data: \ No newline at end of file diff --git a/restore.sh b/restore.sh index 6c03634..07ecbae 100755 --- a/restore.sh +++ b/restore.sh @@ -1,41 +1,29 @@ #!/bin/bash -# Get hostname: try read from file, else get from env -[ -z "${MYSQL_HOST_FILE}" ] || { MYSQL_HOST=$(head -1 "${MYSQL_HOST_FILE}"); } -[ -z "${MYSQL_HOST}" ] && { echo "=> MYSQL_HOST cannot be empty" && exit 1; } -# Get username: try read from file, else get from env -[ -z "${MYSQL_USER_FILE}" ] || { MYSQL_USER=$(head -1 "${MYSQL_USER_FILE}"); } [ -z "${MYSQL_USER}" ] && { echo "=> MYSQL_USER cannot be empty" && exit 1; } -# Get password: try read from file, else get from env, else get from MYSQL_PASSWORD env +# If provided, take password from file [ -z "${MYSQL_PASS_FILE}" ] || { MYSQL_PASS=$(head -1 "${MYSQL_PASS_FILE}"); } -[ -z "${MYSQL_PASS:=$MYSQL_PASSWORD}" ] && { echo "=> MYSQL_PASS cannot be empty" && exit 1; } +# Alternatively, take it from env var +[ -z "${MYSQL_PASS}" ] && { echo "=> MYSQL_PASS cannot be empty" && exit 1; } if [ "$#" -ne 1 ] then echo "You must pass the path of the backup file to restore" - exit 1 fi set -o pipefail -if [ -z "${USE_PLAIN_SQL}" ] -then - SQL=$(gunzip -c "$1") -else - SQL=$(cat "$1") -fi - +SQL=$(gunzip -c "$1") DB_NAME=${MYSQL_DATABASE:-${MYSQL_DB}} if [ -z "${DB_NAME}" ] then - echo "=> Searching database name in $1" DB_NAME=$(echo "$SQL" | grep -oE '(Database: (.+))' | cut -d ' ' -f 2) fi -[ -z "${DB_NAME}" ] && { echo "=> Database name not found" && exit 1; } +[ -z "${DB_NAME}" ] && { echo "=> database name cannot be found" && exit 1; } echo "=> Restore database $DB_NAME from $1" -if echo "$SQL" | mysql -h "$MYSQL_HOST" -P "$MYSQL_PORT" -u "$MYSQL_USER" -p"$MYSQL_PASS" $MYSQL_SSL_OPTS "$DB_NAME" +if echo "$SQL" | mysql -h "$MYSQL_HOST" -P "$MYSQL_PORT" -u "$MYSQL_USER" -p"$MYSQL_PASS" "$DB_NAME" then echo "=> Restore succeeded" else diff --git a/run.sh b/run.sh index 17a420c..95f8009 100755 --- a/run.sh +++ b/run.sh @@ -1,7 +1,7 @@ #!/bin/bash tail -F /mysql_backup.log & -if [ "${INIT_BACKUP:-0}" -gt "0" ]; then +if [ "${INIT_BACKUP}" -gt "0" ]; then echo "=> Create a backup on the startup" /backup.sh elif [ -n "${INIT_RESTORE_LATEST}" ]; then @@ -11,32 +11,10 @@ elif [ -n "${INIT_RESTORE_LATEST}" ]; then echo "waiting database container..." sleep 1 done - # Needed to exclude the 'latest.<database>.sql.gz' file, consider only filenames starting with number - # Only data-tagged backups, eg. '202212250457.database.sql.gz', must be trapped by the regex - find /backup -maxdepth 1 -name '[0-9]*.*.sql.gz' | sort | tail -1 | xargs /restore.sh + find /backup -maxdepth 1 -name '*.sql.gz' | tail -1 | xargs /restore.sh fi -function final_backup { - echo "=> Captured trap for final backup" - echo "=> Requested last backup at $(date "+%Y-%m-%d %H:%M:%S")" - exec /backup.sh - exit 0 -} - -if [ -n "${EXIT_BACKUP}" ]; then - echo "=> Listening on container shutdown gracefully to make last backup before close" - trap final_backup SIGHUP SIGINT SIGTERM -fi - -touch /HEALTHY.status - echo "${CRON_TIME} /backup.sh >> /mysql_backup.log 2>&1" > /tmp/crontab.conf crontab /tmp/crontab.conf echo "=> Running cron task manager in foreground" -crond -f -l 8 -L /mysql_backup.log & - -echo "Listening on crond, and wait..." - -tail -f /dev/null & wait $! - -echo "Script is shutted down." \ No newline at end of file +exec crond -f -l 8 -L /mysql_backup.log