Подключить SMB/CIFS в контейнере Docker

У меня есть веб-приложение, работающее в контейнере Docker. Это приложение должно получить доступ к некоторым файлам на нашем корпоративном файловом сервере (Windows Server с контроллером домена Active Directory). Файлы, к которым я пытаюсь получить доступ, - это файлы изображений, созданные для наших клиентов, и веб-приложение отображает их как часть клиентского портфолио.

На моей машине разработки у меня есть соответствующие папки, смонтированные через записи в /etc/fstab, а точки монтирования хоста монтируются в контейнере Docker с помощью аргумента --volume. Это прекрасно работает.

Теперь я пытаюсь собрать контейнер производства, который будет запускаться на другом сервере и который не полагается на общий ресурс CIFS, установленный на хосте. Поэтому я попытался добавить соответствующие записи в файл /etc/fstab в контейнере и установить их с помощью mount -a. Я получаю mount error(13): Permission denied.

Небольшое исследование онлайн привело меня к этой статье о безопасности Docker. Если я правильно прочитал это, кажется, что Docker явно отказывает в возможности монтировать файловые системы внутри контейнера. Я попытался установить ресурсы только для чтения, но это (неудивительно) тоже не удалось.

Итак, у меня есть два вопроса:

  • Правильно ли я понимаю, что Docker предотвращает использование mount внутри контейнеров?

  • Может ли кто-нибудь подумать о другом способе выполнения этого без монтирования общего ресурса CIFS на хосте, а затем установки папки хоста в контейнере Docker?

Ответы

Ответ 1

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

Кроме того, вы можете комбинировать --cap-add и --cap-drop, чтобы предоставить контейнеру только те возможности, которые ему действительно необходимы. (см. документацию) Возможность SYS_ADMIN предоставляет права монтирования.

Ответ 2

  • да
  • В контейнере есть закрытая проблема mount.cifs

https://github.com/docker/docker/issues/22197

согласно которому добавление

--cap-add SYS_ADMIN --cap-add DAC_READ_SEARCH

для параметров запуска будут выполняться операции mount -t cifs.

Я попробовал это:

mount -t cifs //<host>/<path> /<localpath> -o user=<user>,password=<user>

внутри контейнера, то работает

Ответ 3

Вы можете использовать команду smbclient (часть пакета Samba) для доступа к серверу SMB/CIFS из контейнера Docker без его монтирования, так же, как вы можете использовать curl для загрузки или выгрузки файла.

Есть вопрос о StackExchange Unix, который занимается этим, но вкратце:

smbclient //server/share -c 'cd /path/to/file; put myfile'

Для нескольких файлов есть опция -T которая может создавать или извлекать архивы .tar, однако это выглядит как двухэтапный процесс (один для создания .tar а затем другой для его извлечения локально). Я не уверен, что вы могли бы использовать трубу, чтобы сделать это за один шаг.

Ответ 5

Не делайте свои контейнеры менее безопасными, открывая множество портов только для монтирования общего ресурса. Или запустив его как --privileged

Вот как я решил эту проблему:

  • Сначала подключите том на сервере, на котором запущен Docker.

sudo mount -t cifs -o username=YourUserName,uid=$(id -u),gid=$(id -g)//SERVER/share ~/WinShare

Измените имя пользователя, SERVER и WinShare здесь. Это спросит ваш пароль sudo, а затем попросит пароль для удаленного общего ресурса.

Предположим, вы создали папку WinShare внутри вашей домашней папки. После выполнения этой команды вы сможете увидеть все общие папки и файлы в папке WinShare. В дополнение к этому, поскольку вы используете теги uid и gid вас будет доступ на запись без постоянного использования sudo.

  • Теперь вы можете запустить свой контейнер, используя тег -v и разделить том между сервером и контейнером.

Допустим, вы запустили его следующим образом.

docker run -d --name mycontainer -v/home/WinShare: /home 2d244422164

Теперь вы сможете получить доступ к общей папке Windows и изменить ее из своего контейнера.

Чтобы проверить это просто сделайте:

docker exec -it yourRunningContainer/bin/bash

cd/Home

touch testdocfromcontainer.txt

Вы должны увидеть testdocfromcontainer.txt в testdocfromcontainer.txt Windows.