Compare commits
	
		
			No commits in common. "main" and "v1" have entirely different histories.
		
	
	
		
	
		
					 6 changed files with 74 additions and 433 deletions
				
			
		| 
						 | 
				
			
			@ -1,10 +1,8 @@
 | 
			
		|||
FROM alpine:3.22
 | 
			
		||||
 | 
			
		||||
RUN apk add --no-cache restic docker-cli docker-cli-compose curl zstd bash
 | 
			
		||||
RUN apk add --no-cache restic docker-cli docker-cli-compose curl
 | 
			
		||||
 | 
			
		||||
COPY backup.sh /backup.sh
 | 
			
		||||
COPY backup_local.sh /backup_local.sh
 | 
			
		||||
COPY backup_restic.sh /backup_restic.sh
 | 
			
		||||
RUN chmod +x /backup.sh /backup_local.sh /backup_restic.sh
 | 
			
		||||
RUN chmod +x /backup.sh
 | 
			
		||||
 | 
			
		||||
ENTRYPOINT [ "/backup.sh" ]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										285
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										285
									
								
								README.md
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -1,55 +1,34 @@
 | 
			
		|||
# Database Backup Container
 | 
			
		||||
 | 
			
		||||
A lightweight Alpine-based Docker container for backing up MariaDB and PostgreSQL databases with support for both local snapshots and Restic backups.
 | 
			
		||||
A lightweight Alpine-based Docker container for backing up MariaDB and PostgreSQL databases using Restic.
 | 
			
		||||
 | 
			
		||||
## Overview
 | 
			
		||||
 | 
			
		||||
This container automatically detects the database type (MariaDB or PostgreSQL) in a target container and creates backups using either local file storage with compression or Restic repositories. It supports backing up databases from other Docker containers by executing dump commands inside them.
 | 
			
		||||
This container automatically detects the database type (MariaDB or PostgreSQL) in a target container and creates backups using Restic. It supports backing up databases from other Docker containers by executing dump commands inside them.
 | 
			
		||||
 | 
			
		||||
## Features
 | 
			
		||||
 | 
			
		||||
- **Multi-database support**: Automatically detects and backs up MariaDB or PostgreSQL databases
 | 
			
		||||
- **Dual backup methods**: Choose between local compressed files or Restic repositories
 | 
			
		||||
- **Local snapshots**: Create compressed (zstd) local backup files with timestamps
 | 
			
		||||
- **Restic integration**: Uses Restic for efficient, encrypted, and deduplicated backups
 | 
			
		||||
- **Docker-in-Docker**: Can access and backup databases from other containers
 | 
			
		||||
- **Notification support**: Optional webhook notifications when backups complete
 | 
			
		||||
- **Lightweight**: Based on Alpine Linux for minimal footprint
 | 
			
		||||
 | 
			
		||||
## Prerequisites
 | 
			
		||||
 | 
			
		||||
- Docker with socket access (`/var/run/docker.sock`)
 | 
			
		||||
- Target container with either MariaDB or PostgreSQL client tools
 | 
			
		||||
- For Restic backups: Restic repository (local, S3, B2, etc.)
 | 
			
		||||
- For local backups: Mounted volume for backup storage
 | 
			
		||||
- Restic repository (local, S3, B2, etc.)
 | 
			
		||||
 | 
			
		||||
## Environment Variables
 | 
			
		||||
 | 
			
		||||
### Required (All Methods)
 | 
			
		||||
### Required
 | 
			
		||||
 | 
			
		||||
| Variable | Description |
 | 
			
		||||
|----------|-------------|
 | 
			
		||||
| `CONTAINER` | Name of the Docker container where the database is running |
 | 
			
		||||
 | 
			
		||||
### For Restic Backups
 | 
			
		||||
 | 
			
		||||
| Variable | Description |
 | 
			
		||||
|----------|-------------|
 | 
			
		||||
| `RESTIC_PASSWORD` | Password for the Restic repository |
 | 
			
		||||
| `RESTIC_REPOSITORY` | Restic repository URL (e.g., `s3:s3.amazonaws.com/bucket`, `/data/backups`) |
 | 
			
		||||
 | 
			
		||||
### For Local Backups
 | 
			
		||||
 | 
			
		||||
| Variable | Description |
 | 
			
		||||
|----------|-------------|
 | 
			
		||||
