Montando um diretório NFS no volume do host que é compartilhado com o Docker

7

Considere o seguinte contêiner do Docker:

docker run --rm -it -v /tmp:/mnt/tmp alpine sh

Isso monta o diretório do host / tmp em / mnt / tmp dentro do contêiner alpino.

Agora, no sistema host, montei um volume NFS no diretório / tmp:

mkdir /tmp/nfs
mount -t nfs4 192.168.1.100:/data /tmp/nfs

A montagem funciona no sistema host e vejo o seguinte:

# ls /tmp/nfs
file1 file2 file3
#

Mas no Container do Docker, vejo um diretório em branco:

# ls /mnt/tmp/nfs
#

Eu sei que posso contornar isso fazendo a montagem diretamente no Contêiner do Docker. Mas estou realmente interessado em saber por que a montagem funciona no contêiner do host, mas não no contêiner docker?

    
por Caleb 30.06.2016 / 02:37

3 respostas

12

Isso acontece porque o volume está usando a propagação private mount. Isso significa que, uma vez que a montagem acontece, quaisquer alterações que ocorram no lado da origem (por exemplo, o lado "host" no caso do Docker) não estarão visíveis sob o suporte.

Existem algumas maneiras de lidar com isso:

  1. Execute a montagem do NFS primeiro e inicie o contêiner. A montagem será propagada para o contêiner, no entanto, como antes, quaisquer alterações na montagem não serão vistas pelo contêiner (incluindo desmontagens).

  2. Use a propagação "escrava". Isso significa que, depois que a montagem for criada, qualquer alteração no lado da origem (host do Docker) poderá ser vista no destino (no contêiner). Se acontecer de você estar fazendo montagens aninhadas, você vai querer usar rslave ( r para recursivo).

Há também propagação "compartilhada". Este modo faria alterações no ponto de montagem de dentro do contêiner propagado para o host, bem como o contrário. Como o usuário não teria privilégios para fazer tais alterações (a menos que você adicione CAP_SYS_ADMIN), provavelmente não é isso que você deseja.

Você pode definir o modo de propagação ao criar a montagem assim:

$ docker run -v /foo:/bar:private

A outra alternativa seria usar um volume em vez de um host. Você pode fazer isso assim:

$ docker volume create \
    --name mynfs \
    --opt type=nfs \
    --opt device=:<nfs export path> \
    --opt o=addr=<nfs host> \
    mynfs
$ docker run -it -v mynfs:/foo alpine sh

Isso sempre irá montar o contêiner sempre para você, não depende de ter a configuração do host de alguma maneira específica ou de lidar com a propagação de montagem.
note : o : na frente do caminho do dispositivo é necessário, apenas algo estranho sobre o módulo do kernel nfs.
note : O Docker não resolve atualmente <nfs host> de um nome DNS (ele irá em 1.13) então você precisará fornecer o endereço IP aqui.

Mais detalhes sobre montagens de "subárvores compartilhadas": link

    
por 03.11.2016 / 03:44
4

Habilite a propagação de montagem compartilhada no volume adicionando o sinalizador: shared ao final do argumento de volume:

docker run --rm -it -v /tmp:/mnt/tmp:shared alpine sh

Se o Docker foi instalado por meio de um gerenciador de pacotes ou script de instalação do systemd, talvez seja necessário ajustar o argumento do daemon do MountFlags. Para fazer isso, localize o arquivo docker.service:

$ sudo find /etc -name "docker.service"

No meu caso no Ubuntu 16.04, ele estava localizado em /etc/systemd/system/multi-user.target.wants/docker.service. Edite esse arquivo com vi ou nano e verifique se a opção MountFlags lê:

MountFlags=shared

Salve o arquivo, recarregue os argumentos do daemon e reinicie o docker:

$ sudo systemctl daemon-reload
$ sudo systemctl restart docker

Agora, você deve poder definir o sinalizador de propagação de montagem compartilhada em volumes ao usar "docker run".

    
por 01.07.2016 / 17:37
2

A partir do docker 17.06, você pode montar compartilhamentos do NFS diretamente no contêiner ao executá-lo, sem a necessidade de recursos extras

export NFS_VOL_NAME=mynfs NFS_LOCAL_MNT=/mnt/mynfs NFS_SERVER=my.nfs.server.com NFS_SHARE=/my/server/path NFS_OPTS=vers=4,soft

docker run --mount \
  "src=$NFS_VOL_NAME,dst=$NFS_LOCAL_MNT,volume-opt=device=:$NFS_SHARE,\"volume-opt=o=addr=$NFS_SERVER,$NFS_OPTS\",type=volume,volume-driver=local,volume-opt=type=nfs" \
  busybox ls $NFS_LOCAL_MNT

Como alternativa, você pode criar o volume antes do contêiner:

docker volume create --driver local \
  --opt type=nfs --opt o=addr=$NFS_SERVER,$NFS_OPTS \
  --opt device=:$NFS_SHARE $NFS_VOL_NAME

docker run --rm -v $NFS_VOL_NAME:$NFS_LOCAL_MNT busybox ls $NFS_LOCAL_MNT

Entendi a dica de link

    
por 28.08.2017 / 04:53

Tags