Skip to main content

Docker Backup & Restore Strategy

What this is

A standard approach for backing up and restoring all Docker services, configurations, and data across my homelab.

Covers:

  • What to back up
  • How to back it up
  • How to restore quickly after failure

Why I needed this

Without backups:

  • Total data loss if a drive fails
  • Rebuilding containers is easy — rebuilding data is not
  • Time-consuming recovery
  • Risk of losing documents, media metadata, configs

With backups:

  • Fast recovery (minutes instead of hours/days)
  • Safe upgrades and experimentation
  • Confidence to rebuild or migrate systems

My Setup

  • Docker data:
/opt/docker/

  • NAS storage:
/mnt/sjb2/

  • Key services:
    • Jellyfin (media + metadata)
    • Paperless-ngx (documents)
    • Home Assistant (configs)
    • Others (configs only)

What Gets Backed Up

Critical Data (Must Back Up)

/opt/docker/

Includes:

  • docker-compose.yml files
  • .env files
  • config/
  • data/

External Data (Already on NAS)

/mnt/sjb2/

👉 Usually already safe (depending on NAS backup setup)


Optional (Nice to Have)

/var/lib/docker/volumes/

Only needed if using named volumes (generally avoided)


Key Concepts / Options

Backup Types

Type Method Use Case
File-level rsync ✅ Best for homelab
Image backup Clone disk Full system recovery
Cloud backup External sync Offsite protection

Live vs Stopped Backups

Mode Safe Recommended
Live ⚠️ Sometimes Not ideal
Stopped containers ✅ Yes ✅ Best practice

Recommendation

👉 Use rsync + NAS backups + stopped containers

Why:

  • Fast and reliable
  • Easy to automate
  • Works with existing NAS
  • No Docker-specific tooling required

Setup

1. Stop Containers (Safe Backup)

cd /opt/docker
docker compose down

👉 Run per service OR all services if needed


2. Run Backup (rsync)

rsync -avh --delete /opt/docker/ /mnt/sjb2/backups/docker/


3. Restart Containers

docker compose up -d


4. (Optional) Automate with Cron

crontab -e

Example (daily at 2am):

0 2 * * * rsync -avh --delete /opt/docker/ /mnt/sjb2/backups/docker/


Configuration

Suggested Backup Structure

/mnt/sjb2/backups/
├── docker/
│ ├── jellyfin/
│ ├── paperless/
│ ├── homeassistant/


Optional: Per-Service Backup

rsync -avh /opt/docker/jellyfin/ /mnt/sjb2/backups/docker/jellyfin/


Permissions Notes

  • Preserve ownership:
rsync -avh

  • Fix if needed:
sudo chown -R 1000:1000 /opt/docker


Verification

Check backup contents:

ls /mnt/sjb2/backups/docker/

Test restore (recommended occasionally):

cp -r /mnt/sjb2/backups/docker/jellyfin /opt/docker/test-restore


Restore (Full System)

1. Install base system

  • Ubuntu Server
  • Docker
  • Docker Compose

(Use baseline page)


2. Restore Files

rsync -avh /mnt/sjb2/backups/docker/ /opt/docker/


3. Start Services

cd /opt/docker/<service>
docker compose up -d


Restore (Single Service)

1. Stop service (if exists)

cd /opt/docker/jellyfin
docker compose down


2. Restore files

rsync -avh /mnt/sjb2/backups/docker/jellyfin/ /opt/docker/jellyfin/


3. Start service

docker compose up -d


Common Problems / Fixes

Data missing after restore

  • Cause: Wrong path restored
  • Fix:
  • Verify volume mappings in compose file

Permission errors after restore

  • Cause: Ownership mismatch
  • Fix:
sudo chown -R 1000:1000 /opt/docker


Containers start but configs reset

  • Cause: Config folder not backed up
  • Fix:
  • Ensure /config is inside /opt/docker

rsync deletes wrong files

  • Cause: Misuse of --delete
  • Fix:
  • Double-check source/destination before running

Result

  • Full server recoverable in minutes
  • Services restored with configs intact
  • Minimal downtime after failure
  • Safe environment for testing and upgrades

Notes

  • Always test restores occasionally
  • Backups are useless if untested
  • Keep at least:
    • 1 local backup (NAS)
    • 1 offsite backup (optional but ideal)
  • Avoid relying on Docker volumes alone
  • Consider future improvements:
    • Snapshot-based NAS backups
    • Versioned backups
    • Cloud sync for critical data