Зачем разные drivers
Image-слои, read-only. Контейнер пишет, нужен writable layer поверх. Старые ФС не могли это сделать эффективно, поэтому Docker поддерживал несколько storage drivers, каждый со своим подходом.
Сегодня overlay2 покрывает 95% случаев, но знать остальные стоит, встретится в legacy и в прод-сценариях с особыми требованиями.
Где живёт всё это:
/var/lib/docker/
├── overlay2/ ← если driver = overlay2
│ ├── <layer-hash>/
│ │ ├── diff/ ← файлы конкретного слоя
│ │ ├── lower ← список нижних слоёв
│ │ └── work/ ← рабочая директория overlayfs
├── containers/
└── image/
Какой driver сейчас:
docker info | grep -i storage
# Storage Driver: overlay2
# Backing Filesystem: extfs
overlay2, default
Использует [[tmpfs-overlayfs|overlayfs]] из ядра. Image-слои
read-only lower, container-changes, upper.
Плюсы:
- В ядре, без userspace-overhead
- Page cache shared между контейнерами с одним base image
- Быстрый startup, overlay-mount копеечный
Минусы:
- Inode usage растёт быстро, copy-up at write копирует целые файлы. Большие файлы с маленькими правками = двойной расход
- Не любит много слоёв, kernel-limit на nested overlay около 128
Backing filesystem: ext4, xfs (с ftype=1), btrfs, ext4,
[[tmpfs-overlayfs|tmpfs]] (для rootless через user-namespace).
Для XFS обязательно при mkfs:
mkfs.xfs -f -n ftype=1 /dev/sdb1
Иначе overlay2 откажется работать (d_type отсутствует).
btrfs, native CoW
Использует [[btrfs|btrfs]] subvolumes и snapshots:
- Каждый слой, subvolume
- Container layer, snapshot последнего image-subvolume
- Записи внутри контейнера, copy-on-write на уровне ФС
Плюсы:
- Снапшот за O(1)
- Дедупликация на уровне FS-блоков
btrfs scrubнаходит bit rot
Минусы:
- Вся
/var/lib/dockerдолжна быть на btrfs - Btrfs не любит near-full ФС
- На high-write workload фрагментация бьёт перформанс
- В 2026 не дефолт нигде, нишевый выбор
# daemon.json
{ "storage-driver": "btrfs" }zfs, enterprise CoW
Аналогично btrfs, но через ZFS:
- Каждый слой, zfs filesystem
- Container, clone последнего слоя
- Внутри,
zfs send/receiveдля миграции
Плюсы:
- ZFS-grade reliability (ARC, scrubs, raid-z)
- Дедупликация (если включена)
- Snapshots дёшевы
Минусы:
- ZFS не в mainline kernel, нужен ZoL (zfs-on-Linux), CDDL+GPL лицензионные дрязги
- RAM-голодный (ARC ест free-memory)
- Production-стек редкий, в основном TrueNAS / Solaris-наследники
Для контейнеров, обычно перебор, кроме особых случаев (storage-server).
devicemapper, legacy
Создаёт thin-pool на блочных устройствах, каждый layer, отдельный thin LV.
Раньше дефолт на RHEL 7. Deprecated, удалён из Docker 23+ (2023). Не используй.
vfs, fallback
Просто рекурсивно копирует файлы между layers. Никакой CoW.
- Огромный disk usage
- Очень медленный pull
- Работает на любой ФС
Дефолт rootless-Docker без user-namespaces overlay-permissions. Для prod, никогда.
fuse-overlayfs, rootless
В rootless-Docker/Podman обычный overlayfs не работает (нужен CAP_SYS_ADMIN для mount). FUSE-version делает то же в userspace:
# Podman rootless по умолчанию
podman info | grep -i graphdriver
# graphDriverName: overlay
# ... mountopt: nodev,fsync=0
Современные ядра 5.11+ имеют rootless-overlayfs через user-namespaces,
и overlay работает без FUSE, быстрее. Но FUSE нужен для старых ядер.
Сравнение
| Driver | Backing | CoW level | Рекомендация |
|---|---|---|---|
| overlay2 | ext4/xfs/btrfs | overlayfs (file) | default, 95% случаев |
| btrfs | btrfs | btrfs subvol/snapshot (block) | если уже есть btrfs |
| zfs | zfs | zfs clone (block) | enterprise NAS |
| devicemapper | thin pool | LVM thin (block) | deprecated |
| vfs | любая | none (full copy) | тестовый/fallback |
| fuse-overlayfs | любая | userspace overlay | rootless legacy |
Performance: large-write проблема overlay2
Overlay2 делает copy-up на write: при первой записи в файл из read-only layer весь файл копируется в writable layer. Если файл 10 GB и меняется 1 байт, копия 10 GB.
Для БД и VM-images это убийственно. Решения:
- Volume / bind-mount для data-directory:
bashVolume лежит вне overlay, без copy-up.
docker run -v /var/lib/postgres-data:/var/lib/postgresql/data postgres
- chattr +C на host-директорию если backing, btrfs ([[btrfs|см.]])
- tmpfs для эфемерных каталогов:
bash
docker run --tmpfs /tmp:size=100M ...
Storage size limits
По умолчанию контейнер может занять весь диск (до full-FS). Лимит:
docker run --storage-opt size=10G ...
Работает только на storage drivers с native quota:
- overlay2 + xfs+pquota, да
- btrfs, да через subvolume quota
- devicemapper, да (thin pool)
- overlay2 + ext4, нет
Альтернатива: docker-compose с storage_opt: или k8s
ephemeral-storage requests/limits.
Очистка disk usage
docker system df # сколько занято
docker image prune # неиспользуемые images
docker container prune # остановленные
docker volume prune # unmounted volumes
docker builder prune # build cache
docker system prune -a --volumes # ВСЁ (опасно, удалит images)
# Точечно: какие layers и их размер
du -sh /var/lib/docker/overlay2/* | sort -h | tail
Большой /var/lib/docker/overlay2/, норма для CI-runner'ов;
prune раз в день, must.
Когда что-то пошло не так
failed to register layer: ApplyLayer exit status 1, обычно backing FS не поддерживает overlay (vfat) или место кончилось.device or resource busyпри docker rm, overlay-mount держится.docker stopсначала, или kill процессов из контейнера черезdocker top.d_type is not supportedна XFS, сделан безftype=1. Только пересоздать ФС с правильным mkfs.No space left on deviceпри свободных GB, кончились inode на ext4 (df -i). Overlay создаёт много мелких файлов. Пересоздать сmkfs.ext4 -i 4096.- Очень медленный pull, много мелких слоёв (
docker historyпокажет 50+). При build объединяй RUN-команды. /var/lib/dockerраспух непомерно, старые dangling images, container exit'ed но не удалены, build-cache.docker system df, потом prune.- Контейнерный write на shared volume "пропадает", другой контейнер на той же volume записал поверх. Volume, не overlay, последний writer wins.
Альтернативные runtime'ы и их storage
- podman, подобные drivers (overlay, vfs); rootless =
overlayчерез user-NS - containerd имеет свой "snapshotter" subsystem: native, overlayfs, btrfs, devmapper. Стандарт для k8s.
- CRI-O, overlay (default) или vfs