🌌 Пласти міста-привида — С.І.Д. із гордістю розкладає на екрані власний образ на пласти — ті самі райони, покладені один на одного, які показує docker history: розберися, як OverlayFS склеює їх в одну вулицю, куди лягає все, що контейнер записує за сеанс, і чому нижні пласти ніхто не чіпає — тож із того самого образу можна підняти привида знову й знову, на будь-якій машині, куди він дотягнеться мережею.
Docker-образ (image) — це не один файл, а впорядкований стос незмінних (read-only) шарів (layers), кожен
із яких відповідає одній інструкції Dockerfile (RUN, COPY, ADD), що змінює
файлову систему. Шари ідентифікуються за вмістом (хешем), тому шар, ідентичний уже
завантаженому в іншому образі, не завантажується вдруге — саме тому спільна базова
інструкція FROM ubuntu:24.04 у десятках образів займає місце на диску лише один раз.
Переглянути список шарів конкретного образу можна командою docker history <image>
(людяний вивід, з розміром і командою кожного шару) або docker inspect <image> у полі
RootFS.Layers (точні digest-и).
Об'єднання цих незмінних шарів у єдине дерево файлів виконує OverlayFS — драйвер
файлової системи ядра Linux, що працює за принципом «union mount». У термінах overlayfs
є чотири ключові каталоги: lowerdir — один або декілька шарів лише для читання
(у Docker це шари образу, з'єднані в порядку від найновішого до найстарішого);
upperdir — єдиний шар, доступний на запис, що створюється окремо для кожного
запущеного контейнера; workdir — службовий каталог, який overlayfs використовує
внутрішньо для атомарних операцій (обов'язковий, але «прозорий» для користувача); і
merged — фінальна точка монтування, яку контейнер бачить як свій корінь / —
логічно об'єднаний вигляд усіх lowerdir і upperdir разом.
Ключовий механізм — copy-on-write (CoW). Коли процес усередині контейнера читає файл, що існує лише в lowerdir, overlayfs віддає його напряму з lowerdir без копіювання. Але щойно процес намагається змінити цей файл, спрацьовує стратегія «copy-up»: файл повністю копіюється в upperdir, і вже там застосовується зміна — оригінал у lowerdir лишається недоторканим. Видалення файлу, який існує в lowerdir, реалізується не фізичним видаленням (це неможливо — lowerdir лише для читання), а створенням спеціального «whiteout»-запису в upperdir, який каже overlayfs «приховати цей файл із merged-подання».
Саме тому docker rm <container> видаляє контейнер практично миттєво і без ризику
для образу: видаляється лише upperdir (і workdir) цього конкретного контейнера — тонкий
шар усіх змін, зроблених під час сеансу. Базові lowerdir-шари образу лишаються
незайманими й готовими для наступного docker run того самого образу — звідси
запуск нового контейнера з уже завантаженого образу настільки швидкий: нічого
не копіюється заздалегідь, лише монтується новий порожній upperdir поверх спільних
lowerdir.
Побачити реальні шляхи цих каталогів для конкретного контейнера можна командою
docker inspect <container> --format '{{json .GraphDriver.Data}}' — вона поверне
поля LowerDir, UpperDir, MergedDir, WorkDir як абсолютні шляхи на хості
(типово під /var/lib/docker/overlay2/), що робить абстракцію цілком відчутною —
можна зазирнути в upperdir напряму й побачити файли, які контейнер створив або
змінив за час роботи.
Прочитати ядрову документацію Documentation/filesystems/overlayfs.rst (lowerdir/upperdir/merged/workdir) і виконати docker inspect
У якому з каталогів OverlayFS (lowerdir, upperdir, merged) з'являються файли, які контейнер створив під час роботи, і чому вони зникають після docker rm?
.pixel, якого ніхто не додавав. Стерти його з контейнера можна лише «білою дірою» (whiteout) у верхньому шарі, а в lowerdir він лежить далі — і проступає знову з кожного нового контейнера. «Деякі речі, ранере, лежать глибше за upperdir. Кіт із них перший».Кожна команда терміналу з цієї сторінки — одним реченням. Позначка нове — команда зустрічається в курсі вперше; далі вважаємо її знайомою.
docker inspect-f '{{.State.Pid}}' — витягнути одне поле.dockerdocker <підкоманда> --help — довідка).python3python3 -m http.server 80, найкоротший спосіб підняти тестовий HTTP-сервер.lsls -la — з правами, власником, розміром і прихованими файлами.findновеfind . -name '*.rs').docker historydocker rmdocker rm -f name — навіть якщо він ще працює).docker rundocker run -it ubuntu:24.04 bash — інтерактивно з терміналом; -d — у фоні; --rm — видалити після виходу; -p 8080:80 — прокинути порт).💡 Прочитати README прямо в терміналі: cat README.md (виведе весь файл) або less README.md (посторінково; вихід — клавіша q).
Довідка з будь-якої команди: man curl (повний посібник, вихід — q) або коротко curl --help; для підкоманд — docker run --help, cargo build --help.