├── .gitattributes ├── .github ├── CODEOWNERS ├── dependabot.yml └── workflows │ ├── docker-image.yml │ └── docker-publish.yml ├── .gitignore ├── CONTRIBUTING.md ├── Dockerfile ├── GitReleaseManager.yaml ├── LICENSE ├── README.md ├── backup.sh ├── docker-entrypoint.sh └── example ├── .env.template ├── Dockerfile.mssql ├── README.md ├── backup └── .gitkeep ├── docker-compose.yml └── remote └── .gitkeep /.gitattributes: -------------------------------------------------------------------------------- 1 | * eol=lf -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # These owners will be the default owners for everything in the repo and 2 | # will be requested for review when someone opens a pull request. 3 | * @bbtsoftware/dev-services -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: docker 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | -------------------------------------------------------------------------------- /.github/workflows/docker-image.yml: -------------------------------------------------------------------------------- 1 | name: Docker Image CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - develop 8 | pull_request: 9 | branches: 10 | - master 11 | - develop 12 | 13 | jobs: 14 | 15 | build: 16 | 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - uses: actions/checkout@v3 21 | - name: Build the Docker image 22 | run: docker build . --file Dockerfile --tag my-image-name:$(date +%s) 23 | -------------------------------------------------------------------------------- /.github/workflows/docker-publish.yml: -------------------------------------------------------------------------------- 1 | name: Docker Image Publish 2 | 3 | # This workflow uses actions that are not certified by GitHub. 4 | # They are provided by a third-party and are governed by 5 | # separate terms of service, privacy policy, and support 6 | # documentation. 7 | 8 | on: 9 | release: 10 | types: [published] 11 | 12 | env: 13 | # Use docker.io for Docker Hub if empty 14 | REGISTRY: docker.io 15 | # github.repository as / 16 | IMAGE_NAME: bbtsoftwareag/mssql-backup 17 | 18 | 19 | jobs: 20 | build: 21 | 22 | runs-on: ubuntu-latest 23 | permissions: 24 | contents: read 25 | packages: write 26 | # This is used to complete the identity challenge 27 | # with sigstore/fulcio when running outside of PRs. 28 | id-token: write 29 | 30 | steps: 31 | - name: Checkout repository 32 | uses: actions/checkout@v3 33 | 34 | # Install the cosign tool except on PR 35 | # https://github.com/sigstore/cosign-installer 36 | - name: Install cosign 37 | if: github.event_name != 'pull_request' 38 | uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da #v3.7.0 39 | with: 40 | cosign-release: 'v2.4.1' 41 | 42 | # Set up BuildKit Docker container builder to be able to build 43 | # multi-platform images and export cache 44 | # https://github.com/docker/setup-buildx-action 45 | - name: Set up Docker Buildx 46 | uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0 47 | 48 | # Login against a Docker registry except on PR 49 | # https://github.com/docker/login-action 50 | - name: Log into registry ${{ env.REGISTRY }} 51 | if: github.event_name != 'pull_request' 52 | uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 53 | with: 54 | registry: ${{ env.REGISTRY }} 55 | username: ${{ secrets.DOCKER_USERNAME }} 56 | password: ${{ secrets.DOCKER_PASSWORD }} 57 | 58 | # Extract metadata (tags, labels) for Docker 59 | # https://github.com/docker/metadata-action 60 | - name: Extract Docker metadata 61 | id: meta 62 | uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0 63 | with: 64 | images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} 65 | 66 | # Build and push Docker image with Buildx (don't push on PR) 67 | # https://github.com/docker/build-push-action 68 | - name: Build and push Docker image 69 | id: build-and-push 70 | uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0 71 | with: 72 | context: . 73 | push: ${{ github.event_name != 'pull_request' }} 74 | tags: ${{ steps.meta.outputs.tags }} 75 | labels: ${{ steps.meta.outputs.labels }} 76 | cache-from: type=gha 77 | cache-to: type=gha,mode=max 78 | 79 | # Sign the resulting Docker image digest except on PRs. 80 | # This will only write to the public Rekor transparency log when the Docker 81 | # repository is public to avoid leaking data. If you would like to publish 82 | # transparency data even for private images, pass --force to cosign below. 83 | # https://github.com/sigstore/cosign 84 | - name: Sign the published Docker image 85 | if: ${{ github.event_name != 'pull_request' }} 86 | env: 87 | # https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable 88 | TAGS: ${{ steps.meta.outputs.tags }} 89 | DIGEST: ${{ steps.build-and-push.outputs.digest }} 90 | # This step uses the identity token to provision an ephemeral certificate 91 | # against the sigstore community Fulcio instance. 92 | run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST} 93 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Ignore example backup files 3 | example/backup/ 4 | example/remote/ 5 | 6 | # Ignore environment variable file 7 | example/.env -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guidelines 2 | 3 | ## GitHub Discussion 4 | 5 | Join [GitHub discussions on the BBT Software docker-mssql-backup repository](https://github.com/bbtsoftware/docker-mssql-backup/discussions) 6 | for questions and to discuss ideas & feature requests. 7 | 8 | ## Contribute 9 | 10 | This repository uses [GitFlow] with default configuration. 11 | Development is happening on `develop` branch. 12 | 13 | To contribute: 14 | 15 | * Fork this repository. 16 | * Create a feature branch from `develop`. 17 | * Implement your changes. 18 | * Push your feature branch. 19 | * Create a pull request. 20 | 21 | > _We prefer the approach to create a pull-request per issue._ 22 | 23 | ## Release 24 | 25 | [GitFlow]: (http://nvie.com/posts/a-successful-git-branching-model/) 26 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/mssql-tools:latest 2 | LABEL MAINTAINER="BBT Software AG " 3 | 4 | ENV DB_SERVER="mssql" \ 5 | DB_USER="SA" \ 6 | DB_PASSWORD="" \ 7 | DB_NAMES="" \ 8 | CRON_SCHEDULE="0 1 * * sun" \ 9 | BACKUP_CLEANUP=false \ 10 | BACKUP_AGE=7 \ 11 | SKIP_BACKUP_LOG=false \ 12 | PACK="" \ 13 | ZIP_PASSWORD="" \ 14 | PUSH_REMOTE_MODE="" \ 15 | SMTP_HOST="" \ 16 | SMTP_PORT="" \ 17 | SMTP_AUTH="on" \ 18 | SMTP_USER="" \ 19 | SMTP_PASS="" \ 20 | SMTP_FROM="" \ 21 | SMTP_TLS="on" \ 22 | MAIL_TO="" 23 | 24 | RUN apt-get update && \ 25 | apt-get install -y cron zip msmtp msmtp-mta mailutils && \ 26 | rm -rf /var/cache/apk/* 27 | 28 | COPY backup.sh /usr/local/bin/ 29 | RUN chmod +x /usr/local/bin/backup.sh 30 | 31 | COPY docker-entrypoint.sh /usr/local/bin/ 32 | RUN chmod +x /usr/local/bin/docker-entrypoint.sh 33 | ENTRYPOINT ["docker-entrypoint.sh"] 34 | -------------------------------------------------------------------------------- /GitReleaseManager.yaml: -------------------------------------------------------------------------------- 1 | issue-labels-include: 2 | - Breaking change 3 | - Feature 4 | - Bug 5 | - Improvement 6 | - Documentation 7 | issue-labels-exclude: 8 | - Build 9 | issue-labels-alias: 10 | - name: Documentation 11 | header: Documentation 12 | plural: Documentation -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 BBT Software AG 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Docker image for backup of Microsoft SQL Server 2 | 3 | Docker image to create regular backups of a [Microsoft SQL Server] image. 4 | 5 | ## Information 6 | 7 | | Service | Stats | 8 | |---------|-------------------------------------------------------------------------------------------| 9 | | Docker | [![Build](https://img.shields.io/docker/cloud/build/bbtsoftwareag/mssql-backup.svg?style=flat-square)](https://hub.docker.com/r/bbtsoftwareag/mssql-backup/builds) [![Pulls](https://img.shields.io/docker/pulls/bbtsoftwareag/mssql-backup.svg?style=flat-square)](https://hub.docker.com/r/bbtsoftwareag/mssql-backup) [![Stars](https://img.shields.io/docker/stars/bbtsoftwareag/mssql-backup.svg?style=flat-square)](https://hub.docker.com/r/bbtsoftwareag/mssql-backup) [![Automated](https://img.shields.io/docker/cloud/automated/bbtsoftwareag/mssql-backup.svg?style=flat-square)](https://hub.docker.com/r/bbtsoftwareag/mssql-backup/builds) | 10 | | GitHub | [![Last commit](https://img.shields.io/github/last-commit/bbtsoftware/docker-mssql-backup.svg?style=flat-square)](https://github.com/bbtsoftware/docker-mssql-backup/commits/master) [![Issues](https://img.shields.io/github/issues-raw/bbtsoftware/docker-mssql-backup.svg?style=flat-square)](https://github.com/bbtsoftware/docker-mssql-backup/issues) [![PR](https://img.shields.io/github/issues-pr-raw/bbtsoftware/docker-mssql-backup.svg?style=flat-square)](https://github.com/bbtsoftware/docker-mssql-backup/pulls) [![Size](https://img.shields.io/github/repo-size/bbtsoftware/docker-mssql-backup.svg?style=flat-square)](https://github.com/bbtsoftware/docker-mssql-backup/) [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](https://github.com/bbtsoftware/docker-mssql-backup/blob/master/LICENSE) | 11 | 12 | ## General 13 | 14 | | Topic | Description | 15 | |--------|------------------------------------------------------------------------| 16 | | Image | See [Docker Hub](https://hub.docker.com/r/bbtsoftwareag/mssql-backup). | 17 | | Source | See [GitHub](https://github.com/bbtsoftware/docker-mssql-backup). | 18 | 19 | ## Usage 20 | 21 | This container can create backups on a [Microsoft SQL Server] container. 22 | 23 | **NOTE:** 24 | The backup is written to a directory `/backup` inside the [Microsoft SQL Server] container, not to a volume in the backup container. 25 | For using the cleanup feature attach the same `/backup` volume in the `bbtsoftwareag/mssql-backup` container. 26 | 27 | ### Tags 28 | 29 | | Tag | Description | Size | 30 | |--------|-----------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------| 31 | | latest | Latest master build | ![Size](https://shields.beevelop.com/docker/image/image-size/bbtsoftwareag/mssql-backup/latest.svg?style=flat-square) | 32 | | 0.1.0 | Release [0.1.0](https://github.com/bbtsoftware/docker-mssql-backup/releases/tag/0.1.0) | ![Size](https://shields.beevelop.com/docker/image/image-size/bbtsoftwareag/mssql-backup/0.1.0.svg?style=flat-square) | 33 | | 0.2.0 | Release [0.2.0](https://github.com/bbtsoftware/docker-mssql-backup/releases/tag/0.2.0) | ![Size](https://shields.beevelop.com/docker/image/image-size/bbtsoftwareag/mssql-backup/0.2.0.svg?style=flat-square) | 34 | | 0.3.0 | Release [0.3.0](https://github.com/bbtsoftware/docker-mssql-backup/releases/tag/0.3.0) | ![Size](https://shields.beevelop.com/docker/image/image-size/bbtsoftwareag/mssql-backup/0.3.0.svg?style=flat-square) | 35 | | 0.4.0 | Release [0.4.0](https://github.com/bbtsoftware/docker-mssql-backup/releases/tag/0.4.0) | ![Size](https://shields.beevelop.com/docker/image/image-size/bbtsoftwareag/mssql-backup/0.4.0.svg?style=flat-square) | 36 | | 0.5.0 | Release [0.5.0](https://github.com/bbtsoftware/docker-mssql-backup/releases/tag/0.5.0) | ![Size](https://shields.beevelop.com/docker/image/image-size/bbtsoftwareag/mssql-backup/0.5.0.svg?style=flat-square) | 37 | | 0.5.1 | Release [0.5.1](https://github.com/bbtsoftware/docker-mssql-backup/releases/tag/0.5.1) | ![Size](https://shields.beevelop.com/docker/image/image-size/bbtsoftwareag/mssql-backup/0.5.1.svg?style=flat-square) | 38 | 39 | ### Configuration 40 | 41 | These environment variables are supported: 42 | 43 | | Environment variable | Default value | Description | 44 | |----------------------|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 45 | | DB_SERVER | `mssql` | Name or address of the database server to backup. Normally this should be the name of the [Microsoft SQL Server] service. | 46 | | DB_USER | `SA` | User used to connect to the database server. | 47 | | DB_PASSWORD | | Password used to connect to the database server. | 48 | | DB_NAMES | | Names of the databases for which a backup should be created. | 49 | | TZ | | Timezone to use. | 50 | | CRON_SCHEDULE | `0 1 * * sun` | Cron schedule for running backups. NOTE: There is no check if there's already a backup running when starting the backup job. Therefore time interval needs to be longer than the maximum expected backup time for all databases. | 51 | | BACKUP_CLEANUP | `false` | Set to "true" if you want to let the cronjob remove files older than $BACKUP_AGE days | 52 | | BACKUP_AGE | `7` | Number of days to keep backups in backup directory | 53 | | SKIP_BACKUP_LOG | `false` | Skip step to backup the transaction log . | 54 | | PACK | | Possible values: `tar`, `zip`. If defined, compresses the output files into a single `.tar.gz` (or `zip`)-File. | 55 | | ZIP_PASSWORD | | Sets the password for the zip to the given value. Only works if `PACK` is set to `zip` | 56 | | PUSH_REMOTE_MODE | | The possible values `move` or `copy` activates pushing the backup files to a mapped remote directory. The volume `remote` must be mapped. | 57 | | SMTP_HOST | | If this is set, email reporting is enabled by sending the results of the backup process to `MAIL_TO`. You pretty much have to define all the other `SMTP_*` variables, when the host is defined. | 58 | | SMTP_PORT | | The port of the SMTP server | 59 | | SMTP_USER | | The username used to login against the SMTP server | 60 | | SMTP_PASS | | The password for connecting to the SMTP server | 61 | | SMTP_FROM | | The E-mail address from which mails should be sent from | 62 | | SMTP_TLS | `on` | Whether TLS should be used when connecting to the SMTP server | 63 | | MAIL_TO | | The target E-mail address for receiving mail reports | 64 | 65 | ## Examples 66 | 67 | ### Docker Compose 68 | 69 | The following example will create backups of the databases `MyFirstDatabaseToRestore` and `MySecondDatabaseToRestore` 70 | running inside the `db` container every day at 01.00 CEST and stores it in the `/storage/backup` directory on the host machine. 71 | 72 | ```yaml 73 | version: '3.7' 74 | 75 | services: 76 | db: 77 | image: mcr.microsoft.com/mssql/server 78 | volumes: 79 | - /storage/backup:/backup 80 | environment: 81 | - ACCEPT_EULA=Y 82 | - MSSQL_PID=Express 83 | - SA_PASSWORD=MySecre(12)tPassword 84 | networks: 85 | - default 86 | backup: 87 | image: bbtsoftwareag/mssql-backup 88 | # for using the cleanup feature, use the backup volume from db. 89 | # volumes: 90 | # - /storage/backup:/backup 91 | environment: 92 | - TZ=Europe/Zurich 93 | - DB_SERVER=db 94 | - DB_USER=SA 95 | - DB_PASSWORD=MySecre(12)tPassword 96 | - "DB_NAMES= 97 | MyFirstDatabaseToRestore 98 | MySecondDatabaseToRestore" 99 | - CRON_SCHEDULE=0 1 * * * 100 | networks: 101 | - default 102 | ``` 103 | 104 | ### Example environment 105 | 106 | We added a small docker environment in the [example](https://github.com/bbtsoftware/docker-mssql-backup/tree/develop/example) 107 | subdirectory for `development` or `tests` with a own [readme](https://github.com/bbtsoftware/docker-mssql-backup/blob/develop/example/README.md) file. 108 | 109 | ## Discussion 110 | 111 | For questions and to discuss ideas & feature requests, use the [GitHub discussions on the BBT Software docker-mssql-backup repository](https://github.com/bbtsoftware/docker-mssql-backup/discussions). 112 | 113 | [![Join in the discussion on the BBT Software docker-mssql-backup repository](https://img.shields.io/badge/GitHub-Discussions-green?logo=github)](https://github.com/bbtsoftware/docker-mssql-backup/discussions) 114 | 115 | ## Contributing 116 | 117 | Contributions are welcome. See [Contribution Guidelines](CONTRIBUTING.md). 118 | 119 | [Microsoft SQL Server]: https://hub.docker.com/_/microsoft-mssql-server 120 | -------------------------------------------------------------------------------- /backup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Validate environment variables 4 | [ -z "$DB_SERVER" ] && { echo "Required environment variable DB_SERVER not set" && exit 1; } 5 | [ -z "$DB_USER" ] && { echo "Required environment variable DB_USER not set" && exit 1; } 6 | [ -z "$DB_PASSWORD" ] && { echo "Required environment variable DB_PASSWORD not set" && exit 1; } 7 | [ -z "$DB_NAMES" ] && { echo "Required environment variable DB_NAMES not set" && exit 1; } 8 | 9 | echo "Backup started at $(date "+%Y-%m-%d %H:%M:%S")" 10 | 11 | CURRENT_DATE=$(date +%Y%m%d%H%M) 12 | 13 | # Target backup directory 14 | TARGETDIR="/backup" 15 | 16 | # Remote backup directory 17 | REMOTEDIR="/remote" 18 | 19 | [ "$DB_NAMES" = "*" ] && DB_NAMES=`/opt/mssql-tools/bin/sqlcmd -S "$DB_SERVER" -U "$DB_USER" -P "$DB_PASSWORD" -b -h -1 -Q "SELECT name FROM sys.databases WHERE name NOT IN ('master', 'model', 'tempdb', 'msdb')" | awk '/^[a-z]/'` 20 | 21 | for CURRENT_DB in $DB_NAMES 22 | do 23 | 24 | BACKUPNAME=$CURRENT_DATE.$CURRENT_DB 25 | 26 | # backup database files 27 | BAK_FILENAME=$TARGETDIR/$BACKUPNAME.bak 28 | 29 | echo "Backup database $CURRENT_DB to $BAK_FILENAME on $DB_SERVER..." 30 | if /opt/mssql-tools/bin/sqlcmd -S "$DB_SERVER" -U "$DB_USER" -P "$DB_PASSWORD" -b -Q "BACKUP DATABASE [$CURRENT_DB] TO DISK = N'$BAK_FILENAME' WITH NOFORMAT, NOINIT, NAME = '$CURRENT_DB-full', SKIP, NOUNLOAD, STATS = 10" 31 | then 32 | echo "Backup of database successfully created" 33 | else 34 | echo "Error creating database backup" 35 | rm -rf "$BAK_FILENAME" 36 | fi 37 | 38 | # backup log files 39 | if [ "$SKIP_BACKUP_LOG" = false ]; then 40 | TRN_FILENAME=$TARGETDIR/$BACKUPNAME.trn 41 | 42 | echo "Backup log of $CURRENT_DB to $TRN_FILENAME on $DB_SERVER..." 43 | if /opt/mssql-tools/bin/sqlcmd -S "$DB_SERVER" -U "$DB_USER" -P "$DB_PASSWORD" -b -Q "BACKUP LOG [$CURRENT_DB] TO DISK = N'$TRN_FILENAME' WITH NOFORMAT, NOINIT, NAME = '$CURRENT_DB-log', SKIP, NOUNLOAD, STATS = 10" 44 | then 45 | echo "Backup of log successfully created" 46 | else 47 | echo "Error creating log backup" 48 | rm -rf "$TRN_FILENAME" 49 | fi 50 | else 51 | $TRN_FILENAME="" 52 | echo "Backup of log skipped." 53 | fi 54 | 55 | if [ "$PACK" = "tar" ] || [ "$PACK" = "zip" ]; then 56 | # compress backup files into tar.gz or zip file 57 | echo "" 58 | echo "Compress backup files" 59 | FILES=$(find $TARGETDIR -maxdepth 1 -type f \( -name "$BACKUPNAME.bak" -o -name "$BACKUPNAME.trn" \) ) 60 | if [ "$PACK" = "tar" ]; then 61 | ARCHIVE_FILENAME="$TARGETDIR/$BACKUPNAME.tar.gz" 62 | tar cfvz "$ARCHIVE_FILENAME" $FILES 63 | retval=$? 64 | elif [ "$PACK" = "zip" ]; then 65 | ARCHIVE_FILENAME="$TARGETDIR/$BACKUPNAME.zip" 66 | if [ "$ZIP_PASSWORD" ]; then 67 | zip --password "$ZIP_PASSWORD" "$ARCHIVE_FILENAME" $FILES 68 | retval=$? 69 | else 70 | zip "$ARCHIVE_FILENAME" $FILES 71 | retval=$? 72 | fi 73 | fi 74 | 75 | echo "Packing up results to $ARCHIVE_FILENAME" 76 | if [ $retval -eq 0 ]; then 77 | echo "Successfully packed backup into $ARCHIVE_FILENAME" 78 | else 79 | echo "Failed creating $ARCHIVE_FILENAME" 80 | fi 81 | 82 | rm -rf $FILES 83 | fi 84 | 85 | # Push to remote directory 86 | if [ "$PUSH_REMOTE_MODE" = "move" ] || [ "$PUSH_REMOTE_MODE" = "copy" ]; then 87 | echo "Push backup to remote directory" 88 | find $TARGETDIR -maxdepth 1 -type f -name "$BACKUPNAME.*" -exec cp {} $REMOTEDIR \; 89 | 90 | if [ "$PUSH_REMOTE_MODE" = "move" ]; then 91 | echo "Cleanup target directory" 92 | find $TARGETDIR -maxdepth 1 -type f -name "$BACKUPNAME.*" -exec rm {} \; 93 | fi 94 | fi 95 | 96 | # Cleanup old backup files in target directory 97 | if [ "$BACKUP_CLEANUP" = true ]; then 98 | echo "" 99 | echo "Backup cleanup is activated" 100 | find $TARGETDIR -type f -name "*.$CURRENT_DB.*" -mtime +"$BACKUP_AGE" -exec echo {} " is deleted" \; 101 | find $TARGETDIR -type f -name "*.$CURRENT_DB.*" -mtime +"$BACKUP_AGE" -exec rm {} \; 102 | 103 | if [ "$PUSH_REMOTE_MODE" = "move" ] || [ "$PUSH_REMOTE_MODE" = "copy" ]; then 104 | echo "Cleanup remote directory" 105 | find $REMOTEDIR -type f -name "*.$CURRENT_DB.*" -mtime +"$BACKUP_AGE" -exec echo {} " is deleted" \; 106 | find $REMOTEDIR -type f -name "*.$CURRENT_DB.*" -mtime +"$BACKUP_AGE" -exec rm {} \; 107 | fi 108 | else 109 | echo "Backup files cleanup is disabled" 110 | fi 111 | 112 | done 113 | 114 | echo "Backup process finished at $(date "+%Y-%m-%d %H:%M:%S")" 115 | -------------------------------------------------------------------------------- /docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Create mail config if defined 4 | if [[ $SMTP_HOST ]]; then 5 | 6 | if [[ $SMTP_TLS = "on" ]]; then 7 | 8 | # Configuration with TLS 9 | cat << EOF > /etc/msmtprc 10 | defaults 11 | 12 | host $SMTP_HOST 13 | port $SMTP_PORT 14 | tls $SMTP_TLS 15 | tls_starttls $SMTP_TLS 16 | tls_trust_file /etc/ssl/certs/ca-certificates.crt 17 | tls_certcheck $SMTP_TLS 18 | 19 | account $SMTP_USER 20 | auth $SMTP_AUTH 21 | user $SMTP_USER 22 | password "$SMTP_PASS" 23 | from "$SMTP_USER" 24 | 25 | account default: $SMTP_USER 26 | 27 | aliases /etc/aliases 28 | EOF 29 | 30 | else 31 | 32 | # Configuration without TLS 33 | cat << EOF > /etc/msmtprc 34 | defaults 35 | 36 | host $SMTP_HOST 37 | port $SMTP_PORT 38 | 39 | account $SMTP_USER 40 | auth $SMTP_AUTH 41 | user $SMTP_USER 42 | password "$SMTP_PASS" 43 | from "$SMTP_USER" 44 | 45 | account default: $SMTP_USER 46 | 47 | aliases /etc/aliases 48 | EOF 49 | 50 | fi 51 | 52 | cat << EOF > /etc/aliases 53 | root: $SMTP_FROM 54 | default: $SMTP_FROM 55 | EOF 56 | 57 | echo 'set sendmail="/usr/bin/msmtp -t"' > /etc/mail.rc 58 | 59 | fi 60 | 61 | # Store environment variables to pass to cron job 62 | printenv | sed 's/^\([a-zA-Z0-9_]*\)=\(.*\)$/export \1="\2"/g' > /container_env.sh 63 | 64 | # Remove quotes from CRON_SCHEDULE 65 | cronSchedule=${CRON_SCHEDULE} 66 | cronSchedule=${cronSchedule%\"} 67 | cronSchedule=${cronSchedule#\"} 68 | 69 | # Write log to stdout 70 | cronLogConfig="> /proc/1/fd/1 2>&1 | tee -a $cronLogFile" 71 | 72 | # Create crontab definition 73 | if [[ $SMTP_HOST ]]; 74 | then 75 | echo "Cron e-mail reporting activated. '${SMTP_HOST}'" 76 | echo "$cronSchedule . /container_env.sh; /usr/local/bin/backup.sh $cronLogConfig | mail -s 'SQL Server Backup Result' $MAIL_TO $cronLogConfig" > /etc/cron.d/crontab.conf 77 | else 78 | echo "$cronSchedule . /container_env.sh; /usr/local/bin/backup.sh $cronLogConfig" > /etc/cron.d/crontab.conf 79 | fi 80 | 81 | # Apply cron job 82 | crontab /etc/cron.d/crontab.conf 83 | 84 | echo "Starting cron task manager..." 85 | echo " - Crontab = $cronSchedule" 86 | cron -f -------------------------------------------------------------------------------- /example/.env.template: -------------------------------------------------------------------------------- 1 | TZ=Europe/Zurich 2 | DB_SERVER=db 3 | DB_USER=SA 4 | DB_PASSWORD=MySqlServerPassword1234 5 | DB_NAMES=AdventureWorks2019 6 | BACKUP_CLEANUP=true 7 | BACKUP_AGE=1 8 | CRON_SCHEDULE=*/1 * * * * 9 | SKIP_BACKUP_LOG=false 10 | 11 | PACK="zip" 12 | ZIP_PASSWORD="ZipPassword1" 13 | PUSH_REMOTE_MODE="move" 14 | 15 | SMTP_HOST= 16 | SMTP_PORT= 17 | SMTP_AUTH=off 18 | SMTP_TLS=on 19 | SMTP_USER= 20 | SMTP_PASS= 21 | SMTP_FROM= 22 | MAIL_TO= 23 | -------------------------------------------------------------------------------- /example/Dockerfile.mssql: -------------------------------------------------------------------------------- 1 | # Adventure Works Database on SQL Server 2019 2 | FROM mcr.microsoft.com/mssql/server 3 | 4 | # Note: This isn't a secure password, and please don't use this for production. 5 | ENV SA_PASSWORD=MySqlServerPassword1234 6 | ENV ACCEPT_EULA=Y 7 | 8 | ADD https://github.com/Microsoft/sql-server-samples/releases/download/adventureworks/AdventureWorksLT2019.bak /var/opt/mssql/backup/ 9 | 10 | USER root 11 | RUN chown -R mssql /var/opt/mssql/backup 12 | USER mssql 13 | 14 | # Launch SQL Server, confirm startup is complete, restore the database, then terminate SQL Server. 15 | RUN ( /opt/mssql/bin/sqlservr & ) | grep -q "Service Broker manager has started" \ 16 | && sleep 5s \ 17 | && /opt/mssql-tools/bin/sqlcmd -U sa -P ${SA_PASSWORD} -Q 'RESTORE DATABASE AdventureWorks2019 FROM DISK = "/var/opt/mssql/backup/AdventureWorksLT2019.bak" WITH MOVE "AdventureWorksLT2012_Data" to "/var/opt/mssql/data/AdventureWorks2019.mdf", MOVE "AdventureWorksLT2012_Log" to "/var/opt/mssql/data/AdventureWorks2019_log.ldf", NOUNLOAD, STATS = 5' \ 18 | && /opt/mssql-tools/bin/sqlcmd -U sa -P ${SA_PASSWORD} -Q 'USE [AdventureWorks2019] ; ALTER DATABASE [AdventureWorks2019] SET RECOVERY FULL;' \ 19 | && pkill sqlservr 20 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # BBT Software docker-mssql-backup examples 2 | 3 | This directory includes `docker-compose` example files for try out and testing. 4 | It builds a database backup docker image with current project files and creates a sample database container 5 | which contains the standard AdventureWorks2019 database from microsoft for backup. 6 | 7 | ## Preconditions 8 | 9 | The follow precondition is required for using this examples on a desktop. 10 | 11 | * Installation of [Docker Desktop](https://www.docker.com/products/docker-desktop) Software. 12 | * `Docker Desktop` must switch to linux containers. 13 | 14 | **NOTE:** 15 | [Docker Engine](https://docs.docker.com/engine/) provides .deb and .rpm packages for Linux distribution 16 | 17 | ## Environment variable 18 | 19 | Rename a copy of the template file `.env.template` to `.env` and modify the values of the environment variables. 20 | 21 | ## Backup directory 22 | 23 | The directory `example/backup` will be used for `target` and `example/remote` is used for the `remote` database backup folder. 24 | 25 | ## Test database 26 | 27 | This sample database [AdventureWorksLT2019](https://github.com/Microsoft/sql-server-samples/releases/download/adventureworks/AdventureWorksLT2019.bak) 28 | is used for backup. 29 | 30 | ## Run container 31 | 32 | To run this example container execute the command: 33 | 34 | `docker-compose up` 35 | 36 | ## Logging 37 | 38 | The backup container cron job write logs to stdout and stderr output streams. Docker containers emit logs to the stdout 39 | and stderr output streams. Because containers are stateless, the logs are stored on the Docker host in JSON files by default. 40 | 41 | `docker logs [Container]` 42 | 43 | **NOTE:** 44 | The log file location can get with follow docker command: 45 | `docker inspect --format='{{.LogPath}}' [container-id or container-name]` 46 | 47 | ## Test backup file cleanup 48 | 49 | How to modify a backup file `lastwritetime` file setting, to test the backup file cleanup function. 50 | This example changes the `lastwritetime` file setting of `202102041519.AdventureWorks2019.tar.gz` to `2011-09-14T07:10:00`. 51 | 52 | `$(Get-Item 202102041519.AdventureWorks2019.tar.gz).lastwritetime=$(Get-Date "2011-09-14T07:10:00")` 53 | -------------------------------------------------------------------------------- /example/backup/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbtsoftware/docker-mssql-backup/bdcc13a3df1ee1776d776f8daa3143e4e3d40d03/example/backup/.gitkeep -------------------------------------------------------------------------------- /example/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | 3 | services: 4 | db: 5 | build: 6 | context: . 7 | dockerfile: Dockerfile.mssql 8 | volumes: 9 | - ./backup:/backup 10 | networks: 11 | - default 12 | backup: 13 | build: 14 | context: ../ 15 | volumes: 16 | - ./backup:/backup 17 | - ./remote:/remote 18 | - ../backup.sh:/usr/local/bin/backup.sh 19 | environment: 20 | - TZ 21 | - DB_SERVER 22 | - DB_USER 23 | - DB_PASSWORD 24 | - DB_NAMES 25 | - CRON_SCHEDULE 26 | - BACKUP_CLEANUP 27 | - BACKUP_AGE 28 | - SKIP_BACKUP_LOG 29 | - PACK 30 | - ZIP_PASSWORD 31 | - PUSH_REMOTE_MODE 32 | - SMTP_HOST 33 | - SMTP_PORT 34 | - SMTP_AUTH 35 | - SMTP_USER 36 | - SMTP_PASS 37 | - SMTP_FROM 38 | - SMTP_TLS 39 | - MAIL_TO 40 | networks: 41 | - default -------------------------------------------------------------------------------- /example/remote/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbtsoftware/docker-mssql-backup/bdcc13a3df1ee1776d776f8daa3143e4e3d40d03/example/remote/.gitkeep --------------------------------------------------------------------------------