
Я новичок в Docker и хочу использовать его для получения контролируемой среды компиляции моего кода.
У меня уже есть образ Docker со всеми необходимыми мне инструментами. Моя проблема на данный момент заключается в следующем:
- Мой код находится на хост-машине, внутри моей домашней папки, которая смонтирована с сервера NFS.
- Я хочу сделать эту папку видимой внутри контейнера Docker с правами r+w.
Вот что я попробовал сделать в первую очередь (запустить контейнер с исходной папкой в качестве тома) и какая ошибка у меня возникла:
[mbrandalero@machine ~]$ docker run -it --cap-add sys_admin -v "/homes/mbrandalero/src:/usr/local/src/" mbrandalero/my-image bash
/usr/bin/docker-current: Error response from daemon: error while creating mount source path '/homes/mbrandalero/src': mkdir /homes/mbrandalero/src: permission denied.
(судя по всему, он пытается создать каталог на стороне хоста, но он уже там)
Любопытно, что когда я пытаюсь запустить контейнер со всей домашней папкой в качестве тома, это работает, но выдает другую ошибку (нет разрешения на запись в папку):
[mbrandalero@machine ~]$ docker run -it --cap-add sys_admin -v "/homes/mbrandalero/:/usr/local/src/home" mbrandalero/my_image bash
root@46712ad936f2:/usr/local/src# cd home/
bash: cd: home/: Permission denied
root@46712ad936f2:/usr/local/src# ls -lah | grep "\(\.\|home\)"
total 4.0K
drwxr-xr-x 1 root root 18 May 20 14:50 .
drwxr-xr-x 1 root root 17 May 15 14:06 ..
drwxr-x--- 30 10031 10031 4.0K May 20 15:03 home
Правильно ли я делаю? Что я упускаю?
Дополнительная информация:
- Операционная система: CentOS Linux 7.6
- Версия докера: 1.13.1
ОБНОВЛЕНИЕ (1):
Видимо, установка идентификатора пользователя при запуске docker run
решает проблему, но правильный ли это способ? Запуск таким образом вроде как исправляет ситуацию, но выглядит странно (я получаю "I have no name!" в качестве имени пользователя):
[mbrandalero@machine ~]$ docker run -it --cap-add sys_admin -v "/homes/mbrandalero/:/usr/local/src/home" --user $(id -u) mbrandalero/my_image bash
I have no name!@2efec822e572:/usr/local/src$ cd home/
I have no name!@2efec822e572:/usr/local/src/home$
решение1
Как вы отметили в своем обновлении, UID файлов не отображается в привязке монтирования, это то, как Linux делает привязку монтирования. Вы можете запустить контейнер с другим UID, но это приведет к тому, что /etc/passwd внутри контейнера будет отображаться на другого пользователя или даже на никакого (в вашем случае). Есть разные варианты, но я предпочитаю изменять UID контейнера с помощью команды usermod, которая запускается внутри точки входа для образа с моимскрипт исправления-перезагрузки. Это нужно запускать как root, но затем вы можете использовать gosu
его, чтобы вернуться к пользователю при выполнении команд. Я говорил об этом в своемпрезентации dockercon.
Обратите внимание, что вместо привязки к каталогу NFS хоста вы также можете выполнить монтирование тома непосредственно на сервере NFS. Вот несколько примеров того, как это сделать:
# create a reusable volume
$ docker volume create --driver local \
--opt type=nfs \
--opt o=nfsvers=4,addr=nfs.example.com,rw \
--opt device=:/path/to/dir \
foo
# or from the docker run command
$ docker run -it --rm \
--mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=nfs,\"volume-opt=o=nfsvers=4,addr=nfs.example.com\",volume-opt=device=:/host/path \
foo
# or to create a service
$ docker service create \
--mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=nfs,\"volume-opt=o=nfsvers=4,addr=nfs.example.com\",volume-opt=device=:/host/path \
foo
# inside a docker-compose file
...
volumes:
nfs-data:
driver: local
driver_opts:
type: nfs
o: nfsvers=4,addr=nfs.example.com,rw
device: ":/path/to/dir"
...
решение2
В случае, если вы запускаете свой контейнер как root
, вы можете столкнуться с этим error while creating mount source path ... permission denied
сообщением, поскольку хост NFS переназначает все удаленные корневые UID (т. н. root-squash).
https://en.wikipedia.org/wiki/Unix_security#Root_squash
Это функция, ориентированная на безопасность, которая не позволяет злоумышленнику смонтировать ваш ресурс как своего root
пользователя, а затем сделать что-то плохое с данными. Таким образом, монтирования NFS обычно имеют опцию, root_squash
установленную по умолчанию, чтобы предотвратить подобные проблемы. В случае, если вам нужно, чтобы ваш контейнер работал как root
, вы можете переопределить это, используя опцию в файле no_root_squash
вашего хоста NFS ./etc/exports
/srv/nfs/shared_folder <hostname>(rw,sync,no_subtree_check,no_root_squash)
http://nfs.sourceforge.net/nfs-howto/ar01s03.html
https://www.thegeekdiary.com/understanding-the-etc-exports-file/
решение3
Это сработало для меня - объявил путь хоста nfs как том к контейнеру. И путь хоста nfs - это путь не домашнего каталога, это не домашний каталог.
Точка монтирования nfs моего хоста:/mnt/abc
Фрагмент моего файла docker-compose.yml.
...
volumes:
- /mnt/abc/:/abc
...