Пошук уроків, статей та іншого контенту
Підключайте іменовані томи та локальні каталоги до контейнерів для роботи з файлами.
Файлова система контейнера за замовчуванням є тимчасовою. Якщо контейнер видалити, зміни у файлах усередині нього зазвичай будуть втрачені.
Volume і bind mount дають змогу зберігати або підключати файли поза файловою системою контейнера:
іменований том (named volume) зберігається під керуванням Docker;
bind mount підключає конкретний каталог або файл із хост-системи.
Обидва варіанти монтуються у файлову систему контейнера за певним шляхом, наприклад /app/data.
Іменований том має назву, яку призначає користувач. Docker сам визначає, де фізично зберігати його дані.
Створити том можна командою:
docker volume create app-dataПереглянути список томів:
docker volume lsОтримати інформацію про конкретний том:
docker volume inspect app-dataТом підключається до контейнера за допомогою параметра --mount:
docker run --rm \
--mount type=volume,source=app-data,target=/data \
alpine \
sh -c 'echo "Дані збережено" > /data/message.txt'У цьому прикладі:
type=volume означає, що використовується Docker volume;
source=app-data — назва тому;
target=/data — каталог усередині контейнера;
файл /data/message.txt записується у том, а не лише у тимчасову файлову систему контейнера.
Після завершення контейнера том залишається. Його можна підключити до іншого контейнера:
docker run --rm \
--mount type=volume,source=app-data,target=/data \
alpine \
cat /data/message.txtКоманда виведе:
Дані збереженоВидалення контейнера не видаляє іменований том:
docker rm container_nameАле окрема команда видаляє сам том разом із його даними:
docker volume rm app-dataВидаляйте том лише тоді, коли його дані більше не потрібні.
-vДля монтування тому можна використовувати короткий синтаксис:
docker run --rm \
-v app-data:/data \
alpine \
ls -la /dataФормат:
volume_name:container_path[:options]Наприклад, параметр ro монтує том лише для читання:
docker run --rm \
-v app-data:/data:ro \
alpine \
cat /data/message.txtПорівняно з -v, синтаксис --mount довший, але явно описує кожен параметр і зручніший для складних команд.
Bind mount використовує конкретний шлях на хост-системі. Це зручно, коли:
застосунок повинен бачити файли з локальної машини;
зміни у вихідному коді мають одразу з’являтися в контейнері;
потрібно віддати контейнеру готовий каталог із конфігурацією або статичними файлами.
Створимо локальний каталог і файл:
mkdir -p ./site
printf '<h1>Сторінка з bind mount</h1>\n' > ./site/index.htmlПідключимо його до контейнера Nginx:
docker run --rm \
--mount type=bind,source="$PWD/site",target=/usr/share/nginx/html,readonly \
-p 8080:80 \
nginx:alpineТут:
type=bind вказує на bind mount;
source="$PWD/site" — каталог на хост-системі;
target=/usr/share/nginx/html — каталог у контейнері;
readonly забороняє контейнеру змінювати локальні файли;
-p 8080:80 публікує порт Nginx.
Поки контейнер працює, зміна локального файлу змінює вміст, який бачить Nginx:
printf '<h1>Оновлена сторінка</h1>\n' > ./site/index.htmlДля bind mount контейнер використовує саме локальний шлях. Якщо файл або каталог змінити на хості, зміни будуть доступні всередині контейнера.
-vТой самий bind mount за допомогою короткого синтаксису:
docker run --rm \
-v "$PWD/site:/usr/share/nginx/html:ro" \
-p 8080:80 \
nginx:alpineФормат:
host_path:container_path[:options]У Linux і macOS "$PWD" означає поточний каталог у shell. Під час використання PowerShell шлях можна передати через $PWD, але синтаксис лапок і змінних залежить від оболонки.
--mount і -v: важлива відмінністьДля bind mount ці синтаксиси по-різному поводяться, якщо локальний шлях не існує.
--mountЯкщо вихідний каталог не існує, Docker повідомить про помилку:
docker run --rm \
--mount type=bind,source="$PWD/missing",target=/data \
alpine \
ls /dataЦе допомагає не підключити випадково неправильний шлях.
-vКороткий синтаксис може автоматично створити відсутній каталог на хості:
docker run --rm \
-v "$PWD/missing:/data" \
alpine \
ls /dataЧерез це легко отримати порожній каталог замість очікуваних файлів. Перед використанням bind mount бажано явно створювати й перевіряти локальний шлях.
За замовчуванням монтування доступне для читання і запису. Якщо контейнеру не потрібно змінювати файли, використовуйте режим лише для читання.
Через --mount:
docker run --rm \
--mount type=bind,source="$PWD/site",target=/site,readonly \
alpine \
sh -c 'cat /site/index.html'Через -v:
docker run --rm \
-v "$PWD/site:/site:ro" \
alpine \
sh -c 'cat /site/index.html'Це зменшує ризик, що процес у контейнері випадково видалить або перезапише файли на хості.
Переваги:
Docker керує розташуванням даних;
не потрібно знати конкретний шлях у файловій системі Docker;
зручно зберігати дані сервісів між перезапусками контейнерів;
том легко підключити до кількох контейнерів.
Приклад:
docker run --rm \
--mount type=volume,source=app-data,target=/var/lib/app \
alpineПереваги:
доступ до файлів безпосередньо з хост-системи;
зміни локальних файлів одразу доступні контейнеру;
зручно для розробки та локальної роботи з конфігураціями.
Приклад:
docker run --rm \
--mount type=bind,source="$PWD/config",target=/etc/app,readonly \
alpineВибір залежить від того, кому належить файлова система:
дані, якими керує Docker, зазвичай зберігають у named volume;
файли, якими керує розробник або операційна система хоста, підключають через bind mount.
Переглянути монтування запущеного контейнера:
docker inspect container_nameУ результаті в полі Mounts можна побачити:
тип монтування;
назву тому або шлях на хості;
цільовий шлях у контейнері;
режим доступу.
Щоб перевірити монтування без запуску довготривалого процесу, можна виконати команду в контейнері:
docker run --rm \
--mount type=volume,source=app-data,target=/data \
alpine \
sh -c 'printf "Файл у томі\n" > /data/test.txt && ls -la /data'Bind mount зберігає права доступу хост-системи. Процес у контейнері може не мати дозволу на читання або запис локальних файлів.
Наприклад, контейнер може працювати від користувача з іншим числовим ідентифікатором, ніж користувач на хості. У такому випадку запис у bind mount може завершитися помилкою Permission denied.
Під час діагностики перевіряйте:
ls -ld ./site
ls -l ./siteТакож перевіряйте, від якого користувача працює процес у контейнері:
docker run --rm alpine idНе варто без потреби вирішувати проблему встановленням надто широких прав, наприклад chmod -R 777. Краще узгодити власника, групу або режим доступу з конкретним процесом.
Якщо файл створено лише всередині контейнера, після видалення контейнера він може зникнути:
docker run --name temporary alpine \
sh -c 'echo "Тимчасові дані" > /data.txt'
docker rm temporaryДля збереження потрібно змонтувати volume або bind mount.
Монтування замінює вміст цільового шляху видимим вмістом тому або локального каталогу.
Якщо підключити порожній каталог до каталогу, де в образі вже були файли, ці файли стануть недоступними через змонтований шлях.
Якщо bind mount підключено до неправильного каталогу, контейнер може побачити порожню директорію. Перевіряйте поточний каталог і вміст джерела:
pwd
ls -la ./siteКоманда нижче видаляє том і всі дані в ньому:
docker volume rm app-datadocker volume prune також може видалити невикористані томи, тому використовуйте її обережно.
Якщо том або каталог змонтовано з readonly чи ro, запис завершиться помилкою. Переконайтеся, що режим відповідає призначенню монтування.
Named volume — сховище, яким керує Docker.
Bind mount — конкретний каталог або файл із хост-системи.
Дані в томі переживають видалення контейнера, але не видалення самого тому.
--mount має явний і зрозумілий синтаксис.
-v коротший, але потребує уважної перевірки шляхів.
Для файлів, які контейнер не повинен змінювати, використовуйте readonly або ro.
Bind mount зручний для локальної розробки, а named volume — для даних, якими керують контейнери.