| `TARGET_DIR` | Directory where backup files will be stored |
 | 
			
		||||
 | 
			
		||||
### Optional
 | 
			
		||||
 | 
			
		||||
| Variable | Description |
 | 
			
		||||
|----------|-------------|
 | 
			
		||||
| `NOTIFY_URL` | Optional webhook URL to call when backup completes |
 | 
			
		||||
 | 
			
		||||
### Database-specific
 | 
			
		||||
 | 
			
		||||
#### For MariaDB containers:
 | 
			
		||||
| 
						 | 
				
			
			@ -66,15 +45,7 @@ This container automatically detects the database type (MariaDB or PostgreSQL) i
 | 
			
		|||
 | 
			
		||||
## Usage
 | 
			
		||||
 | 
			
		||||
### Backup Methods
 | 
			
		||||
 | 
			
		||||
The container supports three execution modes:
 | 
			
		||||
 | 
			
		||||
1. **`restic`** - Backup to Restic repositories (cloud storage, remote servers)
 | 
			
		||||
2. **`local`** - Create compressed local backup files
 | 
			
		||||
3. **`loop`** - Keep container running for external schedulers (e.g., Ofelia, Kubernetes CronJob)
 | 
			
		||||
 | 
			
		||||
### Restic Backups
 | 
			
		||||
### Basic Usage
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
docker run --rm \
 | 
			
		||||
| 
						 | 
				
			
			@ -83,101 +54,11 @@ docker run --rm \
 | 
			
		|||
  -e RESTIC_PASSWORD=my-secret-password \
 | 
			
		||||
  -e RESTIC_REPOSITORY=s3:s3.amazonaws.com/my-backup-bucket \
 | 
			
		||||
  -e MARIADB_ROOT_PASSWORD=db-password \
 | 
			
		||||
  gitea.ceperka.net/rosti/db-backup:latest restic
 | 
			
		||||
  gitea.ceperka.net/rosti/db-backup:latest
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Local Backups
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
docker run --rm \
 | 
			
		||||
  -v /var/run/docker.sock:/var/run/docker.sock \
 | 
			
		||||
  -v /host/backup/path:/backups \
 | 
			
		||||
  -e CONTAINER=my-mariadb-container \
 | 
			
		||||
  -e TARGET_DIR=/backups \
 | 
			
		||||
  -e MARIADB_ROOT_PASSWORD=db-password \
 | 
			
		||||
  gitea.ceperka.net/rosti/db-backup:latest local
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Loop Mode (For External Schedulers)
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
docker run -d \
 | 
			
		||||
  -v /var/run/docker.sock:/var/run/docker.sock \
 | 
			
		||||
  -e CONTAINER=my-mariadb-container \
 | 
			
		||||
  -e MARIADB_ROOT_PASSWORD=db-password \
 | 
			
		||||
  gitea.ceperka.net/rosti/db-backup:latest loop
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
In loop mode, the container stays running indefinitely, allowing external schedulers like Ofelia, Kubernetes CronJobs, or other orchestrators to execute the backup scripts directly inside the running container.
 | 
			
		||||
 | 
			
		||||
### With Docker Compose
 | 
			
		||||
 | 
			
		||||
#### Restic Backup Setup
 | 
			
		||||
 | 
			
		||||
```yaml
 | 
			
		||||
version: '3.8'
 | 
			
		||||
 | 
			
		||||
services:
 | 
			
		||||
  database:
 | 
			
		||||
    image: mariadb:latest
 | 
			
		||||
    environment:
 | 
			
		||||
      MARIADB_ROOT_PASSWORD: secretpassword
 | 
			
		||||
      MARIADB_DATABASE: myapp
 | 
			
		||||
    volumes:
 | 
			
		||||
      - db_data:/var/lib/mysql
 | 
			
		||||
 | 
			
		||||
  backup-restic:
 | 
			
		||||
    image: gitea.ceperka.net/rosti/db-backup:latest
 | 
			
		||||
    depends_on:
 | 
			
		||||
      - database
 | 
			
		||||
    environment:
 | 
			
		||||
      CONTAINER: database
 | 
			
		||||
      RESTIC_PASSWORD: my-backup-password
 | 
			
		||||
      RESTIC_REPOSITORY: s3:s3.amazonaws.com/my-backup-bucket
 | 
			
		||||
      MARIADB_ROOT_PASSWORD: secretpassword
 | 
			
		||||
      NOTIFY_URL: https://hc-ping.com/your-healthcheck-uuid
 | 
			
		||||
    volumes:
 | 
			
		||||
      - /var/run/docker.sock:/var/run/docker.sock
 | 
			
		||||
    command: ["restic"]
 | 
			
		||||
 | 
			
		||||
volumes:
 | 
			
		||||
  db_data:
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Local Backup Setup
 | 
			
		||||
 | 
			
		||||
```yaml
 | 
			
		||||
version: '3.8'
 | 
			
		||||
 | 
			
		||||
services:
 | 
			
		||||
  database:
 | 
			
		||||
    image: mariadb:latest
 | 
			
		||||
    environment:
 | 
			
		||||
      MARIADB_ROOT_PASSWORD: secretpassword
 | 
			
		||||
      MARIADB_DATABASE: myapp
 | 
			
		||||
    volumes:
 | 
			
		||||
      - db_data:/var/lib/mysql
 | 
			
		||||
 | 
			
		||||
  backup-local:
 | 
			
		||||
    image: gitea.ceperka.net/rosti/db-backup:latest
 | 
			
		||||
    depends_on:
 | 
			
		||||
      - database
 | 
			
		||||
    environment:
 | 
			
		||||
      CONTAINER: database
 | 
			
		||||
      TARGET_DIR: /backups
 | 
			
		||||
      MARIADB_ROOT_PASSWORD: secretpassword
 | 
			
		||||
      NOTIFY_URL: https://hc-ping.com/your-healthcheck-uuid
 | 
			
		||||
    volumes:
 | 
			
		||||
      - /var/run/docker.sock:/var/run/docker.sock
 | 
			
		||||
      - ./backups:/backups
 | 
			
		||||
    command: ["local"]
 | 
			
		||||
 | 
			
		||||
volumes:
 | 
			
		||||
  db_data:
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Loop Mode with External Scheduler (Ofelia)
 | 
			
		||||
 | 
			
		||||
```yaml
 | 
			
		||||
version: '3.8'
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -196,27 +77,12 @@ services:
 | 
			
		|||
      - database
 | 
			
		||||
    environment:
 | 
			
		||||
      CONTAINER: database
 | 
			
		||||
      TARGET_DIR: /backups
 | 
			
		||||
      RESTIC_PASSWORD: my-backup-password
 | 
			
		||||
      RESTIC_REPOSITORY: /backups
 | 
			
		||||
      MARIADB_ROOT_PASSWORD: secretpassword
 | 
			
		||||
      NOTIFY_URL: https://hc-ping.com/your-healthcheck-uuid
 | 
			
		||||
    volumes:
 | 
			
		||||
      - /var/run/docker.sock:/var/run/docker.sock
 | 
			
		||||
      - ./backups:/backups
 | 
			
		||||
    command: ["loop"]
 | 
			
		||||
    labels:
 | 
			
		||||
      ofelia.enabled: "true"
 | 
			
		||||
      ofelia.job-exec.backup-local.schedule: "0 2 * * *"
 | 
			
		||||
      ofelia.job-exec.backup-local.command: "/backup_local.sh"
 | 
			
		||||
      ofelia.job-exec.backup-restic.schedule: "0 3 * * *" 
 | 
			
		||||
      ofelia.job-exec.backup-restic.command: "/backup_restic.sh"
 | 
			
		||||
 | 
			
		||||
  scheduler:
 | 
			
		||||
    image: mcuadros/ofelia:latest
 | 
			
		||||
    depends_on:
 | 
			
		||||
      - backup
 | 
			
		||||
    command: daemon --docker
 | 
			
		||||
    volumes:
 | 
			
		||||
      - /var/run/docker.sock:/var/run/docker.sock
 | 
			
		||||
 | 
			
		||||
volumes:
 | 
			
		||||
  db_data:
 | 
			
		||||
| 
						 | 
				
			
			@ -226,49 +92,18 @@ volumes:
 | 
			
		|||
 | 
			
		||||
To run backups on a schedule, you can use cron or a container orchestrator:
 | 
			
		||||
 | 
			
		||||
#### Restic Backups
 | 
			
		||||
```bash
 | 
			
		||||
# Add to crontab for daily Restic backups at 2 AM
 | 
			
		||||
