Пошук уроків, статей та іншого контенту
Підключите іменовані та bind volumes, щоб зберігати дані контейнерів між перезапусками.
Файлова система контейнера є тимчасовою. Якщо контейнер видалити, дані, записані всередині нього, зазвичай також буде втрачено.
Volume — це спосіб зберігати дані окремо від життєвого циклу контейнера. Коли контейнер перезапускається або видаляється, volume залишається, доки його не видалити окремо.
Volumes використовують для:
даних баз даних;
завантажених користувачами файлів;
кешів;
конфігурацій або результатів роботи застосунку;
обміну файлами між контейнером і хостом.
Docker підтримує кілька способів монтування даних. У цьому уроці розглянемо:
іменовані volumes — Docker керує місцем зберігання;
bind mounts — конкретна папка хост-системи монтується в контейнер.
Іменований volume має назву, яку можна використовувати в командах Docker. Docker сам створює та зберігає його в службовій директорії.
Створимо volume:
docker volume create app-dataПереглянути список volumes можна так:
docker volume lsВикористаємо volume у контейнері Alpine. Опція -v має формат:
назва-volume:шлях-у-контейнеріdocker run --rm \
--name volume-writer \
-v app-data:/data \
alpine \
sh -c 'echo "Дані збережено у volume" > /data/message.txt'У цьому прикладі:
app-data — іменований volume;
/data — каталог усередині контейнера;
файл message.txt записується не просто в тимчасову файлову систему контейнера, а у volume;
--rm автоматично видаляє контейнер після завершення команди, але не видаляє volume.
Створимо новий контейнер і прочитаємо файл:
docker run --rm \
-v app-data:/data \
alpine \
cat /data/message.txtРезультат:
Дані збережено у volumeКонтейнер, який створив файл, уже видалено, але дані залишилися в app-data.
--mountОпція --mount описує монтування детальніше та зручніше читається в складних командах:
docker run --rm \
--mount type=volume,source=app-data,target=/data \
alpine \
cat /data/message.txtТут:
type=volume — використовується Docker volume;
source=app-data — назва volume;
target=/data — шлях монтування всередині контейнера.
-v коротша, а --mount має більш явний синтаксис. Обидва варіанти підтримують іменовані volumes.
Команда docker volume inspect показує властивості volume:
docker volume inspect app-dataУ результаті Docker покаже JSON із назвою, драйвером і шляхом, де volume зберігається на хості.
Не варто змінювати файли в цій службовій директорії вручну. Працюйте з даними через змонтований volume або Docker-команди.
Один volume можна підключити до кількох контейнерів. Це дає змогу одному контейнеру записувати дані, а іншому — читати їх.
Спочатку запишемо файл:
docker run --rm \
--mount type=volume,source=app-data,target=/data \
alpine \
sh -c 'date > /data/created-at.txt'Тепер прочитаємо його з іншого контейнера:
docker run --rm \
--mount type=volume,source=app-data,target=/data \
alpine \
cat /data/created-at.txtОбидва контейнери використовують один і той самий app-data.
За замовчуванням монтування доступне для читання та запису. Якщо контейнеру потрібен лише доступ для читання, додайте readonly або ro:
docker run --rm \
--mount type=volume,source=app-data,target=/data,readonly \
alpine \
cat /data/message.txtСпроба записати файл у /data у цьому контейнері завершиться помилкою.
Bind mount підключає конкретний шлях на хост-системі до каталогу всередині контейнера.
Створимо папку для даних:
mkdir -p ./local-dataЗапишемо файл у цю папку через контейнер:
docker run --rm \
--mount type=bind,source="$(pwd)/local-data",target=/data \
alpine \
sh -c 'echo "Файл на хості" > /data/message.txt'Тепер файл доступний безпосередньо на хості:
cat ./local-data/message.txtРезультат:
Файл на хостіУ цьому випадку Docker не створює окреме сховище з власною назвою. Контейнер працює безпосередньо з папкою ./local-data.
Короткий синтаксис для bind mount:
docker run --rm \
-v "$(pwd)/local-data:/data" \
alpine \
cat /data/message.txtДля bind mount формат такий:
шлях-на-хості:шлях-у-контейнері| Властивість | Іменований volume | Bind mount | |---|---|---| | Хто визначає місце зберігання | Docker | Розробник | | Чи зручно переглядати файли на хості | Не завжди | Так | | Типове використання | Дані баз даних, постійне сховище | Код, конфігурації, локальна розробка | | Керування через docker volume | Так | Ні | | Залежність від структури хоста | Низька | Висока |
Іменовані volumes зазвичай підходять для даних, якими має керувати Docker. Bind mounts зручні, коли потрібно редагувати файли на хості та одразу бачити зміни в контейнері.
Щоб контейнер не міг змінювати файли, монтування можна зробити доступним лише для читання.
Для bind mount:
docker run --rm \
--mount type=bind,source="$(pwd)/local-data",target=/data,readonly \
alpine \
cat /data/message.txtДля короткого синтаксису:
docker run --rm \
-v "$(pwd)/local-data:/data:ro" \
alpine \
cat /data/message.txtТакий режим корисний, коли контейнеру потрібно лише прочитати конфігурацію або вхідні файли.
Якщо змонтувати volume або bind mount у каталог, де вже були файли образу, ці файли стануть невидимими з контейнера.
Наприклад, якщо в образі є /app/config, а volume змонтовано в /app/config, контейнер побачить вміст volume замість початкового вмісту образу.
Тому потрібно уважно вибирати каталог монтування:
docker run --rm \
--mount type=volume,source=app-data,target=/var/lib/app \
alpine \
sh -c 'echo "Вміст застосунку" > /var/lib/app/data.txt'Не монтуйте volume поверх системних каталогів без чіткої потреби.
Перезапуск контейнера не видаляє volume:
docker run -d \
--name persistent-demo \
--mount type=volume,source=app-data,target=/data \
alpine \
sh -c 'while true; do sleep 3600; done'Перевіримо, що контейнер працює:
docker ps --filter name=persistent-demoЗупинимо та запустимо контейнер знову:
docker restart persistent-demoПеревіримо дані:
docker exec persistent-demo cat /data/message.txtТепер видалимо контейнер:
docker rm -f persistent-demoСтворимо інший контейнер із тим самим volume:
docker run --rm \
--mount type=volume,source=app-data,target=/data \
alpine \
cat /data/message.txtДані збережені, тому що вони належать app-data, а не конкретному контейнеру.
Переглянути всі volumes:
docker volume lsВидалити конкретний volume:
docker volume rm app-dataПісля цього всі файли в app-data буде втрачено.
Docker також може видалити невикористовувані volumes:
docker volume pruneКоманда попросить підтвердження. Вона небезпечна для даних, які ще можуть знадобитися, тому перед виконанням перевіряйте список volumes.
Видалення контейнера не означає автоматичне видалення іменованого volume. Саме тому volumes можуть поступово накопичуватися.
Наведена команда створює контейнер, який працює з даними в іменованому volume:
docker run -d \
--name file-storage \
--mount type=volume,source=file-storage-data,target=/var/lib/storage \
alpine \
sh -c 'while true; do sleep 3600; done'Запишемо файл у сховище:
docker exec file-storage \
sh -c 'echo "Важливий документ" > /var/lib/storage/document.txt'Перевіримо його:
docker exec file-storage \
cat /var/lib/storage/document.txtПісля видалення контейнера volume залишиться:
docker rm -f file-storage
docker volume lsНовий контейнер із тим самим volume матиме доступ до попереднього документа:
docker run --rm \
--mount type=volume,source=file-storage-data,target=/var/lib/storage \
alpine \
cat /var/lib/storage/document.txtЯкщо файл записано лише у файлову систему контейнера, він зникне після видалення контейнера:
docker run --name temporary-data alpine \
sh -c 'echo "Тимчасові дані" > /data.txt'
docker rm temporary-dataФайл /data.txt більше недоступний. Для постійних даних потрібно монтувати volume.
Команда docker volume rm видаляє всі дані volume. Перед виконанням переконайтеся, що він більше не потрібен:
docker volume inspect app-data
docker volume rm app-dataBind mount залежить від шляху на хості. Відносний шлях або неправильна поточна директорія можуть призвести до монтування не тієї папки.
Безпечніше використовувати абсолютний шлях:
docker run --rm \
--mount type=bind,source="$(pwd)/local-data",target=/data \
alpine \
ls -la /dataЯкщо змонтувати volume у каталог із файлами, що постачаються образом, ці файли будуть приховані. Перевіряйте, що шлях target призначений саме для даних, які мають зберігатися окремо.
Кілька контейнерів можуть одночасно змінювати файли в одному volume. Це може спричинити конфлікти або пошкодження даних, якщо сам застосунок не підтримує такий режим роботи.
Volume зберігає дані окремо від файлової системи контейнера.
Іменований volume створюється та керується Docker.
Bind mount підключає конкретну папку хоста до контейнера.
Для іменованих volumes можна використовувати -v або --mount.
Bind mounts зручні для локальної розробки та обміну файлами з хостом.
Видалення контейнера не видаляє іменований volume.
Дані volume видаляються лише після явного docker volume rm або очищення невикористовуваних volumes.
Монтування приховує початковий вміст каталогу контейнера.
Режим readonly захищає дані від змін із контейнера.