Como montar volumes locais na máquina docker

86

Estou tentando usar docker-machine com docker-compose. O arquivo docker-compose.yml tem as seguintes definições:

web:
  build: .
  command: ./run_web.sh
  volumes:
    - .:/app
  ports:
    - "8000:8000"
  links:
    - db:db
    - rabbitmq:rabbit
    - redis:redis

Ao correr docker-compose up -dtudo vai bem até tentar executar o comando e ocorrer um erro:

Não é possível iniciar o contêiner b58e2dfa503b696417c1c3f49e2714086d4e9999bd71915a53502cb6ef43936d: [8] Erro do sistema: exec: "./run_web.sh": stat ./run_web.sh: nenhum arquivo ou diretório

Os volumes locais não são montados na máquina remota. Qual é a estratégia recomendada para montar os volumes locais com o código dos webapps?

jdcaballerov
fonte
A estrutura do projeto e docker-compose.yml é semelhante a este tutorial syncano.com/…
jdcaballerov
1
Isso deve estar nos documentos docker-compose como uma dica útil para aqueles que podem começar a usar o compose localmente. Teria me poupado horas de momentos WTF tentando descobrir por que diabos o caminho do meu arquivo estava errado ou não foi encontrado. Não, eu apenas me sinto boba.
Timbrown de

Respostas:

93

A máquina Docker monta automaticamente o diretório de usuários ... Mas às vezes isso não é suficiente.

Não sei sobre o docker 1.6, mas no 1.8 você PODE adicionar uma montagem adicional à docker-machine

Adicionar Ponto de Montagem de Máquina Virtual (parte 1)

CLI : (só funciona quando a máquina está parada)

VBoxManage sharedfolder add <machine name/id> --name <mount_name> --hostpath <host_dir> --automount

Portanto, um exemplo no Windows seria

/c/Program\ Files/Oracle/VirtualBox/VBoxManage.exe sharedfolder add default --name e --hostpath 'e:\' --automount

GUI : (NÃO requer que a máquina seja parada)

  1. Inicie o "Oracle VM VirtualBox Manager"
  2. Clique com o botão direito <machine name>(padrão)
  3. Configurações...
  4. Pastas partilhadas
  5. A pasta + ícone à direita (adicionar compartilhamento)
  6. Caminho da pasta: <host dir>(e :)
  7. Nome da pasta: <mount name>(e)
  8. Marque "Montagem automática" e "Tornar permanente" (leia apenas se quiser ...) (A montagem automática é meio inútil atualmente ...)

Montagem em boot2docker (parte 2)

Monte manualmente no boot2docker :

  1. Existem várias maneiras de fazer login, use "Mostrar" no "Oracle VM VirtualBox Manager" ou ssh / putty no docker por endereço IP docker-machine ip default, etc ...
  2. sudo mkdir -p <local_dir>
  3. sudo mount -t vboxsf -o defaults,uid=`id -u docker`,gid=`id -g docker` <mount_name> <local_dir>

Mas isso só é bom até você reiniciar a máquina, e então a montagem é perdida ...

Adicionando uma montagem automática ao boot2docker :

Enquanto estiver conectado à máquina

  1. Editar / criar (como root) /mnt/sda1/var/lib/boot2docker/bootlocal.sh, sda1 pode ser diferente para você ...
  2. Adicionar

    mkdir -p <local_dir>
    mount -t vboxsf -o defaults,uid=`id -u docker`,gid=`id -g docker` <mount_name> <local_dir>
    

Com essas mudanças, você deve ter um novo ponto de montagem. Este é um dos poucos arquivos que encontrei que é chamado na inicialização e é persistente. Até que haja uma solução melhor, isso deve funcionar.


Método antigo: menos recomendado , mas deixado como uma alternativa

  • Editar (como root) /mnt/sda1/var/lib/boot2docker/profile, sda1 pode ser diferente para você ...
  • Adicionar

    add_mount() {
      if ! grep -q "try_mount_share $1 $2" /etc/rc.d/automount-shares ; then
        echo "try_mount_share $1 $2" >> /etc/rc.d/automount-shares
      fi
    }
    
    add_mount <local dir> <mount name>
    

