Как напрямую смонтировать общий ресурс / том NFS в контейнере с помощью docker compose v3

У меня есть файл композиции с v3, где есть 3 службы, использующие один и тот же том. При использовании режима роения нам необходимо создать дополнительные контейнеры и тома для управления нашими сервисами в кластере.

Я планирую использовать сервер NFS, чтобы один общий ресурс NFS монтировался непосредственно на всех хостах в кластере.

Я нашел ниже два способа сделать это, но на хосте докеров нужно выполнить дополнительные шаги:

  • Смонтируйте общий ресурс NFS с помощью команды «fstab» или «mount» на хосте, а затем используйте его в качестве тома хоста для служб докеров.

  • Используйте подключаемый модуль Netshare - https://github.com/ContainX/docker-volume-netshare

Есть ли стандартный способ, при котором я могу напрямую использовать / монтировать общий ресурс NFS с помощью docker compose v3, выполнив всего несколько шагов или не выполняя никаких действий (я понимаю, что пакет «nfs-common» все равно требуется) на хосте докеров?


person vivekyad4v    schedule 24.07.2017    source источник


Ответы (5)


Обнаружив, что это в значительной степени недокументировано, вот правильный способ смонтировать том NFS с помощью стека и компоновки докеров.

Самое главное, что вы должны использовать version: "3.2" или выше. В противном случае у вас будут странные и неочевидные ошибки.

Вторая проблема заключается в том, что тома не обновляются автоматически при изменении их определения. Это может привести вас в кроличью нору к мысли, что ваши изменения неверны, если они просто не были применены. Убедитесь, что вы docker rm VOLUMENAME везде, где это возможно, так как если том существует, он не будет проверен.

Третья проблема больше связана с NFS - папка NFS не будет создана на сервере, если она не существует. Так работает NFS. Вы должны убедиться, что он существует, прежде чем что-либо делать.

(Не удаляйте soft и nolock, если вы не уверены, что знаете, что делаете - это предотвратит зависание докера, если ваш сервер NFS отключится)

Вот полный пример:

[root@docker 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"



[root@docker docker-mirror]# docker stack deploy --with-registry-auth -c nfs-compose.yml rsyslog
Creating network rsyslog_default
Creating service rsyslog_rsyslog
[root@docker 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
[root@docker docker-mirror]#

Теперь о рое-4:

root@swarm-4:~# 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
root@swarm-4:~# docker exec -it d883e0f14d3f df -h /nfs
Filesystem                Size      Used Available Use% Mounted on
:/docker/example          7.2T      5.5T      1.7T  77% /nfs
root@swarm-4:~#

Этот том будет создан (но не уничтожен) на любом узле роя, на котором работает стек.

root@swarm-4:~# 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"
    }
]
root@swarm-4:~#
person xrobau    schedule 29.09.2017
comment
Я использую NFS с compose v3.1. О каких проблемах вы думаете? А как насчет возможного повреждения данных из-за использования программного обеспечения и блокировки? Разве их не следует адресовать в вашем ответе? - person herm; 29.09.2017
comment
@herm, возможно, xrobau говорит о нескольких репликах, обращающихся к одному и тому же серверу nfs. - person Galigator; 20.11.2017
comment
soft позволяет прерывать ввод-вывод. 'nolock' позволяет всегда выполнять вызовы flock (). Если вы полагаетесь на flock () с несколькими пользователями NFS, вы значительно замедляете ввод-вывод диска, и вам следует переделать свое приложение. - person xrobau; 20.11.2017
comment
@xrobau, это было то, что мне нужно было оторваться от привередливого и хлопотного драйвера efs docker volume netshare (DVN). когда я пытался это сделать изначально, то, что привело меня к DVN, было устройство: spec в driver_opts :. Благодарю. - person chrisg; 04.01.2018
comment
Эй, этот метод означает, что IP-адреса жестко запрограммированы в файле yml и не могут быть изменены. Есть ли способ установить их в области контейнера, а затем установить их с помощью файла .env? - person GuySoft; 07.08.2018
comment
Я считаю, что вы можете использовать что-то вроде этого: o: addr = host.docker.internal, rw, nolock, hard, nointr, nfsvers = 3. Внутренний адрес host.docker. волшебный. - person Torenware Networks; 07.08.2018
comment
@GuySoft - Помните, что тома НЕ ОБНОВЛЯЮТСЯ после создания. Наличие IP-адреса сервера NFS в качестве переменной (что я не думаю, что вы все равно можете это сделать) будет просто означать, что монтирование NFS будет отличаться на разных машинах. Лучший способ сделать это - создать НОВЫЙ том (например, 'example_nfs2'), указывающий на другой сервер NFS, а затем изменить источник тома в определении службы. Но - серьезно - тома НЕ ОБНОВЛЯЮТСЯ после создания. Это легкая ловушка для неосторожных. - person xrobau; 08.10.2018

