# Back up Docker container data folders (stop, archive, restart)

For apps whose data can't be copied safely while they are running, the simple, reliable method is: stop the container, tar its data folder, then start it again. Do this one container at a time, so each app is only down for a moment.

## Assumptions
Each container's data lives in `<base>/<container-name>/` (for example `/srv/docker/sonarr`), and backups go to a mounted share at `/mnt/backup`.

## The script
```
#!/bin/bash
set -uo pipefail                     # no -e: we must always restart the container
BASE=/srv/docker
DEST=/mnt/backup/docker/$(hostname -s)/$(date +%F)
KEEP=14
mountpoint -q /mnt/backup || { echo "backup share not mounted"; exit 1; }
mkdir -p "$DEST"
for c in $(docker ps --format '{{.Names}}'); do
  [[ -d $BASE/$c ]] || { echo "skip $c (no data folder)"; continue; }
  docker stop -t 120 "$c" >/dev/null || { echo "could not stop $c"; continue; }
  if tar -czf "$DEST/$c.tar.gz.part" -C "$BASE" "$c"; then
    mv "$DEST/$c.tar.gz.part" "$DEST/$c.tar.gz"
  else
    echo "backup of $c failed"; rm -f "$DEST/$c.tar.gz.part"
  fi
  docker start "$c" >/dev/null || echo "WARNING: $c did not restart"
done
find "${DEST%/*}" -type f -name '*.tar.gz' -mtime +$KEEP -delete
find "${DEST%/*}" -mindepth 1 -type d -empty -delete
```

## Why no `set -e`
With `set -e`, a failing `tar` (or tar's exit code 1 for "file changed while reading") ends the script **before `docker start`**, leaving the app down. Handle errors explicitly, or add a `trap` that restarts the current container.

## Skip containers whose folder isn't there
Check that the data folder exists **before** stopping the container. Otherwise a wrong `BASE` path means every container is stopped and started for nothing.

## Stacks with databases
If an app and its database are separate containers, stop the app first, then the database, back up both, and start them in reverse order. Or use a proper database dump; see *Back up Docker app SQLite databases without stopping containers*.

## Schedule
```
0 3 * * * root /usr/local/bin/docker_backup.sh >> /var/log/docker-backup.log 2>&1
```

## Restore
`docker stop app`, then `tar -xzf app.tar.gz -C /srv/docker`, then `docker start app`.