Como último recurso , você pode escolher a alternativa um pouco mais tediosa e pode apenas modificar a imagem de inicialização.

  • git -c core.autocrlf=false clone https://github.com/boot2docker/boot2docker.git
  • cd boot2docker
  • git -c core.autocrlf=false checkout v1.8.1 #ou sua versão apropriada
  • Editar rootfs/etc/rc.d/automount-shares
  • Adicione a try_mount_share <local_dir> <mount_name>linha logo antes de fi no final. Por exemplo

    try_mount_share /e e
    

    Apenas certifique-se de não configurar o para qualquer coisa que o sistema operacional precise, como / bin, etc ...

  • docker build -t boot2docker . #Isso levará cerca de uma hora na primeira vez :(
  • docker run --rm boot2docker > boot2docker.iso
  • Faça backup do boot2docker.iso antigo e copie o novo em seu lugar, em ~ / .docker / machine / machines /

Isso funciona, é apenas longo e complicado

docker versão 1.8.1, docker-machine versão 0.4.0

Andy
fonte
Para qualquer um que tenha problemas com isso, tenho quase certeza de que devo fazer com que os caminhos locais correspondam aos da docker-machine. Além disso, docker-compose parecia ter sucesso na montagem dos volumes, enquanto o docker regular não - não sei por quê.
espiado em
3
Criou um script para a solução mencionada aqui. Funciona no último docker 1.10 e docker-machine 0.6.0 gist.github.com/cristobal/fcb0987871d7e1f7449e
cristobal
Recursos diferentes falam sobre o uso /mnt/sda1/var/lib/boot2docker/profile, você pode explicar por que mudou para o uso /mnt/sda1/var/lib/boot2docker/bootlocal.sh? Além disso, riscar tanto texto não contribui para a legibilidade da sua resposta ;-)
Forragem
1
@Forage Point levado sobre minha formatação :). Não me lembro mais por que sugiro o bootlocal.shmétodo. Tudo o que posso dizer é que parece mais limpo apenas usar um comando de montagem como fiz no bootlocal.shdo que no perfil. Além disso, normalmente, acredito que o profilepode ser executado várias vezes, e uma montagem só precisa ser executada uma vez, por isso faz mais sentido. Mas ambos podem funcionar.
Andy
ADORO! Obrigado!
Qorbani
28

Também tive esse problema e parece que os volumes locais não são montados ao usar docker-machine. Uma solução de hack é

  1. obter o diretório de trabalho atual da instância docker-machine docker-machine ssh <name> pwd

  2. use uma ferramenta de linha de comando como rsynccopiar a pasta para o sistema remoto

    rsync -avzhe ssh --progress <name_of_folder> username@remote_ip:<result _of_pwd_from_1>.
    

O pwd padrão é / root, então o comando acima seria rsync -avzhe ssh --progress <name_of_folder> username@remote_ip:/root

NB: você precisará fornecer a senha para o sistema remoto. Você pode criar um rapidamente por ssh no sistema remoto e criando uma senha.

  1. mude o ponto de montagem do volume em seu docker-compose.ymlarquivo de .:/apppara/root/<name_of_folder>:/app

  2. corre docker-compose up -d

NB: quando as alterações são feitas localmente, não se esqueça de executar novamente rsyncpara enviar as alterações para o sistema remoto.

Não é perfeito, mas funciona. Um problema está em andamento https://github.com/docker/machine/issues/179

Outro projeto que tenta resolver isso inclui docker-rsync

gbozee
fonte
rsync precisa ser instalado no sistema remoto, parece `sh: rsync: não encontrado rsync: conexão fechada inesperadamente (0 bytes recebidos até agora) [remetente] erro rsync: comando remoto não encontrado (código 127) em / SourceCache / rsync / rsync -45 / rsync / io.c (453) [sender = 2.6.9] `Como você fez com que funcionasse?
Krinker
1
O rsync precisa ser instalado em seu sistema local
gbozee
Usar essas etapas bloqueia completamente meu host digitalocean. Os arquivos são transferidos sem problemas, mas quando tento reconectar ao host com docker-machine, consigo exit status 255e tenho que recriar completamente a máquina.
dsifford
1
Criou um script para a solução mencionada aqui. Funciona na mais recente docker 1.10e docker-machine 0.6.0 gist.github.com/cristobal/fcb0987871d7e1f7449e
cristobal
@cristobal parece que você fez o script da solução de montagem, não da solução rsync?
Andy
14

