U principle §6: bind mounts only, never named volumes
Promote 'don't use named volumes' from a mysql/redis-specific explanation to a hard rule that applies to anything needing persistence (ssh host keys, uploads, queue state, etc). Lead with the 'docker compose down -v wipes named volumes' rationale since that's the keystroke this rule is really protecting against. Add a counter-pattern example.
This commit is contained in:
parent
1d1a3b32f9
commit
2589d4baf4
|
|
@ -393,30 +393,64 @@ that's why each one starts with the app's slug.
|
|||
|
||||
---
|
||||
|
||||
## 6. Persistent data: `./docker-data/` in the repo, gitignored
|
||||
## 6. Persistent data: `./docker-data/` bind mounts, never named volumes
|
||||
|
||||
Bind-mount mysql and redis storage to a `docker-data/` folder right next
|
||||
to the source:
|
||||
**Rule: any service that needs to keep state between container restarts
|
||||
gets a bind mount under `./docker-data/<service>/`. Never a named docker
|
||||
volume.** This applies to mysql, redis, ssh host keys, app uploads,
|
||||
queue state, every "this dir needs to survive" case — same shape, same
|
||||
location, no exceptions.
|
||||
|
||||
```
|
||||
docker-data/
|
||||
mysql/ # mysql:8.0 datadir
|
||||
redis/ # redis dump.rdb
|
||||
… # whatever else needs persistence
|
||||
```
|
||||
|
||||
The folder is gitignored (`docker-data/` in `.gitignore`). It survives
|
||||
`docker compose down`. The deploy script `mkdir -p`s it on first run so
|
||||
fresh boxes Just Work.
|
||||
The folder is gitignored (`docker-data/` in `.gitignore`). The deploy
|
||||
script `mkdir -p`s it on first run so fresh boxes Just Work.
|
||||
|
||||
### Why not named docker volumes?
|
||||
### Why bind mounts, not named volumes
|
||||
|
||||
The headline reason: **`docker compose down -v` wipes named volumes**.
|
||||
That command is in too many people's muscle memory ("nuke the stack and
|
||||
start clean") for the production datastore to be one accidental keystroke
|
||||
away from gone. Bind mounts under the repo are immune — `down -v`
|
||||
doesn't touch them.
|
||||
|
||||
The rest of the rationale:
|
||||
|
||||
- Trivially backed up — `tar -caf data.tar.xz docker-data/` from the
|
||||
repo root is the entire prod state.
|
||||
- Survives container/image churn including accidental
|
||||
`docker volume prune -af`.
|
||||
`docker volume prune -af` and `docker system prune --volumes`.
|
||||
- Discoverable — anyone with the repo can see where the data lives.
|
||||
- The repo path identifies which app owns the data when you have ten
|
||||
apps on one host.
|
||||
- Restoring on a new host is `git clone && rsync docker-data/` — no
|
||||
per-volume `docker volume create && docker run --rm -v ... tar` dance.
|
||||
|
||||
### Counter-pattern (do not do this)
|
||||
|
||||
```yaml
|
||||
# WRONG — named volume; `docker compose down -v` deletes the data.
|
||||
services:
|
||||
mysql:
|
||||
volumes:
|
||||
- mysql-data:/var/lib/mysql
|
||||
|
||||
volumes:
|
||||
mysql-data:
|
||||
```
|
||||
|
||||
```yaml
|
||||
# RIGHT — bind mount; survives `down -v`.
|
||||
services:
|
||||
mysql:
|
||||
volumes:
|
||||
- ./docker-data/mysql:/var/lib/mysql
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue