volumes de montagem do docker no host


135

Consegui compartilhar pastas entre um contêiner de docker com volumes usando

docker run -v /host/path:/container/path ...

Mas minha pergunta é qual a diferença entre isso e usar o VOLUMEcomando no Dockerfile

VOLUME /path

Estou usando uma imagem que possui um VOLUMEcomando e gostaria de saber como compartilhá-la com meu host. Eu fiz isso usando o -vcomando acima, mas não sabia se precisava do -ve VOLUME.

Respostas:


155

O VOLUMEcomando montará um diretório dentro do seu contêiner e armazenará todos os arquivos criados ou editados dentro desse diretório no disco do host fora da estrutura de arquivos do contêiner , ignorando o sistema de arquivos da união.

A idéia é que seus volumes possam ser compartilhados entre os contêineres do docker e permanecerão por aí enquanto houver um contêiner (em execução ou parado) que os referencie.

Outros contêineres podem montar volumes existentes (compartilhá-los efetivamente entre contêineres) usando o --volumes-fromcomando ao executar um contêiner.

A diferença fundamental entre VOLUMEe -vé este: -vvai montar os arquivos existentes de seu sistema operacional dentro de seu recipiente janela de encaixe e VOLUMEvai criar um novo volume, vazio em seu host e montá-lo dentro de seu recipiente.

Exemplo:

  1. Você tem um Dockerfile que define a VOLUME /var/lib/mysql.
  2. Você cria a imagem da janela de encaixe e a marca some-volume
  3. Você executa o contêiner

E depois,

  1. Você tem outra imagem de janela de encaixe que deseja usar este volume
  2. Você executa o contêiner do docker com o seguinte: docker run --volumes-from some-volume docker-image-name:tag
  3. Agora você tem um contêiner de docker em execução que terá o volume some-volumemontado no/var/lib/mysql

Nota: O uso --volumes-frommontará o volume sobre o que existe no local do volume. Ou seja, se você tiver alguma coisa dentro /var/lib/mysql, ela será substituída pelo conteúdo do volume.


12
O que acontece se eu usar -v em um diretório que já foi especificado em VOLUME?
Jeff Storey

6
--volumes-fromo montará VOLUMEpor cima de qualquer coisa que você especificar -v. Curiosamente, parece que executar o contêiner no modo privilegiado ( docker run --privileged) e umounting /var/lib/mysqldeixará um diretório vazio, para que sua -vmontagem seja completamente ignorada quando entrar em conflito com a VOLUME.
Chris McKinnel

2
Você diz que os volumes são mantidos enquanto um contêiner os referenciar, e eu já vi isso em outro lugar. docs.docker.com/userguide/dockervolumes diz "Os volumes de dados são projetados para persistir dados, independentemente do ciclo de vida do contêiner. Portanto, o Docker nunca exclui automaticamente os volumes quando você remove um contêiner, nem" coleta de lixo "volumes que não são mais referenciado por um contêiner ". Uma dessas declarações deve estar errada.
Mc0e 6/05

1
Os arquivos que estão no volume são mantidos no disco quando um contêiner não faz mais referência a ele, mas o volume em si não é mais utilizável (a menos que você saiba exatamente como conectar manualmente um volume a um contêiner, mas mesmo assim eu não sei ' não sei se isso é possível). Quando digo que não é mais utilizável, quero dizer que você não pode usar - volumes - from para usá-lo. Quando eles dizem "coleta de lixo" acima, significam excluir os arquivos do disco que estavam no volume.
Chris McKinnel

1
Eles são utilizáveis ​​usando -v, mas não --volumes-from. Volumes-from usa um nome de contêiner para buscar dados de volume (acredito que leva TODOS os pontos de volume). Para o próprio -v, no entanto, o manual menciona que você pode fornecer um volume nomeado para -v na forma de named-volume:/path/in/container. Volumes sem nome recebem hashes para nomes e esses hashes podem ser fornecidos em vez de um caminho do host para acessar volumes órfãos. :) Esteja ciente de que volume lstalvez não mostre a todos - tente docker volume ls -f dangling=truetambém.
Jasmine Hegman

44

Deixe-me adicionar minha própria resposta, porque acredito que os outros estão perdendo o objetivo do Docker.

O uso VOLUMEno Dockerfile é o caminho certo ™, porque você informa ao Docker que um determinado diretório contém dados permanentes. O Docker criará um volume para esses dados e nunca os excluirá, mesmo se você remover todos os contêineres que os usam.

Ele também ignora o sistema de arquivos da união, de modo que o volume é de fato um diretório real montado (leitura / gravação ou somente leitura) no lugar certo em todos os contêineres que o compartilham.

Agora, para acessar esses dados do host, você só precisa inspecionar seu contêiner:

