Поиск по сайту:

Как обмениваться данными между контейнерами Docker


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

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

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

Использование томов для совместного использования каталога

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

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

Для начала создайте том:

docker volume create --name shared-data

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

docker run -d -v shared-data:/data --name example example-image:latest
docker run -d -v shared-data:/backup-source --name backup backup-image:latest

В этом примере контейнер backup получит эффективный доступ к каталогу /data контейнера example. Он будет смонтирован как /backup-source; изменения, сделанные одним контейнером, будут отражены в другом.

Быстрый запуск контейнеров с соответствующими томами

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

docker run -d --volumes-from example --name backup backup-image:latest

На этот раз контейнер backup получит том shared-data, смонтированный в его каталог /data. Флаг --volumes-from извлекает все определения томов, прикрепленные к контейнеру example. Он особенно идеален для заданий резервного копирования и других недолговечных контейнеров, которые действуют как вспомогательные компоненты для вашего основного сервиса.

Повышение безопасности благодаря креплениям только для чтения

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

Рекомендуется монтировать общие тома в режиме только для чтения, когда не ожидается, что контейнер будет вносить изменения. В приведенном выше примере контейнеру backup нужно только прочитать содержимое тома shared-data. Настройка монтирования в режиме только для чтения усиливает это ожидание, не позволяя ошибкам или вредоносным двоичным файлам в образе удалять данные, используемые контейнером example.

docker run -d -v shared-data:/backup-source:ro --name backup backup-image:latest

Добавление ro в качестве третьего параметра, разделенного двоеточием, к флагу -v указывает, что том должен быть смонтирован в режиме только для чтения. Вы также можете написать readonly вместо ro в качестве более явной альтернативы.

Обмен данными по сети

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

docker network create demo-network
docker run -d --net demo-network --name first example-image:latest
docker run -d --net demo-network --name second another-image:latest

Здесь first сможет пинговать second и наоборот. Ваши контейнеры могут запускать службу HTTP API, позволяющую им взаимодействовать с данными друг друга.

Продолжая пример резервного копирования, теперь ваш контейнер backup может сделать сетевой запрос к http://example:8080/backup-data для получения данных для резервного копирования. Контейнер example должен ответить архивом, содержащим все данные, которые необходимо сохранить. Затем контейнер резервного копирования отвечает за сохранение архива в подходящем месте хранения.

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

Если вы используете этот подход, важно учитывать безопасность. Убедитесь, что все API-интерфейсы HTTP, предназначенные для внутреннего доступа других ваших контейнеров Docker, не имеют портов, открытых в мостовой сети вашего хоста Docker. Это поведение по умолчанию при использовании параметров сети, показанных выше; привязка порта с -p 8080:8080 позволит получить доступ к API резервного копирования через сетевые интерфейсы вашего хоста. Это будет проблемой безопасности.

Краткое содержание

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

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