Skip to main content
Back to Category

Container Backup: Docker and Kubernetes Data Protection Strategies

Docker volume backup, container state backup, Kubernetes persistent volume backup, Kubernetes backup with Velero, automated backup scripts, and disaster recovery planning.

Read time: 16 dk Container & Orchestration
dockerkubernetesbackupvelerovolumedisaster recoverydata protection

Table of Contents

Container Backup: Data Protection Strategies

Backing up container environments requires a different approach from traditional server backups. Since containers are ephemeral, what needs to be backed up is not the container itself but the data inside it. This guide covers comprehensive backup strategies for Docker and Kubernetes environments.

Choosing a Backup Strategy

StrategySuitable ForTool
Volume backupDatabase, file storagetar, rsync
Image backupApplication statedocker save
SnapshotFast recoveryLVM, ZFS
K8s backupEntire clusterVelero
Remote backupDisaster recoveryRestic, Rclone

1. Docker Volume Backup

Manual Volume Backup

hljs bash
# Backup volume to tar archive
docker run --rm \
  -v VOLUME_NAME:/data \
  -v $(pwd):/backup \
  alpine tar czf /backup/volume-backup-$(date +%Y%m%d).tar.gz -C /data .

# Example: MySQL volume backup
docker run --rm \
  -v mysql-data:/data \
  -v /backups:/backup \
  alpine tar czf /backup/mysql-$(date +%Y%m%d-%H%M%S).tar.gz -C /data .

# Restore volume
docker run --rm \
  -v mysql-data:/data \
  -v /backups:/backup \
  alpine tar xzf /backup/mysql-20240101-120000.tar.gz -C /data

Backup with Running Container

hljs bash
# MySQL dump (while container is running)
docker exec mysql-db mysqldump \
  -u root -pStrongPass123! \
  --all-databases \
  --single-transaction \
  > /backups/mysql-dump-$(date +%Y%m%d).sql

# PostgreSQL dump
docker exec postgres-db pg_dumpall \
  -U postgres \
  > /backups/postgres-dump-$(date +%Y%m%d).sql

# Redis dump
docker exec redis-db redis-cli BGSAVE
docker cp redis-db:/data/dump.rdb /backups/redis-$(date +%Y%m%d).rdb

2. Automated Backup Script

hljs bash
#!/bin/bash
# /usr/local/bin/docker-backup.sh

BACKUP_DIR="/backups/docker"
DATE=$(date +%Y%m%d-%H%M%S)
RETENTION_DAYS=7

mkdir -p "$BACKUP_DIR"

# Backup all volumes
for volume in $(docker volume ls -q); do
  echo "Backing up: $volume"
  docker run --rm \
    -v "$volume":/data \
    -v "$BACKUP_DIR":/backup \
    alpine tar czf "/backup/${volume}-${DATE}.tar.gz" -C /data . 2>/dev/null
  
  if [ $? -eq 0 ]; then
    echo "Success: $volume"
  else
    echo "ERROR: Failed to backup $volume" >&2
  fi
done

# Backup MySQL databases
if docker ps --format '{{.Names}}' | grep -q mysql; then
  docker exec mysql-db mysqldump \
    -u root -pStrongPass123! \
    --all-databases \
    --single-transaction \
    > "$BACKUP_DIR/mysql-${DATE}.sql"
  echo "MySQL backed up"
fi

# Clean up old backups
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +$RETENTION_DAYS -delete
find "$BACKUP_DIR" -name "*.sql" -mtime +$RETENTION_DAYS -delete

echo "Backup completed: $DATE"
hljs bash
chmod +x /usr/local/bin/docker-backup.sh

# Daily backup via cron
crontab -e
# 0 2 * * * /usr/local/bin/docker-backup.sh >> /var/log/docker-backup.log 2>&1

3. Remote Backup with Restic

hljs bash
# Install Restic
apt install -y restic

# Initialize repository (local)
restic init --repo /backups/restic-repo

# Initialize repository (S3-compatible)
export AWS_ACCESS_KEY_ID=ACCESS_KEY
export AWS_SECRET_ACCESS_KEY=SECRET_KEY
restic init --repo s3:https://s3.example.com/bucket-name

# Backup volume
docker run --rm \
  -v mysql-data:/data \
  -v /tmp/mysql-backup:/backup \
  alpine tar czf /backup/mysql.tar.gz -C /data .

restic backup /tmp/mysql-backup \
  --repo /backups/restic-repo \
  --password-file /etc/restic/password \
  --tag mysql,docker

# List backups
restic snapshots --repo /backups/restic-repo

# Restore
restic restore SNAPSHOT_ID \
  --repo /backups/restic-repo \
  --target /tmp/restore

# Clean up old backups
restic forget \
  --repo /backups/restic-repo \
  --keep-daily 7 \
  --keep-weekly 4 \
  --keep-monthly 3 \
  --prune

4. Docker Image Backup

hljs bash
# Save image to tar file
docker save myapp:latest | gzip > /backups/myapp-$(date +%Y%m%d).tar.gz

# Multiple images
docker save myapp:latest nginx:1.25 mysql:8.0 | gzip > /backups/images-$(date +%Y%m%d).tar.gz

# Restore image
docker load < /backups/myapp-20240101.tar.gz

5. Kubernetes Backup: Velero

Installing Velero

hljs bash
# Install Velero CLI
wget https://github.com/vmware-tanzu/velero/releases/download/v1.12.0/velero-v1.12.0-linux-amd64.tar.gz
tar xzf velero-v1.12.0-linux-amd64.tar.gz
mv velero-v1.12.0-linux-amd64/velero /usr/local/bin/

# Install Velero with MinIO (S3-compatible)
velero install \
  --provider aws \
  --plugins velero/velero-plugin-for-aws:v1.8.0 \
  --bucket velero-backups \
  --secret-file ./credentials-velero \
  --use-volume-snapshots=false \
  --backup-location-config region=minio,s3ForcePathStyle=true,s3Url=http://minio:9000

Backup with Velero

hljs bash
# Backup entire cluster
velero backup create full-backup --wait

# Backup specific namespace
velero backup create production-backup \
  --include-namespaces production \
  --wait

# List backups
velero backup get

# Restore from backup
velero restore create --from-backup full-backup

# Restore specific namespace
velero restore create \
  --from-backup production-backup \
  --include-namespaces production

Scheduled Backup

hljs bash
# Daily backup (at 2 AM)
velero schedule create daily-backup \
  --schedule="0 2 * * *" \
  --ttl 168h  # 7 days retention

# Weekly full backup
velero schedule create weekly-backup \
  --schedule="0 1 * * 0" \
  --ttl 720h  # 30 days retention

6. Backup Verification Script

hljs bash
#!/bin/bash
BACKUP_FILE="$1"

if [ -z "$BACKUP_FILE" ]; then
  echo "Usage: $0 <backup_file>"
  exit 1
fi

# Check archive integrity
if tar tzf "$BACKUP_FILE" > /dev/null 2>&1; then
  echo "Backup file is valid: $BACKUP_FILE"
else
  echo "ERROR: Backup file is corrupted: $BACKUP_FILE"
  exit 1
fi

# Test restore in test environment
docker volume create test-restore
docker run --rm \
  -v test-restore:/data \
  -v $(dirname $BACKUP_FILE):/backup \
  alpine tar xzf "/backup/$(basename $BACKUP_FILE)" -C /data

echo "Restore test successful"
docker volume rm test-restore

Conclusion

Container backup strategy should be shaped according to your business requirements. Volume backup + cron may be sufficient for small environments, while dedicated tools like Velero are required for production Kubernetes clusters. With regular backup and restore testing on REXE servers, you can keep your data safe.