docker-stacks-backup: add init command, output formatting, progress indicators, and bugfixes
New features: - init command: inject default x-backup config into compose files - --dir flag: scan a custom directory for stacks - --to flag: override restore target path Bugfixes: - resolve_docker_volume: no longer double-prefixes volume names - metadata has_volumes now correctly tracks volume state - warn_named_volumes message now accurate about backup-volumes setting Output formatting: - Terminal colors via tput (auto-disabled on non-TTY) - Unicode symbols: ✓ ● ℹ ⚠ ✗ ◇ - Section headers with ━━━ separators - Colored verify results (green OK, red FAIL, yellow SKIP) - Cleaner interactive menus with colored prompts Progress indicators (no dependencies): - tar --checkpoint shows live byte progress during backup/restore - Graceful fallback when checkpoint unavailable or non-TTY
This commit is contained in:
@@ -60,7 +60,9 @@ The script finds stacks in three ways:
|
||||
|------|---------------|
|
||||
| `--all` | Every subdirectory of the **script's directory** containing a compose file |
|
||||
| `--running` | All running compose projects **anywhere on the filesystem** by reading `ConfigFiles` from `docker compose ls --format json` |
|
||||
| `--stack <spec>` | A specific stack by name (relative to the script's directory) or by absolute path |
|
||||
| `--stack <spec>` | A specific stack by name (relative to the **current directory**) or by absolute path |
|
||||
|
||||
Add `--dir <path>` to any command to override the default scan directory (script dir for backup/restore, current dir for init).
|
||||
|
||||
### External Stacks
|
||||
|
||||
@@ -76,6 +78,23 @@ This is useful for ad-hoc backups of stacks that aren't under your main stacks d
|
||||
|
||||
## Usage
|
||||
|
||||
### Init
|
||||
|
||||
```bash
|
||||
# Inject default x-backup config into all stacks in the current directory
|
||||
./docker-stack-backup.sh init
|
||||
|
||||
# Or specify a directory to scan (no cd needed)
|
||||
./docker-stack-backup.sh init --dir /mnt/data/stacks
|
||||
|
||||
# Or target specific stacks
|
||||
./docker-stack-backup.sh init --running
|
||||
./docker-stack-backup.sh init --stack random_stack
|
||||
./docker-stack-backup.sh init --stack /srv/docker/nextcloud
|
||||
./docker-stack-backup.sh init -s stack_a -s stack_b
|
||||
./docker-stack-backup.sh init --dry-run --verbose # preview changes
|
||||
```
|
||||
|
||||
### Backup
|
||||
|
||||
```bash
|
||||
@@ -94,6 +113,9 @@ This is useful for ad-hoc backups of stacks that aren't under your main stacks d
|
||||
./docker-stack-backup.sh backup -s stack_a -s stack_b
|
||||
./docker-stack-backup.sh backup --stack stack_a,stack_b
|
||||
|
||||
# Scan a specific directory for stacks instead of the script's directory
|
||||
./docker-stack-backup.sh backup --dir /srv/docker --all
|
||||
|
||||
# With a custom backup destination
|
||||
./docker-stack-backup.sh backup --all --backup-dir /mnt/nfs/backups
|
||||
|
||||
@@ -128,6 +150,9 @@ After selecting stacks, the script re-executes via `sudo` with your selections a
|
||||
# Restore an external stack by path
|
||||
./docker-stack-backup.sh restore --stack /srv/docker/nextcloud
|
||||
|
||||
# Restore to a different location (overrides the original path)
|
||||
./docker-stack-backup.sh restore --stack random_stack --to /new/location/random_stack
|
||||
|
||||
# Restore from a specific backup directory
|
||||
./docker-stack-backup.sh restore --stack random_stack --backup-dir /mnt/nfs/backups
|
||||
```
|
||||
@@ -149,6 +174,38 @@ After selecting backups, the script re-executes via `sudo` with the resolved sta
|
||||
|
||||
When restoring over an existing stack directory, the current directory is briefly renamed to `<stack>.pre-restore-<timestamp>` as a safety net during extraction. Once the restore completes successfully, the pre-restore copy is removed — the backup archive is the authoritative restore point. Any stale pre-restore directories from previous failed restores are cleaned up automatically.
|
||||
|
||||
### Init (Inject Default Config)
|
||||
|
||||
```bash
|
||||
# Inject default x-backup config into all stacks in the current directory
|
||||
./docker-stack-backup.sh init
|
||||
|
||||
# Or target running/external stacks
|
||||
./docker-stack-backup.sh init --running
|
||||
./docker-stack-backup.sh init --stack /srv/docker/nextcloud
|
||||
```
|
||||
|
||||
Scans each compose file (relative to the **current directory** by default, or use `--dir` to point elsewhere) and injects a default `x-backup` block at the top:
|
||||
|
||||
```yaml
|
||||
x-backup:
|
||||
stop: true
|
||||
backup-volumes: true
|
||||
# pre-hook: ""
|
||||
# post-hook: ""
|
||||
# pre-restore-hook: ""
|
||||
# post-restore-hook: ""
|
||||
# exclude:
|
||||
# - path/to/exclude
|
||||
# retention: 7
|
||||
```
|
||||
|
||||
Active defaults (`stop: true`, `backup-volumes: true`) are uncommented. Optional fields are commented out as a reference — uncomment and adjust as needed.
|
||||
|
||||
If the compose file already has an `x-backup:` block, it is removed first so the result is always a clean standard config. This makes `init` idempotent and safe to re-run at any time.
|
||||
|
||||
Does not require root by default — reads and writes compose files as the current user. If a compose file is owned by another user (e.g. root), the script automatically escalates with `sudo` for the write.
|
||||
|
||||
### Verify
|
||||
|
||||
```bash
|
||||
@@ -383,7 +440,7 @@ Or as a cron job on the host (in root's crontab, or use `sudo`):
|
||||
|
||||
## Requirements
|
||||
|
||||
- **Root access** — backup and restore require root because `tar --same-permissions --preserve-permissions` only preserves UID/GID ownership when running as root. The script automatically re-executes via `sudo` when needed. Read-only commands (`list`, `verify`, and the interactive menus) run without elevation.
|
||||
- **Root access** — backup and restore require root because `tar --same-permissions --preserve-permissions` only preserves UID/GID ownership when running as root. The script automatically re-executes via `sudo` when needed. Read-only commands (`list`, `verify`, and the interactive menus) run without elevation. The `init` command also runs without root by default, but auto-escalates with `sudo` if the compose file isn't writable by the current user.
|
||||
|
||||
When run via `sudo`, the backup archives (`.tar.gz` and `.meta` files) are automatically `chown`ed back to the original user so you can list, copy, or delete them without root.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user