Olá!

Hoje, nós do mundodocker.com.br, vamos ver como podemos utilizar a funcionalidade de volumes no Docker. Um volume pode ser apenas o mapeamento de pasta entre o host e container, bem como o mapeamento de uma pasta entre containers.

Gerenciando volumes

Host – Container

Na imagem abaixo podemos visualizar como fica o mapeamento entre host e container:

host_containerPodemos analisar os pontos positivos e negativos dessa abordagem em:

Prós:

– Menor overhead para acesso disco, pois não há analise pela libcontainer das chamadas para esse volume mapeado;

– É possível mapear o mesmo volume para múltiplos containers, forma primitiva de replicação de dados entre containers (lembrando que neste caso não há controle de arquivos lidos e escritos ao mesmo tempo, quem deve ser responsável por isso é o filesystem do volume, não o volume em si);

– Persistência de dados, não há risco do container cair ou ser removido e os dados desaparecerem;

Contras:

– Sucessível possíveis brechas de segurança a nível de filesystem, escalonamento de privilégios, pois neste ambiente não há controle pela libcontainer.

– Não escalável, pois  atrela-se o container ao host ou pelo menos ao mapeamento.

– Dificulta administração, pois há mais uma camada de gerenciamento que deve ser muito bem estruturada.

Container – Container

Na imagem abaixo podemos visualizar como fica o mapeamento entre containers:

container_containerPodemos analisar os pontos positivos e negativos dessa abordagem em:

Prós:

– Portável, pois o volume não está mais atrelado ao host;

– É possível mapear o mesmo volume para múltiplos containers, forma primitiva de replicação de dados entre containers (lembrando que neste caso não há controle de arquivos lidos e escritos ao mesmo tempo, quem deve ser responsável por isso é o filesystem do volume, não o volume em si);

– Persistência de dados, não há risco do container cair ou ser removido e os dados desaparecerem;

Contras:

– Maior overhead para acesso disco, pois há analise pela libcontainer das chamadas para esse volume mapeado;

– Maior complexidade, pois há mais passos a serem seguidos para criação e remoção de containers;

Criando e montando volumes

Adicionando um volume de dados

Para mapear o volume do container a uma pasta no host basta executar o comando:

docker run -d --name meucontainer -v /var/app imagem

Será criado um novo diretório dentro do container chamado /var/app, caso o mesmo já exista, será sobrescrito por este novo.

Verificando volume

Você pode verificar quais volumes um container possui executando o comando:

docker inspect meucontainer

O resultado do comando será parecido com isso:

...
Mounts": [
    {
        "Name": "fac362...80535",
        "Source": "/var/lib/docker/volumes/fac362...80535/_data",
        "Destination": "/var/app",
        "Driver": "local",
        "Mode": "",
        "RW": true
    }
]
...

Por padrão todos os volumes são montandos como leitura e escrita, você pode montar o volume como apenas leitura, basta executar:

docker run -d --name meucontainer -v /var/app:ro imagem

Note o :ro no final do /var/app, isso quer dizer que este volume é apenas leitura.

Montando um diretório do host como um volume de dados

Para mapear o volume do container a uma pasta no host basta executar o comando:

docker run -d --name meucontainer -v /var/app:/var/www/html imagem

Será criado um novo diretório dentro do container chamado /var/app, caso o mesmo já exista, será sobrescrito por este novo.

Criando e montando um container como um volume de dados

É possível você criar um container com um volume que pode ser compartilhado com demais containers, isso é uma prática comum quando deseja-se ter alguma persistência de dados e que não esteja atrelado ao host onde o container está. Para isso, crie o container conforme abaixo:

docker create -v /dados --name meucontainer imagem /bin/true

Agora, no próximo container basta você utilizar o parametro –volumes-from para que o volume criado no container acima seja mapeado para o novo container, algo como isso:

docker run -d --volumes-from dados--name meucontainer1 imagem

Você pode criar quantos containers desejar mapeando este volume, inclusive pode mapear o volume de um container, por exemplo:

docker run -d --volumes-from container1 --name meucontainer2 imagem

Com isso não é necessário mapear obrigatoriamente o container de volume, e sim algum container que já utiliza ele. Outro ponto importante a se observar nessa caso é que:

  • Quando removido o container de volume os demais containers não perdem os dados, pois continuará existindo neste container a pasta montada;
  • Para remover o volume nesse caso é necessário remover todos os containers que foram criando mapeando este container e em seguida executar o comando: docker em -v

 

Bom pessoal, espero que tenham gostado, esse assunto é muito importante dentro do Docker, espero fazer um vídeo e disponibilizar para vocês um prática usando volumes.

Não fique com dúvida, mande e-mail para: [email protected] e vamos conversando, ajude a divulgar o blog e disseminar conhecimento, abraço!