0 2 * * * docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -e CONTAINER=my-db -e RESTIC_PASSWORD=pass -e RESTIC_REPOSITORY=s3:s3.amazonaws.com/bucket -e MARIADB_ROOT_PASSWORD=dbpass gitea.ceperka.net/rosti/db-backup:latest restic
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Local Backups
 | 
			
		||||
```bash
 | 
			
		||||
# Add to crontab for daily local backups at 3 AM
 | 
			
		||||
0 3 * * * docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v /host/backups:/backups -e CONTAINER=my-db -e TARGET_DIR=/backups -e MARIADB_ROOT_PASSWORD=dbpass gitea.ceperka.net/rosti/db-backup:latest local
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### External Schedulers with Loop Mode
 | 
			
		||||
 | 
			
		||||
When using loop mode, you can execute backups from external schedulers by running the backup scripts directly inside the running container:
 | 
			
		||||
 | 
			
		||||
#### With Ofelia Scheduler
 | 
			
		||||
Ofelia can execute jobs in running containers using labels (see Docker Compose example above).
 | 
			
		||||
 | 
			
		||||
#### Manual Execution in Loop Mode
 | 
			
		||||
```bash
 | 
			
		||||
# Execute local backup in running container
 | 
			
		||||
docker exec <container-name> /backup_local.sh
 | 
			
		||||
 | 
			
		||||
# Execute restic backup in running container  
 | 
			
		||||
docker exec <container-name> /backup_restic.sh
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### With Kubernetes CronJob + Running Pod
 | 
			
		||||
```bash
 | 
			
		||||
# Execute backup in running pod
 | 
			
		||||
kubectl exec <pod-name> -- /backup_local.sh
 | 
			
		||||
# Add to crontab for daily backups at 2 AM
 | 
			
		||||
0 2 * * * docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -e CONTAINER=my-db -e RESTIC_PASSWORD=pass -e RESTIC_REPOSITORY=/backups -e MARIADB_ROOT_PASSWORD=dbpass gitea.ceperka.net/rosti/db-backup:latest
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Kubernetes CronJob
 | 
			
		||||
 | 
			
		||||
#### Restic Backup CronJob
 | 
			
		||||
 | 
			
		||||
```yaml
 | 
			
		||||
apiVersion: batch/v1
 | 
			
		||||
kind: CronJob
 | 
			
		||||
metadata:
 | 
			
		||||
  name: database-backup-restic
 | 
			
		||||
  name: database-backup
 | 
			
		||||
spec:
 | 
			
		||||
  schedule: "0 2 * * *"  # Daily at 2 AM
 | 
			
		||||
  jobTemplate:
 | 
			
		||||
| 
						 | 
				
			
			@ -278,7 +113,6 @@ spec:
 | 
			
		|||
          containers:
 | 
			
		||||
          - name: backup
 | 
			
		||||
            image: gitea.ceperka.net/rosti/db-backup:latest
 | 
			
		||||
            args: ["restic"]
 | 
			
		||||
            env:
 | 
			
		||||
            - name: CONTAINER
 | 
			
		||||
              value: "my-database-pod"
 | 
			
		||||
| 
						 | 
				
			
			@ -304,87 +138,12 @@ spec:
 | 
			
		|||
          restartPolicy: OnFailure
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Local Backup CronJob
 | 
			
		||||
 | 
			
		||||
