diff --git a/mysql-restore-s3/Dockerfile b/mysql-restore-s3/Dockerfile new file mode 100644 index 0000000..708839d --- /dev/null +++ b/mysql-restore-s3/Dockerfile @@ -0,0 +1,21 @@ +FROM alpine:latest + +ADD install.sh install.sh +RUN sh install.sh && rm install.sh + +ENV MYSQL_HOST **None** +ENV MYSQL_PORT 3306 +ENV MYSQL_USER **None** +ENV MYSQL_PASSWORD **None** +ENV S3_ACCESS_KEY_ID **None** +ENV S3_SECRET_ACCESS_KEY **None** +ENV S3_BUCKET **None** +ENV S3_REGION us-west-1 +ENV S3_ENDPOINT **None** +ENV S3_S3V4 no +ENV S3_PREFIX 'backup' +ENV S3_FILENAME **None** + +ADD restore.sh restore.sh + +CMD ["sh", "restore.sh"] diff --git a/mysql-restore-s3/README.md b/mysql-restore-s3/README.md new file mode 100644 index 0000000..9f31140 --- /dev/null +++ b/mysql-restore-s3/README.md @@ -0,0 +1,37 @@ +# mysql-restore-s3 + +Restore a MySQL backup from S3 to MySQL + +## Warning + +This will potentially put your database in a very bad state or complete destroy your data, be very careful. + +## Limitations + +This is made to restore a backup made from mysql-backup-s3, if you backup came from somewhere else please check your format. + +* Your s3 bucket must only contain backups which you wish to restore - it will always grabs the 'latest' based on unix sort with no filtering, unless exact name provided +* They must be gzip encoded text sql files +* If your bucket has more than a 1000 files the latest may not be restore, only one s3 ls command is made + +## Usage + +Docker: +```sh +$ docker run -e S3_ACCESS_KEY_ID=key -e S3_SECRET_ACCESS_KEY=secret -e S3_BUCKET=my-bucket -e S3_PREFIX=backup -e MYSQL_USER=user -e MYSQL_PASSWORD=password -e MYSQL_HOST=localhost schickling/mysql-restore-s3 +``` + +## Environment variables + +- `MYSQL_HOST` the mysql host *required* +- `MYSQL_PORT` the mysql port (default: 3306) +- `MYSQL_USER` the mysql user *required* +- `MYSQL_PASSWORD` the mysql password *required* +- `S3_ACCESS_KEY_ID` your AWS access key *required* +- `S3_SECRET_ACCESS_KEY` your AWS secret key *required* +- `S3_BUCKET` your AWS S3 bucket path *required* +- `S3_PREFIX` path prefix in your bucket (default: 'backup') +- `S3_FILENAME` filename from S3 used for backup. If not set, it will use the latest snapshot file. +- `S3_REGION` the AWS S3 bucket region (default: us-west-1) +- `S3_ENDPOINT` the AWS Endpoint URL, for S3 Compliant APIs such as [minio](https://minio.io) (default: none) +- `S3_S3V4` set to `yes` to enable AWS Signature Version 4, required for [minio](https://minio.io) servers (default: no) diff --git a/mysql-restore-s3/install.sh b/mysql-restore-s3/install.sh new file mode 100644 index 0000000..ce29968 --- /dev/null +++ b/mysql-restore-s3/install.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +# exit if a command fails +set -eo pipefail + +apk update + +# install mysqldump +apk add mysql-client + +# install s3 tools +apk add python3 py3-pip +pip install awscli + +# cleanup +rm -rf /var/cache/apk/* diff --git a/mysql-restore-s3/restore.sh b/mysql-restore-s3/restore.sh new file mode 100644 index 0000000..2f4d5ce --- /dev/null +++ b/mysql-restore-s3/restore.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +set -eo pipefail + +if [ "${S3_ACCESS_KEY_ID}" == "**None**" ]; then + echo "Warning: You did not set the S3_ACCESS_KEY_ID environment variable." +fi + +if [ "${S3_SECRET_ACCESS_KEY}" == "**None**" ]; then + echo "Warning: You did not set the S3_SECRET_ACCESS_KEY environment variable." +fi + +if [ "${S3_BUCKET}" == "**None**" ]; then + echo "You need to set the S3_BUCKET environment variable." + exit 1 +fi + +if [ "${MYSQL_HOST}" == "**None**" ]; then + echo "You need to set the MYSQL_HOST environment variable." + exit 1 +fi + +if [ "${MYSQL_USER}" == "**None**" ]; then + echo "You need to set the MYSQL_USER environment variable." + exit 1 +fi + +if [ "${MYSQL_PASSWORD}" == "**None**" ]; then + echo "You need to set the MYSQL_PASSWORD environment variable or link to a container named MYSQL." + exit 1 +fi + +if [ "${S3_IAMROLE}" != "true" ]; then + # env vars needed for aws tools - only if an IAM role is not used + export AWS_ACCESS_KEY_ID=$S3_ACCESS_KEY_ID + export AWS_SECRET_ACCESS_KEY=$S3_SECRET_ACCESS_KEY + export AWS_DEFAULT_REGION=$S3_REGION +fi + +if [ "${S3_ENDPOINT}" == "**None**" ]; then + AWS_ARGS="" +else + AWS_ARGS="--endpoint-url ${S3_ENDPOINT}" +fi + +if [ "${S3_FILENAME}" == "**None**" ]; then + echo "Finding latest backup" + S3_FILENAME=$(aws $AWS_ARGS s3 ls s3://$S3_BUCKET/$S3_PREFIX/ | sort | tail -n 1 | awk '{ print $4 }') +fi + +MYSQL_HOST_OPTS="${MYSQL_OPTS} -h $MYSQL_HOST -P $MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD" + +echo "Fetching ${S3_FILENAME} from S3" + +aws $AWS_ARGS s3 cp s3://$S3_BUCKET/$S3_PREFIX/${S3_FILENAME} dump.sql.gz +gzip -d dump.sql.gz + +echo "Restoring ${S3_FILENAME}" + +mysql $MYSQL_HOST_OPTS < dump.sql + +echo "MySQL Restore complete"