Перейти к содержимому
Главная страница » Как передать файл между контейнерами Docker

Как передать файл между контейнерами Docker

Возможно вам нужна инструкция, как обмениваться данными между Docker и хостом.

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

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

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

Предварительные требования

Чтобы следовать этой статье, вам понадобится сервер Ubuntu 22.04 со следующим:

  • Пользователь, не являющийся пользователем root, с правами sudo;
  • Установленный Docker.

Примечание: Хотя в Предварительных требованиях приведены инструкции по установке Docker в Ubuntu 22.04, docker команды для томов данных Docker в этой статье должны работать в других операционных системах, пока установлен Docker и пользователь sudo добавлен в docker группу.

Создание независимого тома

Представленная в выпуске Docker команда docker volume create позволяет создавать тома, не привязывая их к какому-либо конкретному контейнеру. Вы будете использовать эту команду для добавления тома с именем DataVolume1:

docker volume create --name DataVolume1

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

Output
DataVolume1

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

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

Находясь в контейнере, запишите некоторые данные на том:

echo "Example1" > /datavolume1/Example1.txt

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

exit

Вы можете убедиться, что том присутствует в вашей системе с помощью docker volume inspect:

docker volume inspect DataVolume1
Output[
    {
        "CreatedAt": "2018-07-11T16:57:54Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/DataVolume1/_data",
        "Name": "DataVolume1",
        "Options": {},
        "Scope": "local"
    }
]

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

Далее запустите новый контейнер и прикрепите DataVolume1:

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

Проверьте содержимое:

cat /datavolume1/Example1.txt

Output
Example1

Выйдите из контейнера:

exit

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

Создание тома, который сохраняется при удалении контейнера

В следующем примере вы создадите том одновременно с контейнером, удалите контейнер, затем присоедините том к новому контейнеру.

Вы будете использовать docker run команду для создания нового контейнера с использованием базового образа Ubuntu. -t предоставит нам терминал и -i позволит нам взаимодействовать с ним. Для наглядности вы будете использовать --name для идентификации контейнера.

Флаг -v позволит нам создать новый том, который вы вызовете DataVolume2. Вы будете использовать двоеточие, чтобы отделить это имя от пути, по которому том должен быть смонтирован в контейнере. Наконец, вы укажете базовый образ Ubuntu и будете полагаться на команду по умолчанию в файле Docker базового образа Ubuntubash чтобы перенести нас в оболочку:

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

Примечание: -v Флаг очень гибкий. Он может привязывать или присваивать имя тому с небольшой корректировкой синтаксиса. Если первый аргумент начинается с / или ~/, вы создаете bindmount . Удалите это, и вы присвоите тому имя. Например:

  • -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
Output
Example2

Выйдите из контейнера:

exit

При перезапуске контейнера том подключится автоматически:

docker start -ai Container2

Убедитесь, что том действительно смонтирован и ваши данные все еще на месте:

cat /datavolume2/Example2.txt
Output
Example2

Наконец, завершите работу и очистите:

exit

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

docker volume rm DataVolume2

В сообщении сообщается, что том все еще используется, и предоставляется расширенная версия идентификатора контейнера:

OutputError response from daemon: unable to remove volume: remove DataVolume2: volume is in use - [d0d2233b668eddad4986313c7a4a1bc0d2edaf0c7e1c02a6a6256de27db17a63]

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

docker rm d0d2233b668eddad4986313c7a4a1bc0d2edaf0c7e1c02a6a6256de27db17a63
Outputd0d2233b668eddad4986313c7a4a1bc0d2edaf0c7e1c02a6a6256de27db17a63

Удаление контейнера не повлияет на объем. Вы можете увидеть, что он все еще присутствует в системе, перечислив тома с помощью docker volume ls:

docker volume ls
OutputDRIVER              VOLUME NAME
local               DataVolume2

И вы можете использовать docker volume rm для его удаления:

docker volume rm DataVolume2

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

Создание тома из существующего каталога с данными

Как правило, независимое создание тома с помощью docker volume create и создание тома при создании контейнера эквивалентны, за одним исключением. Если вы создаете том одновременно с созданием контейнера и указываете путь к каталогу, который содержит данные в базовом образе, эти данные будут скопированы в том.

В качестве примера вы создадите контейнер и добавите объем данных в /var, каталог, который содержит данные в базовом образе:

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

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

Выйдите из текущего контейнера:

exit

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

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

В каталоге datavolume3 теперь есть копия содержимого /var каталога базового образа:

Outputbackups
cache
lib
local
lock
log
mail
opt
run
spool
tmp

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

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

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

Создайте Container4 и DataVolume4

Используйте docker run для создания нового контейнера с именем Container4 с прикрепленным объемом данных:

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

Далее вы создадите файл и добавите текст:

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

Затем вы выйдете из контейнера:

exit

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

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

Вы собираетесь создавать Container5 и монтировать тома из Container4:

docker run -ti --name=Container5 --volumes-from Container4 ubuntu

Проверьте сохраняемость данных:

cat /datavolume4/Example4.txt
OutputThis file is shared between containers

Теперь добавьте немного текста из Container5:

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

Наконец, вы выйдете из контейнера:

exit

Далее вы убедитесь, что ваши данные все еще присутствуют в Container4.

Просмотреть изменения, внесенные в Container5

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

docker start -ai Container4

Проверьте наличие изменений:

cat /datavolume4/Example4.txt
OutputThis file is shared between containers
Both containers can write to DataVolume4

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

exit

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

Запустите контейнер 6 и смонтируйте том только для чтения

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

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

Вы проверите статус «только для чтения», попытавшись удалить файл примера:

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

Наконец, вы выйдете из контейнера и очистите свои тестовые контейнеры и тома:

exit

Теперь, когда вы закончили, очистите свои контейнеры и тома:

docker rm Container4 Container5 Container6
docker volume rm DataVolume4

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

Заключение

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

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *