K3s Kubernetes Setup: Lightweight Container Orchestration
Single and multi-node Kubernetes cluster setup with K3s, kubectl usage, creating deployments and services, application management with Helm. Kubernetes guide for VPS environments.
Docker volume backup, container state backup, Kubernetes persistent volume backup, Kubernetes backup with Velero, automated backup scripts, and disaster recovery planning.
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.
| Strategy | Suitable For | Tool |
|---|---|---|
| Volume backup | Database, file storage | tar, rsync |
| Image backup | Application state | docker save |
| Snapshot | Fast recovery | LVM, ZFS |
| K8s backup | Entire cluster | Velero |
| Remote backup | Disaster recovery | Restic, Rclone |
# 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
# 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
#!/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"
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
# 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
# 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
# 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 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
# 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
#!/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
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.
Backup frequency is determined by your RPO (Recovery Point Objective) target. Hourly or more frequent backups for critical databases, daily for application data, weekly for static content. Increasing backup frequency increases disk space and I/O load — keep this balance in mind.
For databases, backup without stopping is recommended when possible: use mysqldump --single-transaction for MySQL, pg_dump for PostgreSQL. For filesystem backups, a brief stop may be needed for consistency. For critical systems, take backups from a read replica.
Check backup status with velero backup describe BACKUP_NAME. Regularly test restoration in a test environment with velero restore create --from-backup BACKUP_NAME. Velero also automatically verifies backup integrity.
Apply the 3-2-1 rule: 3 copies, 2 different media, 1 remote location. A combination of local disk + remote S3-compatible storage (MinIO, AWS S3, Backblaze B2) is recommended. Encrypt backups (Restic encrypts by default). Avoid storing backups on the same server.
You need to back up two things: 1) docker-compose.yml and .env files (should be stored in Git), 2) Volume data (backup with tar). To back up the entire stack, back up each volume separately. For restoration, first start the stack with docker-compose up, then restore the volume data.
Single and multi-node Kubernetes cluster setup with K3s, kubectl usage, creating deployments and services, application management with Helm. Kubernetes guide for VPS environments.
Docker volume types (named, bind mount, tmpfs), volume management, Docker network modes (bridge, host, overlay), creating custom networks and container communication. Comprehensive guide.
Docker log drivers, docker logs command, Kubernetes pod logs, centralized log collection (Loki, ELK Stack), log rotation, and production log management best practices.