В зависимости от того, как мне нужно использовать громкость, у меня есть следующие 3 варианта.

Во-первых, вы можете создать именованный том напрямую и использовать его как внешний том в compose или как именованный том в команде docker run или 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 и docker service create. Это довольно длинный вариант, и когда вы встраиваете параметр с разделителями-запятыми в другой параметр с разделителями-запятыми, вам нужно передать некоторые кавычки (экранированные, чтобы оболочка не удаляла их) в выполняемую команду. Я обычно использую это для одноразового контейнера, которому нужен доступ к 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 и командой mount в Linux заключается в том, что устройство имеет часть до :, перемещенную в параметр addr.
  • nfsvers используется для установки версии NFS. Это позволяет избежать задержек, поскольку ОС сначала пробует другие версии NFS.
  • addr может быть DNS-именем, когда вы используете type=nfs, а не только IP-адресом. Очень полезно, если у вас есть несколько VPC с разными серверами NFS, использующими одно и то же DNS-имя, или если вы хотите настроить сервер NFS в будущем без обновления каждого монтирования тома.
  • Другие параметры, такие как rw (чтение-запись), можно передать параметру o.
  • Поле device - это путь на удаленном сервере NFS. Обязателен ведущий двоеточие. Это артефакт того, как команда mount перемещает IP-адрес в поле addr для системного вызова. Этот каталог должен существовать на удаленном хосте до того, как том будет смонтирован в контейнер.
  • В синтаксисе --mount поле dst - это путь внутри контейнера. Для именованных томов вы указываете этот путь справа от монтирования тома (в сокращенном синтаксисе) в вашей команде docker run -v.

Если у вас возникают проблемы с разрешениями при доступе к удаленному тому NFS, я часто сталкиваюсь с тем, что контейнеры работают с правами root, а сервер NFS настроен на root squash (изменение всего корневого доступа на пользователя nobody). Вам нужно либо настроить контейнеры для работы с хорошо известным UID без полномочий root, который имеет доступ к каталогам на сервере NFS, либо отключить корневой сквош на сервере NFS.

person BMitch    schedule 17.06.2019
comment
это должен быть ответ: '( - person Valerio Zhang; 04.12.2019
comment
@ValerioZhang Я немного удивлен, что другой ответ получил столько голосов, так как он был опубликован после этого и повторяет почти все, что было опубликовано здесь, но так работает SO несколько дней. - person BMitch; 04.12.2019
comment
ваша - лучше всего написанная, исчерпывающая и лучшая из всех plug-and-play. пожать плечами. Еще раз спасибо, Митч, за ваш вклад! - person Valerio Zhang; 05.12.2019
comment
После успешного создания тома NFS я хотел бы, чтобы он использовался более чем одним контейнером. Но для каждого контейнера требуется отдельный каталог под этим томом. Должен ли я создавать том для каждого каталога или есть дополнительный параметр, который я могу добавить, чтобы указать его? Я попытался добавить папку перед общим ресурсом, но безрезультатно. Спасибо! - person nununo; 28.02.2020
comment
Системный вызов монтирования Linux не позволяет монтировать несуществующий каталог NFS. Перед подключением томов необходимо создать каталоги. - person BMitch; 28.02.2020
comment
Я следил за всем здесь, в докере, в файле compose v3.4 в контейнере Windows. Однако я получаю сообщение об ошибке - Ответ об ошибке от демона: create bf670d3c790fd64bfaf8e3d2fe33ca211075771602093d8fd8494dffb1572c48: параметры не поддерживаются на этой платформе. Есть ли у вас какие-либо идеи? - person Richa Garg; 16.10.2020
comment
@RichaGarg драйвер локального тома передает настройки системному вызову монтирования ядра Linux. Если вы используете контейнеры Windows, у вас нет ядра Linux, которое могло бы принять эти параметры. - person BMitch; 17.10.2020
comment
@BMitch спасибо за ответ. Не могли бы вы рассмотреть этот вопрос stackoverflow.com/questions/64430814/? - person Richa Garg; 19.10.2020

Да, вы можете напрямую ссылаться на 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
person herm    schedule 24.07.2017

Мое решение для AWS EFS, которое работает:

  1. Создать EFS ( не забудьте открыть порт NFS 2049 в группе безопасности)
  2. Установите пакет nfs-common:

    sudo apt-get install -y nfs-common

  3. Проверьте, работает ли ваш 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 должен существовать

  4. Настройте файл 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]:/

person super_p    schedule 12.10.2018

Моя проблема была решена изменением типа опции драйвера на NFS4.

volumes:
  my-nfs-share:
    driver: local
    driver_opts:
      type: "nfs4"
      o: "addr=172.24.0.107,rw"
      device: ":/mnt/sharedwordpress"
person namaiiee    schedule 16.06.2019