# docker inspect myapp
[{
    .
    .
    .
    "Volumes": {
        "/var/www": "/var/lib/docker/vfs/dir/b3ef4bc28fb39034dd7a3aab00e086e6...",
        "/var/cache/nginx": "/var/lib/docker/vfs/dir/62499e6b31cb3f7f59bf00d8a16b48d2...",
        "/var/log/nginx": "/var/lib/docker/vfs/dir/71896ce364ef919592f4e99c6e22ce87..."
    },
    "VolumesRW": {
        "/var/www": false,
        "/var/cache/nginx": true,
        "/var/log/nginx": true
    }
}]

O que eu costumo fazer é criar links simbólicos em algum local padrão como / srv , para que eu possa acessar facilmente os volumes e gerenciar os dados que eles contêm (apenas para os volumes de seu interesse):

ln -s /var/lib/docker/vfs/dir/b3ef4bc28fb39034dd7a3aab00e086e6... /srv/myapp-www
ln -s /var/lib/docker/vfs/dir/71896ce364ef919592f4e99c6e22ce87... /srv/myapp-log

E se o host do docker estiver em execução em uma VM? Por exemplo, boot2docker no mac. Então esses volumes estão disponíveis apenas remotamente. Além disso, ao usar volumes no Dockerfile como você descreveu, o conteúdo da imagem será copiado para o volume. No entanto, ao montar em um diretório local, essa cópia não ocorre. Você sabe por que esse é o caso? Existe uma maneira de ter um volume montado localmente, mas ainda 'começar de novo' com os arquivos da imagem?
LostSalad 4/10/15

4
Com o docker-compose, você pode fazer exatamente isso, montar um volume em um local específico do sistema operacional host . Não há links simbólicos necessários ...
Hugo Koopmans

@Tobia: exemplo docker-compose, consulte os documentos docs.docker.com/compose/compose-file/…
Hugo Koopmans

11

VOLUME é usado Dockerfilepara expor o volume a ser usado por outros recipientes. Exemplo, crie Dockerfilecomo:

FROM ubuntu: 14.04

RUN mkdir /myvol  
RUN echo "hello world" > /myvol/greeting  
VOLUME /myvol

construa a imagem:

$ docker build -t testing_volume .

Execute o contêiner, digamos container1:

$ docker run -it <image-id of above image> bash

Agora execute outro contêiner com a opção de volumes como (digamos, container2)

$ docker run -it --volumes-from <id-of-above-container> ubuntu:14.04 bash

Você receberá todos os dados do /myvoldiretório container1 no container2 no mesmo local.

-vA opção é fornecida no tempo de execução do contêiner, usado para montar o diretório do contêiner no host. É simples de usar, basta fornecer -vopção com argumento <host-path>:<container-path>. Todo o comando pode ser tão$ docker run -v <host-path>:<container-path> <image-id>


8

Basicamente VOLUMEe -vopção são quase iguais. Isso significa 'montar diretório específico no seu contêiner'. Por exemplo, VOLUME /datae -v /dataé exatamente o mesmo significado. Se você executar a imagem que possui VOLUME /dataou com a -v /dataopção, o /datadiretório está montado em seu contêiner. Este diretório não pertence ao seu contêiner.

Imagine que você inclua alguns arquivos /datano contêiner e confirme o contêiner na nova imagem. Não há arquivos no diretório de dados porque o /datadiretório montado pertence ao contêiner original.

$ docker run -it -v /data --name volume ubuntu:14.04 bash
root@2b5e0f2d37cd:/# cd /data
root@2b5e0f2d37cd:/data# touch 1 2 3 4 5 6 7 8 9
root@2b5e0f2d37cd:/data# cd /tmp
root@2b5e0f2d37cd:/tmp# touch 1 2 3 4 5 6 7 8 9
root@2b5e0f2d37cd:/tmp# exit
exit

$ docker commit volume nacyot/volume  
835cfe3d8d159622507ba3256bb1c0b0d6e7c1419ae32751ad0f925c40378945
nacyot $ docker run -it nacyot/volume
root@dbe335c7e64d:/# cd /data
root@dbe335c7e64d:/data# ls
root@dbe335c7e64d:/data# cd /tmp
root@dbe335c7e64d:/tmp# ls
1  2  3  4  5  6  7  8  9
root@dbe335c7e64d:/tmp# 
root@dbe335c7e64d:/tmp# 

Esse diretório montado como /dataé usado para armazenar dados que não pertencem ao seu aplicativo. E você pode predefinir o diretório de dados que não pertence ao contêiner usando VOLUME.

Uma diferença entre Volumee -vopção é que você pode usar a -vopção dinamicamente ao iniciar o contêiner. Isso significa que você pode montar algum diretório dinamicamente. E outra diferença é que você pode montar o diretório host em seu contêiner usando-v


8

Isso é da própria documentação do Docker, pode ser útil, simples e claro:

"O diretório host é, por natureza, dependente do host. Por esse motivo, você não pode montar um diretório host no Dockerfile, a instrução VOLUME não suporta a passagem de um diretório host, porque as imagens criadas devem ser portáteis. O diretório não estaria disponível em todos os hosts em potencial. "

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.