Как напрямую монтировать общий объем/объем NFS в контейнере с помощью docker compose v3
У меня есть файл для компоновки с v3, где есть 3 службы, разделяющие/использующие один том. При использовании режима роя нам необходимо создать дополнительные контейнеры и тома для управления нашими службами по всему кластеру.
Я планирую использовать NFS-сервер, так что один общий ресурс NFS будет установлен непосредственно на всех узлах кластера.
Я нашел ниже два способа сделать это, но для этого требуются дополнительные шаги для хоста докера -
Есть ли стандартный способ, с помощью которого я могу напрямую использовать/монтировать общий ресурс NFS с помощью docker compose v3, выполнив только несколько/без шагов (я понимаю, что пакет nfs-common требуется в любом случае) на хосте docker?
Ответы
Ответ 1
Узнав, что это массово недокументировано, здесь правильный способ монтирования тома NFS с использованием стека и докера.
Самое главное, что вам нужно использовать version: "3.2"
или выше. У вас будут странные и неочевидные ошибки, если вы этого не сделаете.
Вторая проблема заключается в том, что тома не обновляются автоматически при изменении их определения. Это может привести вас к кроличьей дыре, думая, что ваши изменения неверны, когда они просто не применялись. Убедитесь, что вы используете docker rm VOLUMENAME
везде, где это возможно, как если бы этот том существовал, он не будет проверен.
Третья проблема связана с проблемой NFS. Папка NFS не будет создана на сервере, если она не существует. Это как раз то, как работает NFS. Вы должны убедиться, что он существует, прежде чем что-либо сделать.
(Не удаляйте "soft" и "nolock", если вы не уверены, что знаете, что делаете - это останавливает докер от зависания, если ваш сервер NFS уходит)
Вот полный пример:
[[email protected] docker-mirror]# cat nfs-compose.yml
version: "3.2"
services:
rsyslog:
image: jumanjiman/rsyslog
ports:
- "514:514"
- "514:514/udp"
volumes:
- type: volume
source: example
target: /nfs
volume:
nocopy: true
volumes:
example:
driver_opts:
type: "nfs"
o: "addr=10.40.0.199,nolock,soft,rw"
device: ":/docker/example"
[[email protected] docker-mirror]# docker stack deploy --with-registry-auth -c nfs-compose.yml rsyslog
Creating network rsyslog_default
Creating service rsyslog_rsyslog
[[email protected] docker-mirror]# docker stack ps rsyslog
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
tb1dod43fe4c rsyslog_rsyslog.1 jumanjiman/rsyslog:latest swarm-4 Running Starting less than a second ago
[[email protected] docker-mirror]#
Теперь, на рое-4:
[email protected]:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d883e0f14d3f jumanjiman/rsyslog:latest "rsyslogd -n -f /e..." 6 seconds ago Up 5 seconds 514/tcp, 514/udp rsyslog_rsyslog.1.tb1dod43fe4cy3j5vzsy7pgv5
[email protected]:~# docker exec -it d883e0f14d3f df -h /nfs
Filesystem Size Used Available Use% Mounted on
:/docker/example 7.2T 5.5T 1.7T 77% /nfs
[email protected]:~#
Этот том будет создан (но не разрушен) на любом узле рой, в котором работает стек.
[email protected]:~# docker volume inspect rsyslog_example
[
{
"CreatedAt": "2017-09-29T13:53:59+10:00",
"Driver": "local",
"Labels": {
"com.docker.stack.namespace": "rsyslog"
},
"Mountpoint": "/var/lib/docker/volumes/rsyslog_example/_data",
"Name": "rsyslog_example",
"Options": {
"device": ":/docker/example",
"o": "addr=10.40.0.199,nolock,soft,rw",
"type": "nfs"
},
"Scope": "local"
}
]
[email protected]:~#
Ответ 2
Да, вы можете напрямую ссылаться на NFS из файла компоновки:
volumes:
db-data:
driver: local
driver_opts:
type: nfs
o: addr=$SOMEIP,rw
device: ":$PathOnServer"
И аналогичным образом вы можете создать том nfs на каждом хосте.
docker volume create --driver local --opt type=nfs --opt o=addr=$SomeIP,rw --opt device=:$DevicePath --name nfs-docker
Ответ 3
Мое решение для AWS EFS, которое работает:
- Создать EFS (не забудьте открыть порт NFS 2049 в группе безопасности)
-
Установите пакет nfs-common:
sudo apt-get install -y nfs-common
-
Проверьте, работает ли ваш efs:
mkdir efs-test-point
sudo chmod go+rw efs-test-point
sudo mount -t nfs -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport [YOUR_EFS_DNS]:/ efs-test-point
touch efs-test-point/1.txt
sudo umount efs-test-point/
ls -la efs-test-point/
каталог должен быть пустым
sudo mount -t nfs -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport [YOUR_EFS_DNS]:/ efs-test-point
ls -la efs-test-point/
файл 1.txt должен существовать
-
Сконфигурируйте файл docker-compose.yml:
services:
sidekiq:
volumes:
- uploads_tmp_efs:/home/application/public/uploads/tmp
...
volumes:
uploads_tmp_efs:
driver: local
driver_opts:
type: nfs
o: addr=[YOUR_EFS_DNS],nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2
device: [YOUR_EFS_DNS]:/
Ответ 4
Моя проблема была решена с изменением типа опции драйвера на NFS4.
volumes:
my-nfs-share:
driver: local
driver_opts:
type: "nfs4"
o: "addr=172.24.0.107,rw"
device: ":/mnt/sharedwordpress"
Ответ 5
В зависимости от того, как мне нужно использовать громкость, у меня есть следующие 3 варианта.
Во-первых, вы можете создать именованный том напрямую и использовать его в качестве внешнего тома в compose или в качестве именованного тома в команде docker run
docker service create
или команды docker service create
.
# 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
Далее, есть синтаксис --mount
который работает из docker run
--mount
и docker service create
--mount
. Это довольно длинный параметр, и когда вы встраиваете параметр с разделителями-запятыми в другой параметр с разделителями-запятыми, вам нужно передать некоторые кавычки (экранированные, чтобы оболочка не удаляла их) в выполняемой команде. Я склонен использовать это для одноразового контейнера, которому требуется доступ к NFS (например, служебный контейнер для установки каталогов NFS):
# 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
...
services:
example-app:
volumes:
- "nfs-data:/data"
...
volumes:
nfs-data:
driver: local
driver_opts:
type: nfs
o: nfsvers=4,addr=nfs.example.com,rw
device: ":/path/to/dir"
...
В каждом из этих примеров:
- Тип установлен в
nfs
, а не nfs4
. Это связано с тем, что docker предоставляет некоторые полезные функции для поля addr
, но только для типа nfs
. -
o
- это параметры, которые передаются системному вызову mount. Одно из отличий между монтированием syscall и командой mount в Linux состоит в том, что у устройства есть часть перед параметром :
перемещено в опцию addr
. -
nfsvers
используется для установки версии NFS. Это позволяет избежать задержек, так как ОС сначала пробует другие версии NFS. -
addr
может быть DNS-именем, когда вы используете type=nfs
, а не только IP-адрес. Очень полезно, если у вас есть несколько VPC с разными NFS-серверами, использующими одно и то же DNS-имя, или если вы хотите настроить NFS-сервер в будущем без обновления каждого тома монтирования. - Другие опции, такие как
rw
(чтение-запись), могут быть переданы опции o
. - Поле
device
- это путь на удаленном сервере NFS. Требуется ведущий двоеточие. Это артефакт, как команда монтирования перемещает IP - адрес в addr
поле для системного вызова. Этот каталог должен существовать на удаленном хосте до того, как том будет смонтирован в контейнер. - В синтаксисе
--mount
поле dst
- это путь внутри контейнера. Для именованных томов вы задаете этот путь в правой части монтирования тома (в кратком синтаксисе) в docker run -v
.
Если у вас возникают проблемы с правами доступа к удаленному тому NFS, я часто сталкиваюсь с контейнерами, работающими как root, с сервером NFS, установленным на root squash (изменяя все права доступа root для пользователя nobody). Вам необходимо либо настроить контейнеры для работы с хорошо известным UID без полномочий root, который имеет доступ к каталогам на NFS-сервере, либо отключить корневое сжатие на NFS-сервере.