```yaml
 | 
			
		||||
apiVersion: batch/v1
 | 
			
		||||
kind: CronJob
 | 
			
		||||
metadata:
 | 
			
		||||
  name: database-backup-local
 | 
			
		||||
spec:
 | 
			
		||||
  schedule: "0 3 * * *"  # Daily at 3 AM
 | 
			
		||||
  jobTemplate:
 | 
			
		||||
    spec:
 | 
			
		||||
      template:
 | 
			
		||||
        spec:
 | 
			
		||||
          containers:
 | 
			
		||||
          - name: backup
 | 
			
		||||
            image: gitea.ceperka.net/rosti/db-backup:latest
 | 
			
		||||
            args: ["local"]
 | 
			
		||||
            env:
 | 
			
		||||
            - name: CONTAINER
 | 
			
		||||
              value: "my-database-pod"
 | 
			
		||||
            - name: TARGET_DIR
 | 
			
		||||
              value: "/backups"
 | 
			
		||||
            - name: MARIADB_ROOT_PASSWORD
 | 
			
		||||
              valueFrom:
 | 
			
		||||
                secretKeyRef:
 | 
			
		||||
                  name: db-secrets
 | 
			
		||||
                  key: root-password
 | 
			
		||||
            volumeMounts:
 | 
			
		||||
            - name: docker-sock
 | 
			
		||||
              mountPath: /var/run/docker.sock
 | 
			
		||||
            - name: backup-storage
 | 
			
		||||
              mountPath: /backups
 | 
			
		||||
          volumes:
 | 
			
		||||
          - name: docker-sock
 | 
			
		||||
            hostPath:
 | 
			
		||||
              path: /var/run/docker.sock
 | 
			
		||||
          - name: backup-storage
 | 
			
		||||
            persistentVolumeClaim:
 | 
			
		||||
              claimName: backup-pvc
 | 
			
		||||
          restartPolicy: OnFailure
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Backup File Naming
 | 
			
		||||
 | 
			
		||||
### Restic Backups
 | 
			
		||||
Backups are stored with the following naming convention:
 | 
			
		||||
- MariaDB: `mariadb_[CONTAINER]_[DB_NAME].sql`
 | 
			
		||||
- PostgreSQL: `pgsql_[CONTAINER]_[DB_NAME].sql`
 | 
			
		||||
 | 
			
		||||
### Local Backups
 | 
			
		||||
Local backup files include timestamps and are compressed:
 | 
			
		||||
- MariaDB: `YYYYMMDD_HHMMSS_mariadb_[CONTAINER]_[DB_NAME].sql.zst`
 | 
			
		||||
- PostgreSQL: `YYYYMMDD_HHMMSS_pgsql_[CONTAINER]_[DB_NAME].sql.zst`
 | 
			
		||||
 | 
			
		||||
Local backups use zstd compression for efficient storage and include atomic file operations (temporary files are renamed when complete).
 | 
			
		||||
 | 
			
		||||
## MariaDB Backup Features
 | 
			
		||||
 | 
			
		||||
The container includes comprehensive MariaDB backup options:
 | 
			
		||||
 | 
			
		||||
- **`--add-drop-trigger`** - Add DROP TRIGGER statements
 | 
			
		||||
- **`--add-drop-table`** - Add DROP TABLE statements  
 | 
			
		||||
- **`--add-drop-database`** - Add DROP DATABASE statements
 | 
			
		||||
- **`--hex-blob`** - Use hexadecimal notation for binary data
 | 
			
		||||
- **`--compress`** - Compress data in backup
 | 
			
		||||
- **`--events`** - Include events in backup
 | 
			
		||||
- **`--routines`** - Include stored procedures and functions
 | 
			
		||||
- **`--single-transaction`** - Consistent backup for InnoDB tables
 | 
			
		||||
- **`--triggers`** - Include triggers in backup
 | 
			
		||||
 | 
			
		||||
## Notification Support
 | 
			
		||||
 | 
			
		||||
Both backup methods support optional webhook notifications:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
# Set NOTIFY_URL to receive notifications when backups complete
 | 
			
		||||
-e NOTIFY_URL=https://hc-ping.com/your-healthcheck-uuid
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The container will make a GET request to the URL after successful backup completion.
 | 
			
		||||
 | 
			
		||||
## Supported Restic Repositories
 | 
			
		||||
 | 
			
		||||
This container supports all Restic repository types:
 | 
			
		||||
| 
						 | 
				
			
			@ -432,31 +191,14 @@ docker build -t gitea.ceperka.net/rosti/db-backup:dev .
 | 
			
		|||
   - Verify database credentials are correct
 | 
			
		||||
   - Ensure environment variables are properly set
 | 
			
		||||
 | 
			
		||||
4. **"TARGET_DIR does not exist"** (Local backups)
 | 
			
		||||
   - Ensure the target directory is mounted as a volume
 | 
			
		||||
   - Check directory permissions
 | 
			
		||||
 | 
			
		||||
5. **"Unknown backup method"**
 | 
			
		||||
   - Ensure you specify either `local` or `restic` as the command argument
 | 
			
		||||
 | 
			
		||||
### Debug Mode
 | 
			
		||||
 | 
			
		||||
To debug issues, you can run the container interactively:
 | 
			
		||||
 | 
			
		||||
#### Restic Debug
 | 
			
		||||
```bash
 | 
			
		||||
