Модуль 9 / 18
Данные: volumes, bind mounts, tmpfs и backup
Содержание
1. Цели и модель данных
Вы научитесь выбирать volume, bind mount или tmpfs, ограничивать доступ и проверять восстановление backup.
- writable layer принадлежит контейнеру
- volume живёт независимо
- bind mount связан с host path
- tmpfs эфемерен
- backup подтверждается restore
2. Теория: writable layer и mount
Root filesystem объединяет read-only image layers с writable layer. Copy-on-write удобен для временного state, но удаляется вместе с контейнером.
Mount скрывает image-файлы в destination до отключения. Два набора данных автоматически не объединяются.
3. Теория: volumes
Named volume — объект Engine с именем, driver, labels и mountpoint. Удаление контейнера не удаляет volume. Одновременную запись должны поддерживать приложение и filesystem.
Внутренний путь local driver не является переносимым API; внешний driver наследует свойства storage backend.
4. Теория: bind mounts и права
Bind mount показывает container существующий host path и привязывает workload к машине. --mount ошибается при отсутствующем source, а legacy -v может молча создать каталог.
Ядро проверяет числовые UID/GID; также действуют SELinux/AppArmor labels. Без необходимости записи используйте readonly.
5. Теория: tmpfs
tmpfs не попадает в writable layer и очищается с контейнером. Он подходит для sockets, cache и временных secrets, но не заменяет secret manager.
Лимитируйте размер: память учитывается cgroup и может вызвать OOM; swap зависит от host policy.
6. Теория: backup, RPO и RTO
Файловая копия при активной записи может быть несогласованной. Для database нужен native dump/snapshot или quiesce, а не tar живого datadir.
Проверяйте checksum и metadata, восстанавливайте в новый volume. RPO задаёт допустимую потерю, RTO — время восстановления.
7. Методические указания
- Классифицируйте path: immutable, persistent или ephemeral
- Предпочитайте --mount
- Не монтируйте /, /etc или docker.sock
- Используйте readonly
- Планируйте UID/GID и LSM labels
- Не удаляйте volume до evidence и backup
- Регулярно тестируйте restore
8. Лабораторная работа
Докажите разные жизненные циклы и запрет записи.
docker volume create docker-m9-data
docker run --name docker-m9-writer --mount type=volume,src=docker-m9-data,dst=/data alpine:3.21 sh -c 'printf "persistent data\n" > /data/message.txt; sha256sum /data/message.txt'
docker rm docker-m9-writer
docker volume inspect docker-m9-data
docker run --rm --mount type=volume,src=docker-m9-data,dst=/data,readonly alpine:3.21 sh -c 'cat /data/message.txt; sha256sum /data/message.txt; if touch /data/forbidden 2>/dev/null; then exit 1; else echo read_only=enforced; fi'mkdir -p /tmp/docker-module-09/backup
printf 'host input\n' > /tmp/docker-module-09/input.txt
docker run --rm --mount type=bind,src=/tmp/docker-module-09,dst=/workspace alpine:3.21 sh -c 'stat -c "uid=%u gid=%g mode=%a" /workspace/input.txt; printf "container output\n" > /workspace/output.txt'
stat -c 'uid=%u gid=%g mode=%a path=%n' /tmp/docker-module-09/output.txt
docker run --rm --mount type=bind,src=/tmp/docker-module-09,dst=/workspace,readonly alpine:3.21 sh -c 'if touch /workspace/forbidden 2>/dev/null; then exit 1; else echo read_only=enforced; fi'docker run -d --name docker-m9-tmpfs --mount type=tmpfs,dst=/run/course,tmpfs-size=16m,tmpfs-mode=0700 alpine:3.21 sh -c 'printf "ephemeral\n" > /run/course/state; sleep 300'
docker inspect docker-m9-tmpfs --format '{{json .Mounts}}'
docker exec docker-m9-tmpfs sh -c 'cat /run/course/state; df -h /run/course; stat -c "mode=%a" /run/course'
docker rm -f docker-m9-tmpfs
docker run --rm --mount type=tmpfs,dst=/run/course alpine:3.21 sh -c 'test ! -e /run/course/state && echo new_tmpfs=empty'Создайте backup вне source volume и восстановите его отдельно.
docker run --rm --mount type=volume,src=docker-m9-data,dst=/source,readonly --mount type=bind,src=/tmp/docker-module-09/backup,dst=/backup alpine:3.21 tar -C /source -czf /backup/data.tgz .
sha256sum /tmp/docker-module-09/backup/data.tgz
tar -tzf /tmp/docker-module-09/backup/data.tgz
docker volume create docker-m9-restore
docker run --rm --mount type=volume,src=docker-m9-restore,dst=/restore --mount type=bind,src=/tmp/docker-module-09/backup,dst=/backup,readonly alpine:3.21 tar -C /restore -xzf /backup/data.tgz
docker run --rm --mount type=volume,src=docker-m9-restore,dst=/data,readonly alpine:3.21 sha256sum /data/message.txtКритерий: checksum совпадает, readonly запрещает запись, новый tmpfs пуст.
9. Диагностика данных и Permission denied
Сначала проверьте context и Mounts. Не исправляйте проблему через --privileged или chmod 777.
docker volume inspect docker-m9-data
docker system df --verbose
df -h /var/lib/docker 2>/dev/null || true
findmnt /var/lib/docker 2>/dev/null || true
stat -c 'uid=%u gid=%g mode=%a path=%n' /tmp/docker-module-09 /tmp/docker-module-09/input.txt- inspect .Mounts: Type, Source, Destination, RW
- volume inspect: имя, driver, scope
- stat: UID/GID и mode
- df/findmnt: capacity и read-only state
- logs, events и LSM audit
10. Контроль и cleanup
- Почему writable layer не persistent?
- Volume или bind mount?
- Почему --mount безопаснее -v?
- Что скрывает mountpoint?
- Как влияют UID/GID?
- Когда tar несогласован?
- Как tmpfs связан с OOM?
- Зачем restore test?
docker rm -f docker-m9-tmpfs 2>/dev/null || true
docker volume rm docker-m9-data docker-m9-restore
rm -f /tmp/docker-module-09/backup/data.tgz /tmp/docker-module-09/input.txt /tmp/docker-module-09/output.txt
rmdir /tmp/docker-module-09/backup /tmp/docker-module-09
docker volume lsМодуль освоен, если вы выбираете верный lifecycle и воспроизводимо восстанавливаете данные в новый volume.