Подключить 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
а затем другой для его извлечения локально). Я не уверен, что вы могли бы использовать трубу, чтобы сделать это за один шаг.
Ответ 4
Вы можете использовать подключаемый модуль тома Netshare Docker, который позволяет монтировать удаленные CIFS/Samba в качестве томов.
Ответ 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.