No momento, não consigo ver nenhuma maneira de montar volumes em máquinas, então a abordagem agora seria copiar ou sincronizar de alguma forma os arquivos de que você precisa para a máquina.

conversas sobre como resolver esse problema no repositório github da docker-machine. Alguém fez uma solicitação de pull implementando scp na docker-machine e já está mesclado no master, então é muito provável que a próxima versão o inclua.

Como ainda não foi lançado, agora eu recomendaria que, se você tem seu código hospedado no github, apenas clone seu repo antes de executar o aplicativo

web:
  build: .
  command: git clone https://github.com/my/repo.git; ./repo/run_web.sh
  volumes:
    - .:/app
  ports:
    - "8000:8000"
  links:
    - db:db
    - rabbitmq:rabbit
    - redis:redis

Atualização: Olhando mais além, descobri que o recurso já está disponível nos binários mais recentes , quando você os obtiver, poderá copiar seu projeto local executando um comando como este:

docker-machine scp -r . dev:/home/docker/project

Sendo esta a forma geral:

docker-machine scp [machine:][path] [machine:][path]

Assim, você pode copiar arquivos de, para e entre máquinas.

Saúde! 1

claudevandort
fonte
a documentação para docker-machine scp: docs.docker.com/machine/reference/scp
Anthony Dahanne
2
este método é muito lento :(
Sergej Jevsejev
5

Desde outubro de 2017, há um novo comando para docker-machine que resolve o problema, mas certifique-se de que não haja nada no diretório antes de executá-lo, caso contrário, ele pode se perder:

docker-machine mount <machine-name>:<guest-path> <host-path>

Verifique os documentos para obter mais informações: https://docs.docker.com/machine/reference/mount/

PR com a mudança: https://github.com/docker/machine/pull/4018

Jorge
fonte
1
Inacreditavelmente, a partir da documentação da Docker Machine (que você vinculou), é - literalmente - impossível saber se a ordem do comando é ...:<guest-path> <host-path>(e não o contrário). Algo tão simples e crítico quanto isso para anotar na documentação ... simplesmente não é!
Dan Nissenbaum
Acho que não é muito explícito, você tem razão. Tem que ser adivinhado na lista de comandos
Jorge
Funciona, mas de outra maneira. Ele permite montar o diretório docker-machine em sua máquina local. Infelizmente, não permite outra maneira :(
ravenwing
4

Se você escolher a opção rsync com docker-machine, poderá combiná-la com o docker-machine ssh <machinename>comando como este:

rsync -rvz --rsh='docker-machine ssh <machinename>' --progress <local_directory_to_sync_to> :<host_directory_to_sync_to>

Ele usa este formato de comando de rsync, deixando em HOSTbranco:

rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST

( http://linuxcommand.org/man_pages/rsync1.html )

dmh
fonte
1

Finalmente descobri como atualizar o Windows Docker Toolbox para v1.12.5 e manter meus volumes funcionando adicionando uma pasta compartilhada no Oracle VM VirtualBoxgerenciador e desabilitando a conversão de caminho. Se você tem o Windows 10+, é melhor usar o Docker para Windows mais recente.

Primeiro a dor de atualização:

  1. Desinstale o VirtualBox primeiro.
    • Sim, isso pode quebrar coisas em outras ferramentas como o Android Studio. Obrigado Docker :(
  2. Instale a nova versão do Docker Toolbox.

Exemplo de banco de dados Redis: redis: image: redis:alpine container_name: redis ports: - "6379" volumes: - "/var/db/redis:/data:rw"

No Terminal Docker Quickstart ....

  1. executar docker-machine stop default- Certifique-se de que a VM esteja interrompida

No Oracle VM VirtualBox Manager ...

  1. Adicionada uma pasta compartilhada na defaultVM via ou linha de comando
    • D:\Projects\MyProject\db => /var/db

Em docker-compose.yml...

  1. Volume redis mapeado como: "/var/db/redis:/data:rw"

No Terminal Docker Quickstart ....

  1. Definido COMPOSE_CONVERT_WINDOWS_PATHS=0(para a versão do Toolbox> = 1.9.0)
  2. execute docker-machine start defaultpara reiniciar a VM.
  3. cd D:\Projects\MyProject\
  4. docker-compose up deve funcionar agora.

Agora cria banco de dados redis em D:\Projects\MyProject\db\redis\dump.rdb

Por que evitar caminhos de host relativos?

Eu evitado caminhos de acolhimento relativas para Windows caixa de ferramentas como eles podem introduzir '\' caracteres inválidos. Não é tão bom quanto usar caminhos relativos a, docker-compose.ymlmas pelo menos meus colegas desenvolvedores podem fazer isso facilmente, mesmo se sua pasta de projeto estiver em outro lugar, sem ter que hackear o docker-compose.ymlarquivo (ruim para SCM).

Problema Original

Para sua informação ... Aqui está o erro original que recebi quando usei bons caminhos relativos limpos que costumavam funcionar bem para versões mais antigas. Meu mapeamento de volume costumava ser apenas"./db/redis:/data:rw"

ERROR: for redis Cannot create container for service redis: Invalid bind mount spec "D:\\Projects\\MyProject\\db\\redis:/data:rw": Invalid volume specification: 'D:\Projects\MyProject\db\redis:/data

Isso quebra por dois motivos ..

  1. Não pode acessar o D:drive
  2. Caminhos de volume não podem incluir \caracteres
    • docker-compose adiciona e depois culpa você por isso !!
    • Use COMPOSE_CONVERT_WINDOWS_PATHS=0para parar com esse absurdo.

Eu recomendo documentar seu mapeamento de pasta compartilhada VM adicional em seu docker-compose.ymlarquivo, pois pode ser necessário desinstalar o VirtualBox novamente e redefinir a pasta compartilhada e, de qualquer forma, seus colegas desenvolvedores vão adorar você por isso.

Tony O'Hagan
fonte
você senhor, é uma boa pessoa
AaronHS
1

Todas as outras respostas foram boas para o momento, mas agora (Docker Toolbox v18.09.3) tudo funciona fora da caixa. Você só precisa adicionar uma pasta compartilhada no VirtualBox VM.

O Docker Toolbox adiciona automaticamente C:\Usersuma pasta compartilhada /c/Usersna máquina virtual linux (usando o recurso de pastas compartilhadas do Virtual Box), portanto, se o seu docker-compose.ymlarquivo estiver localizado em algum lugar sob este caminho e você montar os diretórios da máquina host apenas neste caminho - tudo deve funcionar imediatamente.

Por exemplo:

C:\Users\username\my-project\docker-compose.yml:

...
  volumes:
    - .:/app
...

O .caminho será convertido automaticamente em caminho absoluto C:\Users\username\my-projecte depois em /c/Users/username/my-project. E é exatamente assim que esse caminho é visto do ponto de vista da máquina virtual linux (você pode conferir: docker-machine sshe depois ls /c/Users/username/my-project). Então, a montagem final será /c/Users/username/my-project:/app.

Tudo funciona de forma transparente para você.

Mas isso não funciona se o caminho de montagem do host não estiver sob o C:\Userscaminho. Por exemplo, se você colocar o mesmo docker-compose.ymlem D:\dev\my-project.

Isso pode ser corrigido facilmente.

  1. Pare a máquina virtual ( docker-machine stop).
  2. Abra a GUI do Virtual Box, abra as configurações da máquina virtual nomeada default, abra a Shared Foldersseção e adicione a nova pasta compartilhada:

    • Caminho da pasta: D:\dev
    • Nome da pasta: d/dev

    Pressione OKduas vezes e feche a GUI do Virtual Box.

  3. Inicie a máquina virtual ( docker-machine start).

Isso é tudo. Todos os caminhos da máquina host sob D:\devdevem funcionar agora nas docker-compose.ymlmontagens.

Ruslan Stelmachenko
fonte
1

Pode ser combinação bruxa feito de três ferramentas: docker-machine mount, rsync,inotifywait

TL; DR

O script baseado em tudo abaixo está aqui

Digamos que você tenha seu docker-compose.ymle run_web.shem/home/jdcaballerov/web

  1. Monte o diretório na máquina que tem o mesmo caminho que você tem em seu hostdocker-machine machine:/home/jdcaballerov/web /tmp/some_random_dir
  2. Sincronize o diretório montado com o dir em seu host rsync -r /home/jdcaballerov/web /tmp/some_random_dir
  3. Sincronize a cada mudança de arquivos em seu diretório:

    inotifywait -r -m -e close_write --format '%w%f' /home/jdcaballerov/web | while read CHANGED_FILE
    do
        rsync /home/jdcaballerov/web /tmp/some_random_dir
    done
    

ATENÇÃO - há dois diretórios com o mesmo caminho - um está na máquina local (host), o segundo está na máquina docker.

asa de corvo
fonte
0

Presumo que o run_web.sharquivo esteja no mesmo diretório do seu docker-compose.ymlarquivo. Então o comando deve ser command: /app/run_web.sh.

A menos Dockerfileque (que você não está divulgando) se encarregue de colocar o run_web.sharquivo na imagem do Docker.

Thomasleveil
fonte
obrigado pela sua resposta. Ele está no mesmo diretório. No entanto, noto que o volume não está sendo aumentado. Os arquivos não estão disponíveis, e essa é a questão. Como adicioná-los. A estrutura é semelhante a syncano.com/…
jdcaballerov
Certifique-se de ter as versões mais recentes de docker e dicker-compose.
Thomasleveil
docker: Docker versão 1.6.0, compilação 4749651, docker-machine versão 0.2.0 (8b9eaf2), docker-compose 1.2.0
jdcaballerov
Você modificou o Dockerfile de syncano.com/… de alguma forma?
Thomasleveil
1
Sim, eu adiciono o código, crio o diretório. O problema é que quando docker-compose é executado, ele sobrescreve o volume: volumes: -.: / App e deixa um diretório vazio. Comentei volumes na composição e funciona.
jdcaballerov
0

Depois de resumir as postagens aqui, o script atualizado anexado cria um ponto de montagem de host adicional e montagem automática quando o Virtualbox reiniciar. O resumo do ambiente de trabalho é o seguinte: - Windows 7 - docker-machine.exe versão 0.7.0 - VirtualBox 5.0.22

    #!env bash

    : ${NAME:=default}
    : ${SHARE:=c/Proj}
    : ${MOUNT:=/c/Proj}
    : ${VBOXMGR:=C:\Program Files\Oracle\VirtualBox\VBoxManage.exe}
    SCRIPT=/mnt/sda1/var/lib/boot2docker/bootlocal.sh

    ## set -x
    docker-machine stop $NAME
    "$VBOXMGR" sharedfolder add $NAME --name c/Proj --hostpath 'c:\' --automount 2>/dev/null || :
    docker-machine start $NAME
    docker-machine env $NAME

    docker-machine ssh $NAME 'echo "mkdir -p $MOUNT" | sudo tee $SCRIPT'
    docker-machine ssh $NAME 'echo "sudo mount -t vboxsf -o rw,user $SHARE $MOUNT" |  sudo tee -a $SCRIPT'
    docker-machine ssh $NAME 'sudo chmod +x /mnt/sda1/var/lib/boot2docker/bootlocal.sh'
    docker-machine ssh $NAME 'sudo /mnt/sda1/var/lib/boot2docker/bootlocal.sh'
    #docker-machine ssh $NAME 'ls $MOUNT'
Jesse
fonte
0

Estou usando docker-machine 0.12.2 com a unidade virtualbox em minha máquina local. Descobri que existe um diretório /hosthome/$(user name)de onde você tem acesso aos arquivos locais.

Benjamin Slabbert
fonte
0

Pensei em mencionar que estou usando 18.03.1-ce-win65 (17513) no Windows 10 e percebi que, se você compartilhou uma unidade e armazenou as credenciais em cache, depois de alterar sua senha, o docker começará a ter os volumes montados em contêineres em branco.

Não dá nenhuma indicação de que o que realmente está acontecendo é que agora ele não está conseguindo acessar o compartilhado com as credenciais antigas armazenadas em cache. A solução neste cenário é redefinir as credenciais por meio da IU (Configurações-> Unidades compartilhadas) ou desabilitar e, em seguida, reativar o compartilhamento da unidade e inserir a nova senha.

Seria útil se docker-compose fornecesse um erro nessas situações.

Nrjohnstone
fonte