Docker Volumes предоставляет разработчикам постоянное хранилище для контейнеров. Этот инструмент отключает привязку данных к жизненному циклу контейнера, позволяя получить доступ к контейнерным данным в любой момент. Таким образом, сделанные в контейнерах записи остаются доступными после уничтожения содержавшего их контейнера и могут повторно использоваться в других.
Запуская контейнер Docker нам может понадобится сохранить где-то данные или наоборот добавить их в контейнер. Для реализации этой задачи, в Docker, был создан объект томов Volumes и возможность проброса папок Bind mounts.
Bind mounts и volumes в Docker служат для сохранения данных, однако они работают немного по-разному и используются в различных сценариях. Вот основные отличия:
Bind Mounts
Volumes
Синтаксические Отличия: При использовании bind mounts указывается абсолютный путь к директории на хосте. Синтаксис является прямым и понятным, так как указывается конкретный путь на файловой системе хоста. При использовании volumes указывается только имя volume, без указания пути на хосте. Docker сам управляет расположением и жизненным циклом этих volumes.
Рассмотрим синтаксис на примере двух сценариев.
Сценарий использования Bind Mounts: Разработчик хочет связать директорию на его локальной машине с контейнером, чтобы иметь возможность редактировать исходный код приложения на хосте и видеть изменения в реальном времени внутри контейнера. Команда:
docker run -d -v /путь/к/директории/на/хосте:/путь/в/контейнере my_image
Здесь /путь/к/директории/на/хосте - это путь к директории на хосте, а /путь/в/контейнере - путь, по которому эта директория будет доступна внутри контейнера.
Сценарий использования Volumes: Администратор хочет запустить базу данных в Docker, сохраняя данные базы данных в volume, чтобы они оставались сохраненными между перезапусками контейнера. Команда:
docker run -d --name mydb -v mydbdata:/var/lib/mysql mydb_image
В этом случае, mydbdata - это имя volume, которое будет создано Docker, если оно ещё не существует. /var/lib/mysql - это путь в контейнере, куда будет подключен volume.
Тома mount предназначены для добавления в контейнер имеющегося пути. Это помогает для добавления конфигурационной информации, а также наборов данных и статики с сайтов. Чтобы указать каталоги, предназначенные для монтирования в контейнер, нужно использовать инструкцию –mount совместно с <host path>:<container path>.
Помните, если вы смонтируете внутрь контейнера любую папку, то внутри контейнера игнорируются права установленные на хостовом сервере. Внутри контейнера все действия происходят от пользователя root. Вы можете удалить любую примонтированную директорию или файл из контейнера! Старайтесь монтировать конкретные файлы или задавайте режим монтировании только для чтения.
Bind mount:
docker run -v <полный_путь_на_хосте>:<полный_путь_в_контейнере> <образ>
Удобно использовать pwd, чтобы не указывать полный путь
docker run --rm -it -v $(pwd)</путь_на_хосте>:<полный_путь_в_контейнере> <образ>
Пример: проброс файл todo_list.csv внутрь контейнера (предварительно создадим контейнер из Dockerfile):
# cat Dockerfile FROM python:3.8 WORKDIR /app docker build -t tg_bot_files/token . docker run --rm -it -v $(pwd)/todo_result/todo_list.csv:/app/todo_result/todo_list.csv tg_bot_files/token
При помощи bind mount можно прокинуть сокет докера, в результате чего мы получим доступ к демону внутри контейнера. Такое может понадобиться, например, в CI/CD. Если кратко — нужно уметь внутри контейнера запускать, например, сборку образа (docker build).
docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock docker
Заходим внутрь контейнера и запускаем команду (в пример redis имя предварительно созданного контейнера, он должен быть выключен):
docker run --rm -d --name redis redis
Команда подключения
docker run -v <название_вольюма>:<полный_путь_в_контейнере> <образ>
Readonly режим
docker run -v <полный_путь_на_хосте>:<полный_путь_в_контейнере>:ro <образ>
Используем как обычно inspect для вывода информации о существующих томах.
docker volume ls DRIVER VOLUME NAME local 187c0f08408ec8d5a1a876f699ef993afbcb8853f21459fb65a39c60c5d9cfce local redis_vol local tg_4_vol docker volume inspect redis_vol [ { "CreatedAt": "2023-05-21T22:41:21+03:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/redis_vol/_data", "Name": "redis_vol", "Options": null, "Scope": "local" } ]
Если вы хотите восстановить данные с неудалённого тома на, который больше не ссылаются контейнеры, найдите каталог Mountpoint, затем просмотрите его как пользователь root.
Тома tempfs выполняют функцию, обратную главной задаче Docker Volumes, то есть они отменяют сохранение информации после ликвидации контейнера. Это может понадобиться тем разработчикам, которые ведут достаточно обширное журналирование. В таком случае постоянные одноразовые записи могут привести к серьезному падению производительности системы. Инструкции –tempfs создают временные директории для записи непосредственно в памяти (ОЗУ), чтобы исключить постоянные обращения к файловой системе.
Tempfs Mount работает только под Linux, с ограничением в 1 контейнер.
Bind Mounts часто используются для разработки на локальных машинах, где разработчикам требуется прямой доступ к файлам и директориям на хосте. Volumes же предпочтительнее в продакшн средах из-за их управляемости, безопасности и портативности. Выбор между bind mounts и volumes зависит от конкретных требований к приложению и среде, в которой оно будет развернуто.