Entusiasta Open Source, seu principal foco é ir atrás de ideias novas e torna-las realidade através de soluções simples e eficientes, o menos é mais, e o dividir é multiplicar.
  • Flavio Roncat

    Muito bom post!

  • Obrigado Flavio! Estamos montando uma serie de posts com algo mais prático para que nossos leitores possam visualizar as utilidades do Docker.
    Abraço!

  • Olá, digamos que eu já tenha um container criado e com algumas alterações, eu consigo alterar as configurações de compartilhamento de volumes e encaminhamento de portas? Ou preciso fazer um commit deste container eu uma versão de uma imagem e depois criar um novo container com estas mudanças?

  • Oi Ricardo! obrigado pela pergunta. Pois bem, esse é ainda um dos desafios que o Docker não conseguiu tratar, sim, você está acerto, depois de um container iniciado não é possível modificar as configuração de volume por portas, você terá que gerar uma imagem desse container e iniciar outro baseado nessa imagem. Existe essa necessidade, pois reduziria ainda mais o tempo investido em administração dos containers.

  • Pois é, como está, ao meu ver, o container se comporta como algo muito provisório, sendo que na realidade não, sei se é tão viável tratá-los desta forma (dependendo da aplicação), criando e recriando td hora ou mesmo fazendo commits. Tb não encontrei nenhuma maneira de fazer um merge das imagens usadas em um container, então se eu fizer muitos commits, acabaria criando um mar de layers de imagens vinculadas. Imagino que com o tempo, não seria algo tão simples de administrar.

  • Oi Ricardo, na verdade o ideal é você ter o mínimo de layers possível, os containers devem ser os mais imutáveis possível, se você precisa gerar uma nova imagem a cada alteração na aplicação acredito que o Docker não seja a melhor opção. O mais comum é você encapsular seu ambiente (S.O, variáveis de ambiente, frameworks, etc) em um container e apenas realizar o deploy de sua aplicação ai dentro. Precisou atualizar a aplicação? Instancie um novo container e faça deploy lá, eu pessoalmente recomendo a você ter containers imutáveis e replicáveis é dessa forma que você ganhará em escala.

  • aristoteles

    Olá, uma boa seria mostrar isso automatizado com Dockerfile. Belo post!

  • Oi Aristoteles, valeu pela dica, vamos montar algo sim. Obrigado!

  • aristoteles

    😉 é uma sugestão de dúvida pessoal hahaha vlw!

  • Adriano Ferraz

    O que siginifica o parâmetro ‘-d’?

  • Oi Adriano,
    Esse parâmetro é de deamon, ou seja, não é um container interativo, ele apenas executa o que for passado como comando.

  • Adriano Ferraz

    Olá, é que a maioria dos ‘docker run’ tem esse parâmetro ‘-d’ e isso estava me dando nos nervos já, pois eu executava ‘docker run -d /bin/bash’ e quando eu executa ‘docker ps’ não tinha nada rodando…hoje uso o ‘docker run -itd ‘ estou correto em fazer assim? Abs.

  • Oi Adriano,
    te recomendo a não colocar o d, mas isso só por questão de organização mesmo, da forma que você está utilizando funciona.

  • Tenho um host com dois discos, um com 50GB e outro com 500GB. Gostaria de configurar o Docker para sempre usar para as imagens o disco de 500GB, sendo que o de 50GB é para o SO do host (Debian 8) como faço isso?

    Desculpe se estou sendo muito iniciante, mas não achei em nenhum lugar essa resposta.

  • Oi William,
    Nenhuma pergunta é iniciante, não preocupe. Isso é bem simples, você pode mapear o /var/lib/docker para esse disco maior, não esqueça antes de fazer um backup da pasta, monte a partição como /var/lib/docker e copie para lá a pasta novamente. Com isso tanto as imagens quanto as layers dos containers estarão no disco maior.

  • Obrigado.

  • Alexandre Moura

    Primeiramente gostaria de parabeniza-lo pelo excelente conteúdo que nos é disposto neste site, tenho algumas dúvidas caso você pudesse respondê-las ficaria agradecido.
    Existe a possibilidade de o nosso volume de arquivos ficar em um storage NFS e na hora da montagem do Container ele montar esta partição NFS, porque o meu ambiente é o seguinte eu teria meu container de homologação que seria igual ao de produção, porém nesse container de homologação eu faria os testes do meu sistema para depois passar para o meu container de produção, a outra dúvida seria, caso seja possível, na sua opinião qual seria melhor forma:

    1. O volume de dados no host (como você disse)
    2. O Volume de dados em outro container (como você disse)
    3. O volume de dados em um storage NFS.

    Desde já agradeço pela atenção.

  • Oi Alexandre,
    NFS com certeza é a melhor saída, pois evita configurações nos hosts e deixa seu ambiente mais fácil de ser gerenciado, MAS você estará criando um ponto único de falha, que é seu Storage, se isso não for problema para você, ou não há necessidade de se preocupar com isso agora, ótimo! Use-o ;).
    Lembrando, utilize o volume apenas para os dados que você precisa persistir entre os container (like /var/www/html), tenha em mente: Um container, um processo, e eu posso viver sem ele até subir outro igual.

  • Eu trabalhei com Vagrant e tive um pouco de dificuldade de me adaptar com a diferença entre Vagrantfile e Dockerfile…

    Eu tenho uma certa de dificuldade de entender como criar volumes compartilhados entre o host e o container.

    No Dockerfile eu tenho uma opção para definir o volume é possível compartilhar uma pasta entre meu host e o container através da opção VOLUME no Dockerfile?

  • Oi @alessandrosales:disqus
    A opção VOLUME no Dockerfile vai criar apenas um volume no docker para os containers que você criar através dessa imagem. Para você compartilhar uma pasta do host com o container, você deve fazer no momento da criação do container, usando o paramatro -v, assim:

    docker run -d -v /minha/pasta:/var/www/html apache

    Dessa forma tudo que está na pasta local do host, será mapeado para a pasta dentro do container.