Перейти к основному содержимому

Руководство по томам Docker

· 7 мин. чтения

Задача: Сумма двух

Дано массив целых чисел и целая сумма. Нужно найти индексы двух чисел, сумма которых равна заданной ...

ANDROMEDA

1. Обзор

Контейнеры Docker используются для запуска приложений в изолированной среде. По умолчанию все изменения внутри контейнера теряются при остановке контейнера. Если мы хотим сохранить данные между запусками, могут помочь тома Docker и привязки.

В этом руководстве мы узнаем о томах Docker , а также о том, как управлять ими и подключать их к контейнерам.

2. Что такое объем?

2.1. Файловая система Docker

Контейнер Docker запускает программный стек, определенный в образе . Изображения состоят из набора слоев, доступных только для чтения, которые работают в файловой системе под названием Union File System. Когда мы запускаем новый контейнер, Docker добавляет слой чтения-записи поверх слоев образа, позволяя контейнеру работать так, как если бы он работал в стандартной файловой системе Linux .

Таким образом, любое изменение файла внутри контейнера создает рабочую копию на уровне чтения-записи. Однако когда контейнер останавливается или удаляется, этот уровень чтения-записи теряется .

./3900c9bae4b3bf0fa7de274afd1187d9.png

Мы можем попробовать это, запустив команду, которая записывает, а затем читает файл:

$ docker run bash:latest \ 
bash -c "echo hello > file.txt && cat file.txt"

Результат:

hello

Но если мы запустим тот же образ только с командой для вывода содержимого файла:

$ docker run bash:latest bash -c "cat file.txt" 
cat: can't open 'file.txt': No such file or directory

Второй запуск контейнера выполняется на чистой файловой системе, поэтому файл не найден.

2.2. Привязать маунтов

Привязка Docker — это высокопроизводительное подключение контейнера к каталогу на хост-компьютере . Это позволяет хосту совместно использовать собственную файловую систему с контейнером , который можно сделать доступным только для чтения или чтения-записи.

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

$ docker run -v $(pwd):/var/opt/project bash:latest \ 
bash -c "echo Hello > /var/opt/project/file.txt"

Параметр –v может использоваться для всех форм монтирования и указывает, в данном случае, источник на хосте – рабочий каталог в выводе $(pwd) – и целевую точку монтирования в контейнере – /var/opt /проект .

После запуска этой команды мы найдем файл .txt в рабочем каталоге нашего хост-компьютера. Это простой способ предоставления постоянных файлов между вызовами контейнера Docker, хотя он наиболее полезен, когда контейнер выполняет работу от имени хоста.

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

Следует отметить, что $(pwd -W) иногда требуется в оболочках Windows bash для предоставления рабочего каталога в форме, которую оболочка bash может передать в Docker.

2.3. Объемы докеров

При монтировании с привязкой используется файловая система хоста, но тома Docker являются родными для Docker . Данные хранятся где-то в хранилище, подключенном к хосту — часто в локальной файловой системе. Жизненный цикл самого тома длиннее, чем у контейнера, что позволяет ему сохраняться до тех пор, пока он не станет не нужен. Тома могут быть разделены между контейнерами.

В некоторых случаях том находится в форме, которую хост не может использовать напрямую.

3. Управление томами

Docker позволяет нам управлять томами с помощью набора команд docker volume . Мы можем дать тому явное имя (именованные тома) или позволить Docker сгенерировать случайное имя (анонимные тома).

3.1. Создание томов

Мы можем создать том, используя подкоманду create и передав имя в качестве аргумента:

$ docker volume create data_volume
data_volume

Если имя не указано, Docker генерирует случайное имя:

$ docker volume create  
d7fb659f9b2f6c6fd7b2c796a47441fa77c8580a080e50fb0b1582c8f602ae2f

3.2. Список томов

Подкоманда ls показывает все тома, известные Docker:

$ docker volume ls
DRIVER VOLUME NAME
local data_volume
local d7fb659f9b2f6c6fd7b2c796a47441fa77c8580a080e50fb0b1582c8f602ae2f

Мы можем фильтровать, используя флаг -f или –filter и передавая параметры ключ=значение для большей точности:

$ docker volume ls -f name=data
DRIVER VOLUME NAME
local data_volume

