Обмен данными между контейнерами Docker

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

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

Однако в некоторых ситуациях приложения должны совместно использовать данные или сохранять данные после остановки контейнера. Базы данных, пользовательский контент веб-сайтов, логи – лишь несколько примеров данных, которые нецелесообразно или невозможно включить в контейнер Docker ; но приложениям такие данные крайне необходимы. Постоянный доступ к данным могут обеспечить тома Docker.

Требования

  • Сервер Ubuntu 16.04 (начальная настройка описана здесь).
  • Пользователь с доступом к команде sudo.
  • Docker (инструкции по установке можно найти здесь).

Примечание: данное руководство предназначено для сервера Ubuntu 16.04, однако команды docker одинаково работают в разных операционных системах (если пользователь с доступом к sudo добавлен в группу docker).

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

1: Независимый том

В Docker’s 1.9 была добавлена команда docker volume create, которая позволяет создавать тома отдельно от контейнеров. К примеру, чтобы добавить том DataVolume1, нужно ввести:

docker volume create --name DataVolume1

Если команда выполнена успешно, на экране появится имя контейнера:

DataVolume1

Чтобы использовать этот том, создайте новый контейнер с помощью образа Ubuntu, используя –rm флаг, чтобы автоматически удалить его при выходе.

Чтобы смонтировать новый том, нужно использовать опцию -v. Эта опция требует имя тома; после имени нужно поставить двоеточие и указать абсолютный путь к тому внутри контейнера. Если в контейнере/образе нет такого каталога, команда создаст его. Если каталог существует, смонтированный том удалит всё его содержимое.

docker run -ti --rm -v DataVolume1:/datavolume1 ubuntu

Добавьте в том данные:

echo "Example1" > /datavolume1/Example1.txt

Поскольку при запуске был использован флаг –rm, контейнер будет автоматически удалён, если его закрыть. Однако к тому это не относится – он останется в системе.

exit

Убедитесь, что том существует в системе:

docker volume inspect DataVolume1
[
{
"Name": "DataVolume1",
"Driver": "local",
"Mountpoint": "/var/lib/docker/volumes/datavolume1/_data",
"Labels": null,
"Scope": "local"
}
]

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

Попробуйте запустить новый контейнер и прикрепить к нему том DataVolume1:

docker run --rm -ti -v DataVolume1:/datavolume1 ubuntu
cat /datavolume1/Example1.txt
Example1

Закройте контейнер:

exit

2: Как сохранить том после удаления контейнера

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

Создайте новый контейнер с помощью команды docker run на основе образа ubuntu. Флаг –t предоставит терминал, -i позволит с ним взаимодействовать. Чтобы указать имя, используйте –name.

Добавьте флаг –v, чтобы создать том. Он будет называться DataVolume2. После имени через двоеточие нужно указать путь к точке монтирования. В конце команды нужно указать базовый образ Ubuntu. Встроенная в образ команда bash развернёт оболочку контейнера.

docker run -ti --name=Container2 -v DataVolume2:/datavolume2 ubuntu

Примечание: Флаг –v очень гибкий. Он также используется для выбора имени тома. Если первый аргумент начинается с / или ~/, флаг выполнит монтирование. В противном случае он присвоит тому имя.

-v /path:/path/in/container смонтирует каталоги /path и /path/in/container
-v path:/path/in/container создаст том по имени path, не имеющий никакого отношения к хосту.

Читайте также: Обмен данными между контейнером Docker и хостом

Теперь вы в контейнере. Добавьте данные в том.

echo "Example2" > /datavolume2/Example2.txt
cat /datavolume2/Example2.txt
Example2

Закройте контейнер:

exit

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

docker start -ai Container2

Убедитесь, что том успешно смонтирован и все данные на месте:

cat /datavolume2/Example2.txt
Example2

Закройте контейнер:

exit

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

docker volume rm DataVolume2

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

Error response from daemon: Unable to remove volume,
volume still in use: remove DataVolume2: volume is in use -
[719f98391ecf1d6f0f053ffea1bbd84cd2dc9cf6d31d5a4f348c60d98392804c]

Чтобы удалить контейнер, укажите его ID:

docker rm 719f98391ecf1d6f0f053ffea1bbd84cd2dc9cf6d31d5a4f348c60d98392804c
719f98391ecf1d6f0f053ffea1bbd84cd2dc9cf6d31d5a4f348c60d98392804c

Удаление контейнера никак не повлияет на том. Убедитесь, что том присутствует в системе:

docker volume ls
DRIVER              VOLUME NAME
local               DataVolume2

Чтобы удалить том, введите:

docker volume rm DataVolume2

Теперь вы знаете, как создать пустой том данных вместе с контейнером.

3: Создание тома на основе существующих данных

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

Для примера попробуйте создать контейнер и добавить том в /var (в базовом образе этот каталог содержит некоторые данные).

docker run -ti --rm -v DataVolume3:/var ubuntu

Содержимое каталога /var из исходного образа будет скопировано в том. Этот том можно смонтировать в новый контейнер. В этот раз используйте команду ls, которая выведет на экран содержимое каталога:

docker run --rm -v DataVolume3:/datavolume3 ubuntu ls DataVolume3

Том DataVolume3 является копией каталога /var.

backups
cache
lib
local
lock
log
mail
opt
run
spool
tmp

Эта функция будет полезна при необходимости сохранить данные собственного образа.

4: Совместное использование тома

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

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

Создайте новый контейнер и том (Container4 и DataVolume4).

docker run -ti --name=Container4 -v DataVolume4:/datavolume4 ubuntu

Создайте файл и добавьте в него какой-нибудь текст:

echo "This file is shared between containers" > /datavolume4/Example4.txt

Закройте контейнер:

exit

Эта команда вернёт вас в командную строку хоста, с помощью которой вы сможете создать новый контейнер и смонтировать его с томом данных DataVolume4.

Создайте Container5 и смонтируйте том Container4:

docker run -ti --name=Container5 --volumes-from Container4 ubuntu
cat /datavolume4/Example4.txt
This file is shared between containers

Добавьте в файл текст, находясь в Container5:

echo "Both containers can write to DataVolume4" >> /datavolume4/Example4.txt

Закройте контейнер:

exit

Теперь убедитесь, что данные остались в контейнере Container4.

Просмотрите изменения, внесённые в контейнере Container5. Перезапустите Container4:

docker start -ai Container4
cat /datavolume4/Example4.txt
cat /DataVolume4/Example4.txt
This file is shared between containers
Both containers can write to DataVolume4

Как видите, оба контейнера имеют право на чтение и запись в томе данных.

Закройте контейнер Container4:

exit

Как уже говорилось, Docker не блокирует файлы. Потому приложения, запущенные в контейнерах, должны делать это самостоятельно. Добавив :ro, том можно смонтировать в режиме только для чтения, чтобы не допустить случайного повреждения данных. попробуйте сделать это.

Смонтируйте том только для чтения в контейнере Container6. При этом нужно создать новый контейнер, подключить его к тому, а затем удалить старый контейнер. Демонтировать том не придётся.

Чтобы смонтировать том только для чтения, используйте опцию :ro после имени контейнера:

docker run -ti --name=Container6 --volumes-from Container4:ro ubuntu

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

rm /datavolume4/Example4.txt
rm: cannot remove '/datavolume4/Example4.txt': Read-only file system

Закройте контейнер:

exit

Теперь можно удалить контейнеры и том.

docker rm Container4 Container5 Container6
docker volume rm DataVolume4

Заключение

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

Читайте также: Обмен данными между контейнером Docker и хостом

Tags: ,

Добавить комментарий