docker run -it --rm \
 | 
			
		||||
  -v /var/run/docker.sock:/var/run/docker.sock \
 | 
			
		||||
  --entrypoint /bin/bash \
 | 
			
		||||
  gitea.ceperka.net/rosti/db-backup:latest
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Local Debug
 | 
			
		||||
```bash
 | 
			
		||||
docker run -it --rm \
 | 
			
		||||
  -v /var/run/docker.sock:/var/run/docker.sock \
 | 
			
		||||
  -v /host/backup/path:/backups \
 | 
			
		||||
  --entrypoint /bin/bash \
 | 
			
		||||
  --entrypoint /bin/sh \
 | 
			
		||||
  gitea.ceperka.net/rosti/db-backup:latest
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -467,3 +209,6 @@ docker run -it --rm \
 | 
			
		|||
- Regularly rotate Restic repository passwords
 | 
			
		||||
- Consider using encrypted storage for backup repositories
 | 
			
		||||
 | 
			
		||||
## License
 | 
			
		||||
 | 
			
		||||
This project is licensed under the MIT License.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,3 @@ tasks:
 | 
			
		|||
  testdb:
 | 
			
		||||
    cmds:
 | 
			
		||||
    - docker run -d --name testmariadb --env MARIADB_USER=maria --env MARIADB_PASSWORD=maria --env MARIADB_DATABASE=maria --env MARIADB_ROOT_PASSWORD=maria mariadb:latest
 | 
			
		||||
  test:
 | 
			
		||||
    cmds:
 | 
			
		||||
    - docker run --name testmariadb-snapshot --rm -e CONTAINER=testmariadb -e TARGET_DIR=/backup -v ./tmp:/backup {{ .IMAGE }}:{{ .TAG }} local
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										70
									
								
								backup.sh
									
									
									
									
									
								
							
							
						
						
									
										70
									
								
								backup.sh
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -1,17 +1,61 @@
 | 
			
		|||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
set -e
 | 
			
		||||
# Environment variables
 | 
			
		||||
#
 | 
			
		||||
# CONTAINER - name of the container where the database is running
 | 
			
		||||
# RESTIC_PASSWORD
 | 
			
		||||
# RESTIC_REPOSITORY
 | 
			
		||||
# NOTIFY_URL - optional, URL to send notification to
 | 
			
		||||
 | 
			
		||||
if [ "$1" = "local" ]; then
 | 
			
		||||
    source /backup_local.sh
 | 
			
		||||
elif [ "$1" = "restic" ]; then
 | 
			
		||||
    source /backup_restic.sh
 | 
			
		||||
elif [ "$1" = "loop" ]; then
 | 
			
		||||
    # Infinite loop to keep the container running and let Ofelia scheduler (or any other) manage the execution
 | 
			
		||||
    echo "Entering infinite loop mode. Use external scheduler to trigger backups."
 | 
			
		||||
    while true; do
 | 
			
		||||
        sleep 86400
 | 
			
		||||
    done
 | 
			
		||||
else
 | 
			
		||||
    echo "Unknown backup method. Use 'local', 'loop or 'restic'."
 | 
			
		||||
if [ -z "$CONTAINER" ]; then
 | 
			
		||||
    echo "CONTAINER environment variable is not set."
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ -z "$RESTIC_PASSWORD" ]; then
 | 
			
		||||
    echo "RESTIC_PASSWORD environment variable is not set."
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ -z "$RESTIC_REPOSITORY" ]; then
 | 
			
		||||
    echo "RESTIC_REPOSITORY environment variable is not set."
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ ! `docker info` ]; then
 | 
			
		||||
    echo "Docker is not available."
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
echo "Starting backup for container: $CONTAINER"
 | 
			
		||||
if [ `docker exec -i $CONTAINER test -e /usr/bin/mariadb-dump && echo "yes" || echo "no"` = "yes" ]; then
 | 
			
		||||
    DBTYPE="mariadb"
 | 
			
		||||
    docker exec -i $CONTAINER mariadb-dump \
 | 
			
		||||
        --user=root \
 | 
			
		||||
        --password=$MARIADB_ROOT_PASSWORD \
 | 
			
		||||
        --add-drop-trigger \
 | 
			
		||||
        --add-drop-table \
 | 
			
		||||
        --add-drop-database \
 | 
			
		||||
        --hex-blob \
 | 
			
		||||
        --compress \
 | 
			
		||||
        --events \
 | 
			
		||||
        --routines \
 | 
			
		||||
        --single-transaction \
 | 
			
		||||
        --triggers | restic backup --stdin --stdin-filename=$DBTYPE_$CONTAINER_$DB_NAME.sql
 | 
			
		||||
elif [ `docker exec -i $CONTAINER test -e /usr/bin/pg_dump && echo "yes" || echo "no"` = "yes" ]; then
 | 
			
		||||
    DBTYPE="pgsql"
 | 
			
		||||
    docker exec -i $CONTAINER pg_dump --username=$DB_USER --password=$PGPASSWORD $DB_NAME | restic backup --stdin --stdin-filename=$DBTYPE_$CONTAINER_$DB_NAME.sql
 | 
			
		||||
else
 | 
			
		||||
    echo "Unsupported database type or database client not found in the container."
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
echo "Backup completed successfully."
 | 
			
		||||
 | 
			
		||||
echo "Running restic forget and prune..."
 | 
			
		||||
 | 
			
		||||
restic forget --prune --keep-daily 7 --keep-weekly 4
 | 
			
		||||
 | 
			
		||||
if [ -n "$NOTIFY_URL" ]; then
 | 
			
		||||
    curl $NOTIFY_URL
 | 
			
		||||
fi
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,78 +0,0 @@
 | 
			
		|||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
# Environment variables
 | 
			
		||||
#
 | 
			
		||||
# CONTAINER - name of the container where the database is running
 | 
			
		||||
# NOTIFY_URL - optional, URL to send notification to
 | 
			
		||||
# TARGET_DIR - directory where to store the backup
 | 
			
		||||
# HISTORY - number of backups to keep (default: 3)
 | 
			
		||||
 | 
			
		||||
if [ -z "$CONTAINER" ]; then
 | 
			
		||||
    echo "CONTAINER environment variable is not set."
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ -z "$TARGET_DIR" ]; then
 | 
			
		||||
    echo "TARGET_DIR environment variable is not set."
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ -z "$HISTORY" ]; then
 | 
			
		||||
    HISTORY=3
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
docker info > /dev/null 2>&1
 | 
			
		||||
if [ ! $? -eq 0 ]; then
 | 
			
		||||
    echo "Docker is not available."
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ ! -d "$TARGET_DIR" ]; then
 | 
			
		||||
    echo "TARGET_DIR does not exist. Creating it..."
 | 
			
		||||
    exit 2
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
echo "Starting backup for container: $CONTAINER"
 | 
			
		||||
if [ `docker exec -i $CONTAINER test -e /usr/bin/mariadb-dump && echo "yes" || echo "no"` = "yes" ]; then
 | 
			
		||||
    DBTYPE="mariadb"
 | 
			
		||||
    FILENAME=`date +"%Y%m%d_%H%M%S"`_$DBTYPE_$CONTAINER.sql.zst
 | 
			
		||||
    docker exec -i $CONTAINER mariadb-dump \
 | 
			
		||||
        --all-databases \
 | 
			
		||||
        --user=root \
 | 
			
		||||
        --password=$MARIADB_ROOT_PASSWORD \
 | 
			
		||||
        --add-drop-trigger \
 | 
			
		||||
        --add-drop-table \
 | 
			
		||||
        --add-drop-database \
 | 
			
		||||
        --hex-blob \
 | 
			
		||||
        --compress \
 | 
			
		||||
        --events \
 | 
			
		||||
        --routines \
 | 
			
		||||
        --single-transaction \
 | 
			
		||||
        --triggers | zstd -1 > $TARGET_DIR/$FILENAME.tmp
 | 
			
		||||
        mv $TARGET_DIR/$FILENAME.tmp $TARGET_DIR/$FILENAME
 | 
			
		||||
elif [ `docker exec -i $CONTAINER test -e /usr/bin/pg_dump && echo "yes" || echo "no"` = "yes" ]; then
 | 
			
		||||
    DBTYPE="pgsql"
 | 
			
		||||
    FILENAME=`date +"%Y%m%d_%H%M%S"`_$DBTYPE_$CONTAINER.sql.zst
 | 
			
		||||
    docker exec -i $CONTAINER pg_dumpall --username=$DB_USER --password=$PGPASSWORD | zstd -1 > $TARGET_DIR/$FILENAME.tmp
 | 
			
		||||
    mv $TARGET_DIR/$FILENAME.tmp $TARGET_DIR/$FILENAME
 | 
			
		||||
else
 | 
			
		||||
    echo "Unsupported database type or database client not found in the container."
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
echo "Backup completed successfully."
 | 
			
		||||
 | 
			
		||||
# Remove old backups
 | 
			
		||||
echo "Removing old backups, keeping last $HISTORY backups..."
 | 
			
		||||
cd $TARGET_DIR
 | 
			
		||||
ls -1t *_$DBTYPE_$CONTAINER.sql.zst | tail -n +$((HISTORY + 1)) | xargs -r rm --
 | 
			
		||||
cd -
 | 
			
		||||
echo "Old backups removed."
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if [ -n "$NOTIFY_URL" ]; then
 | 
			
		||||
    curl $NOTIFY_URL
 | 
			
		||||
fi
 | 
			
		||||
| 
						 | 
				
			
			@ -1,65 +0,0 @@
 | 
			
		|||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
# Environment variables
 | 
			
		||||
#
 | 
			
		||||
# CONTAINER - name of the container where the database is running
 | 
			
		||||
# RESTIC_PASSWORD
 | 
			
		||||
# RESTIC_REPOSITORY
 | 
			
		||||
# NOTIFY_URL - optional, URL to send notification to
 | 
			
		||||
 | 
			
		||||
if [ -z "$CONTAINER" ]; then
 | 
			
		||||
    echo "CONTAINER environment variable is not set."
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ -z "$RESTIC_PASSWORD" ]; then
 | 
			
		||||
    echo "RESTIC_PASSWORD environment variable is not set."
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ -z "$RESTIC_REPOSITORY" ]; then
 | 
			
		||||
    echo "RESTIC_REPOSITORY environment variable is not set."
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
docker info > /dev/null 2>&1
 | 
			
		||||
if [ ! $? -eq 0 ]; then
 | 
			
		||||
    echo "Docker is not available."
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
echo "Starting backup for container: $CONTAINER"
 | 
			
		||||
if [ `docker exec -i $CONTAINER test -e /usr/bin/mariadb-dump && echo "yes" || echo "no"` = "yes" ]; then
 | 
			
		||||
    DBTYPE="mariadb"
 | 
			
		||||
    docker exec -i $CONTAINER mariadb-dump \
 | 
			
		||||
        --all-databases \
 | 
			
		||||
        --user=root \
 | 
			
		||||
        --password=$MARIADB_ROOT_PASSWORD \
 | 
			
		||||
        --add-drop-trigger \
 | 
			
		||||
        --add-drop-table \
 | 
			
		||||
        --add-drop-database \
 | 
			
		||||
        --hex-blob \
 | 
			
		||||
        --compress \
 | 
			
		||||
        --events \
 | 
			
		||||
        --routines \
 | 
			
		||||
        --single-transaction \
 | 
			
		||||
        --triggers | restic backup --stdin --stdin-filename=$DBTYPE_$CONTAINER.sql
 | 
			
		||||
elif [ `docker exec -i $CONTAINER test -e /usr/bin/pg_dump && echo "yes" || echo "no"` = "yes" ]; then
 | 
			
		||||
    DBTYPE="pgsql"
 | 
			
		||||
    docker exec -i $CONTAINER pg_dumpall --username=$DB_USER --password=$PGPASSWORD | restic backup --stdin --stdin-filename=$DBTYPE_$CONTAINER.sql
 | 
			
		||||
else
 | 
			
		||||
    echo "Unsupported database type or database client not found in the container."
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
echo "Backup completed successfully."
 | 
			
		||||
 | 
			
		||||
echo "Running restic forget and prune..."
 | 
			
		||||
 | 
			
		||||
restic forget --prune --keep-daily 7 --keep-weekly 4
 | 
			
		||||
 | 
			
		||||
if [ -n "$NOTIFY_URL" ]; then
 | 
			
		||||
    curl $NOTIFY_URL
 | 
			
		||||
fi
 | 
			
		||||
		Loading…
	
		Reference in a new issue