Bind Mounts vs Volumes в Docker: Сравнение и Примеры

Docker Volumes предоставляет разработчикам постоянное хранилище для контейнеров. Этот инструмент отключает привязку данных к жизненному циклу контейнера, позволяя получить доступ к контейнерным данным в любой момент. Таким образом, сделанные в контейнерах записи остаются доступными после уничтожения содержавшего их контейнера и могут повторно использоваться в других.

Запуская контейнер Docker нам может понадобится сохранить где-то данные или наоборот добавить их в контейнер. Для реализации этой задачи, в Docker, был создан объект томов Volumes и возможность проброса папок Bind mounts.

Bind mounts и volumes в Docker служат для сохранения данных, однако они работают немного по-разному и используются в различных сценариях. Вот основные отличия:

Bind Mounts

  1. Прямое отображение на файловую систему хоста: Bind mounts связывают определённую директорию или файл на хосте с контейнером. Это означает, что изменения, сделанные в этой директории или файле, будут отражаться как в контейнере, так и на хосте.
  2. Управление файлами и директориями: Пользователи могут напрямую управлять файлами и директориями на хосте, которые используются в bind mounts.
  3. Не управляется Docker: Docker не управляет файловыми системами bind mounts; они полностью находятся под контролем пользователя.
  4. Зависимость от файловой системы хоста: Bind mounts зависят от структуры файловой системы хоста, что может быть проблематично при переносе на другие машины.

Volumes

  1. Управление Docker: Volumes полностью управляются Docker. Docker может создавать новые volumes, копировать данные из образа в volume при первом запуске контейнера и удалять неиспользуемые volumes.
  2. Изоляция от файловой системы хоста: Volumes хранятся в части файловой системы хоста, управляемой Docker, и изолированы от основной файловой системы хоста. Это делает их более безопасными и менее зависимыми от файловой системы хоста.
  3. Портативность: Volumes могут быть легко перенесены между различными системами и обеспечивают большую согласованность в развертываниях, так как они не зависят от окружения хоста.
  4. Поддержка драйверов: 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

Концепция Docker-in-Docker

При помощи 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 volume ls — вывести список вольюмов (ссылка)
  • docker volume create <название> — создать вольюм (ссылка)
  • docker volume rm <название> — удалить вольюм (ссылка)
  • docker volume prune — удалить вольюмы, которые не используются контейнерами (ссылка)

Команда подключения

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 зависит от конкретных требований к приложению и среде, в которой оно будет развернуто.

PQ VPS сервера в 28+ странах.