3.3. Проверка томов

Чтобы отобразить подробную информацию об одном или нескольких томах, мы используем подкоманду inspect :

$ docker volume inspect ca808e6fd82590dd0858f8f2486d3fa5bdf7523ac61d525319742e892ef56f59
[
{
"CreatedAt": "2020-11-13T17:04:17Z",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/ca808e6fd82590dd0858f8f2486d3fa5bdf7523ac61d525319742e892ef56f59/_data",
"Name": "ca808e6fd82590dd0858f8f2486d3fa5bdf7523ac61d525319742e892ef56f59",
"Options": null,
"Scope": "local"
}
]

Следует отметить, что драйвер тома описывает, как хост Docker находит том. Тома могут быть на удаленном хранилище через nfs, например. В этом примере том находится в локальном хранилище.

3.4. Удаление томов

Чтобы удалить один или несколько томов по отдельности, мы можем использовать подкоманду rm :

$ docker volume rm data_volume
data_volume

3.5. Обрезка томов

Мы можем удалить все неиспользуемые тома с помощью подкоманды prune :

$ docker volume prune
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
data_volume

4. Запуск контейнера с томом

4.1. Использование -v

Как мы видели в предыдущем примере, мы можем запустить контейнер с монтированием привязки, используя параметр -v :

$ docker run -v $(pwd):/var/opt/project bash:latest \
bash -c "ls /var/opt/project"

Этот синтаксис также поддерживает монтирование тома:

$ docker run -v data-volume:/var/opt/project bash:latest \
bash -c "ls /var/opt/project"

Поскольку наш том пуст, в нем ничего не отображается из точки монтирования. Однако, если бы мы записывали в том во время одного вызова контейнера:

$ docker run -v data-volume:/var/opt/project bash:latest \
bash -c "echo ForEach > /var/opt/project/ForEach.txt"

Тогда наше последующее использование контейнера с этим смонтированным томом сможет получить доступ к файлу:

$ docker run -v data-volume:/var/opt/project bash -c "ls /var/opt/project"
ForEach.txt

Параметр -v содержит три компонента, разделенных двоеточием:

  • Исходный каталог или имя тома
  • Точка монтирования внутри контейнера
  • (Необязательно) ro , если монтирование должно быть доступно только для чтения

4.2. Использование параметра –mount

Мы можем предпочесть использовать более понятную опцию –mount , чтобы указать том, который мы хотим смонтировать:

$ docker run --mount \
'type=volume,src=data-volume,\
dst=/var/opt/project,volume-driver=local,\
readonly' \
bash -c "ls /var/opt/project"

Входными данными для –mount является строка пар ключ-значение, разделенных запятыми. Здесь мы установили:

  • type — как том , чтобы указать монтирование тома
  • src — к имени тома, хотя это мог быть и исходный каталог, если бы мы выполняли монтирование с привязкой
  • dst — как конечная точка монтирования в контейнере
  • volume-driver — в данном случае локальный драйвер
  • readonly – сделать это монтирование доступным только для чтения; мы могли бы выбрать rw для чтения/записи

Следует отметить, что приведенная выше команда также создаст том, если он еще не существует.

4.3. Использование –volumes-from для совместного использования томов

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

Допустим, мы запустили наш эхо - скрипт в контейнере с монтированием тома данных . Позже мы могли бы перечислить все контейнеры , которые мы использовали:

$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4920602f8048 bash "docker-entrypoint.s…" 7 minutes ago Exited (0) 7 minutes ago exciting_payne

Мы могли бы запустить наш следующий контейнер, скопировав тома, используемые этим:

$ docker run --volumes-from 4920 \
bash:latest \
bash -c "ls /var/opt/project"
ForEach.txt

На практике –volumes-from обычно используется для связывания томов между запущенными контейнерами . Jenkins использует его для обмена данными между агентами, работающими как контейнеры Docker.

5. Вывод

В этой статье мы увидели, как Docker обычно создает контейнер с новой файловой системой, но как связывание монтирования и тома позволяют долговременное хранение данных за пределами жизненного цикла контейнера.

Мы увидели, как составлять список томов Docker и управлять ими, а также как подключать тома к работающему контейнеру через командную строку.