0

docker

Dockerfile VOLUME

04.01.2023

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

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

Тома могут быть смонтированы при запуске контейнеров с помощью флага -v команды docker run.

Это может быть либо ссылка на именованный том, либо связывающее монтирование каталога хоста в файловую систему контейнера.

Также можно определить тома во время сборки образа с помощью инструкции VOLUME в файлах Dockerfile.

Этот механизм гарантирует, что контейнеры, запущенные из образа, будут иметь постоянное хранилище.

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

Определение томов в Dockerfile

Инструкция Dockerfile VOLUME создает точку монтирования тома по указанному пути к контейнеру.

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

Dockerfile в следующем примере определяет том по пути к контейнеру /opt/app/data.

Новые контейнеры будут автоматически монтировать том в каталог.

FROM ubuntu:22.04
VOLUME /opt/app/data

Создайте образ, чтобы можно было проверить монтирование тома:

$ docker build -t volumes-test:latest .

Получение списка существующих томов:

$ docker volume ls
DRIVER   VOLUME NAME
local    demo-volume

Теперь запустите контейнер, используя ваш тестовый образ:

$ docker run -it volume-test:latest
root@07be7bde68c2:/#

Повторите команду docker volume ls, чтобы подтвердить создание нового тома:

$ docker volume ls
DRIVER   VOLUME NAME
local    3198bf857fdcbb8758c5ec7049f2e31a40b79e329f756a68725d83e46976b7a8
local    demo-volume

Выйдите из оболочки вашего тестового контейнера, чтобы контейнер остановился:

root@07be7bde68c2:/# exit
exit

Том и его данные будут сохраняться:

$ docker volume ls
DRIVER   VOLUME NAME
local    3198bf857fdcbb8758c5ec7049f2e31a40b79e329f756a68725d83e46976b7a8
local    demo-volume

Вы можете определить несколько томов в одной инструкции в виде строки, разделенной пробелами, или массива JSON.

Обе следующие формы создают и монтируют два уникальных тома при запуске контейнеров:

VOLUME /opt/app/data /opt/app/config
# ИЛИ
VOLUME ["/opt/app/data", "/opt/app/config"]

Заполнение начального содержимого тома

Тома автоматически заполняются содержимым, помещенным в каталог монтирования на предыдущих этапах создания образа:

FROM ubuntu:22.04
COPY default-config.yaml /opt/app/config/default-config.yaml
VOLUME /opt/app/config

Этот Dockerfile определяет том, который будет инициализирован существующим файлом default-config.yaml.

Контейнер сможет читать /opt/app/config/default-config.yaml без необходимости проверять, существует ли этот файл.

Изменения содержимого тома, сделанные после инструкции VOLUME, будут отброшены.

В этом примере файл default-config.yaml все еще доступен после запуска контейнеров, потому что команда rm поступает после того, как /opt/app/config помечен как том.

FROM ubuntu:22.04
COPY default-config.yaml /opt/app/config/default-config.yaml
VOLUME /opt/app/config
RUN rm /opt/app/config/default-config.yaml

Переопределение инструкций VOLUME при запуске контейнера

Тома, созданные с помощью инструкции VOLUME, автоматически получают имя с длинным уникальным хэшем.

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

Вы можете предотвратить появление таких томов, вручную определив тома на ваших контейнерах с помощью команды docker run -v, как обычно.

Следующая команда явно монтирует именованный том в каталог /opt/app/config контейнера, делая инструкцию VOLUME в Dockerfile излишней.

$ docker run -it -v config:/opt/app/config volumes-test:latest

Когда следует использовать инструкции VOLUME?

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

Использование инструкций VOLUME облегчает запуск контейнеров без необходимости запоминать флаги -v для применения.

VOLUME также служит документацией для путей контейнеров, хранящих постоянные данные.

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

Недостатки VOLUME

VOLUME не лишен недостатков.

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

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

Досадная оплошность, описанная ранее, все еще применима: эффекты команд после инструкции VOLUME будут отброшены.

Поскольку VOLUME будет находиться в базовом образе, все в вашем собственном Dockerfile идет после инструкции, и вы не сможете изменить содержимое каталога по умолчанию.

За кулисами, запуск временного контейнера для сборки создаст новый том на вашем хосте, который будет уничтожен по окончании сборки. Изменения не будут скопированы обратно в выходной образ.

Автоматическое монтирование тома может быть проблематичным и в других ситуациях.

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

VOLUME устраняет эту возможность, поскольку отключить автоматическое монтирование невозможно.

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

Заключение

Инструкции Dockerfile VOLUME позволяют определить монтирование томов во время сборки образа.

Они гарантируют, что контейнеры, запущенные из образа, будут иметь постоянное хранилище данных, даже если пользователь опустит флаг -v в команде docker run.

Свежие комментарии

Подписка

Лучшие статьи


Fatal error: Uncaught Error: Call to a member function have_posts() on null in /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/inc/blog.php:380 Stack trace: #0 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/widgets/latest-posts/widget.php(257): fox56_blog_grid(NULL, Array) #1 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/widgets/latest-posts/register.php(33): include('/home/host18670...') #2 /home/host1867038/the-devops.ru/htdocs/www/wp-includes/class-wp-widget.php(394): Wi_Widget_Latest_Posts->widget(Array, Array) #3 /home/host1867038/the-devops.ru/htdocs/www/wp-includes/widgets.php(837): WP_Widget->display_callback(Array, Array) #4 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/inc/single.php(417): dynamic_sidebar('sidebar') #5 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/inc/single.php(136): fox56_single_sidebar() #6 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/inc/single.php(7): fox56_single_inner() #7 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/single.php(23): fox56_single() #8 /home/host1867038/the-devops.ru/htdocs/www/wp-includes/template-loader.php(106): include('/home/host18670...') #9 /home/host1867038/the-devops.ru/htdocs/www/wp-blog-header.php(19): require_once('/home/host18670...') #10 /home/host1867038/the-devops.ru/htdocs/www/index.php(17): require('/home/host18670...') #11 {main} thrown in /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/inc/blog.php on line 380