Como posso adicionar um volume a um contêiner do Docker existente?

297

Eu tenho um contêiner do Docker que eu criei simplesmente instalando o Docker no Ubuntu e fazendo:

sudo docker run -i -t ubuntu /bin/bash

Comecei imediatamente a instalar o Java e algumas outras ferramentas, passe algum tempo com ele e parei o contêiner

exit

Então, eu queria adicionar um volume e percebi que isso não é tão simples quanto eu pensava que seria. Se eu usar sudo docker -v /somedir run ..., acabarei com um novo contêiner novo, para que eu instale o Java e faça o que já fiz antes apenas para chegar a um contêiner com um volume montado.

Toda a documentação sobre a montagem de uma pasta no host parece implicar que a montagem de um volume é algo que pode ser feito ao criar um contêiner. Portanto, a única opção que tenho para evitar a reconfiguração de um novo contêiner do zero é confirmar o contêiner existente em um repositório e usá-lo como base de um novo enquanto monta o volume.

Essa é realmente a única maneira de adicionar um volume a um contêiner existente?

mahonya
fonte
1
Depois dos contêineres, eles se tornaram parte integrante dos programadores e, portanto, essas perguntas estão sendo postadas com mais frequência aqui. Perguntas postadas aqui usando dockertag são 34k + , que são muito mais do que os dois locais stackoverflow.com/questions/tagged/docker
MA Hossain Tonu

Respostas:

394

Você pode confirmar seu contêiner existente (ou seja, criar uma nova imagem a partir das alterações do contêiner) e executá-lo com suas novas montagens.

Exemplo:

$ docker ps  -a
CONTAINER ID        IMAGE                 COMMAND                  CREATED              STATUS                          PORTS               NAMES
    5a8f89adeead        ubuntu:14.04          "/bin/bash"              About a minute ago   Exited (0) About a minute ago                       agitated_newton

$ docker commit 5a8f89adeead newimagename

$ docker run -ti -v "$PWD/dir1":/dir1 -v "$PWD/dir2":/dir2 newimagename /bin/bash

Se estiver tudo bem, pare seu recipiente antigo e use este novo.

É isso aí :)

Leonardo Cuquejo
fonte
22
E se você precisar que o novo contêiner adote o nome antigo por algum motivo, use a renomeação do docker após remover o antigo.
Dirk
10
só queria salientar isso acima, onde você menciona newnameofcontainerque provavelmente deve ser nomeado new_image_name- porque docker commitcria uma nova imagem no seu sistema. Em seguida, quando você faz um, docker runvocê realmente usa o nome da imagem da qual deseja executar um novo contêiner. O exemplo acima funciona, mas você gostaria de esclarecer aos outros que o espaço reservado newnameofcontainer acima é realmente o nome de uma nova imagem. obrigado! resposta incrível. oh, você pode ver a imagem recém-criado a partir da primeira janela de encaixe comando commit utilizandodocker image ls
FireDragon
3
De fato, você não precisa confirmar um novo contêiner se desejar iniciar a partir de uma imagem. Apenas docker run -v /srv/a:/tmp ubuntu:14.04é bom.
YongHao Hu
Eu já tenho um contêiner em execução com todos os arquivos. se o método acima criar um novo contêiner, não será possível compilar tudo novamente. Existe uma maneira de evitar isso e montar sem precisar criar um novo container ou imagem?
Dhinar
Isso manterá os mapeamentos de volume antigos do contêiner antigo ou devo declará-los novamente com o novo contêiner?
thebeancounter 25/09/18
79

Não temos como adicionar volume no contêiner em execução, mas para atingir esse objetivo, você pode usar os comandos abaixo:

Copie arquivos / pastas entre um contêiner e o sistema de arquivos local: -

docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-

docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH

Para referência, consulte:

https://docs.docker.com/engine/reference/commandline/cp/

user128364
fonte
47
Há uma enorme diferença entre a montagem de um volume e copiar arquivos de e para um recipiente ...
Jules
31
Enfim, isso me ajudou. Eu não conhecia o comando 'docker cp' e estava tentando conseguir exatamente isso - copiar arquivos da execução do contêiner para o host.
Ivan
3
não é uma montagem, mas é útil trazer arquivos de volta entre o contêiner e o host local.
Linerr 26/04/19
Embora isso resolva o problema de replicar o conteúdo do contêiner localmente, isso não é equivalente a montar um volume e não deve ser pensado como uma alternativa. Ou seja, a replicação deve ser gerenciada pelo usuário e os dados existem agora em dois locais.
Sebastian Gaweda 26/07/19
1
Eu não entendo por que tantos votos positivos, esta é uma resposta muito errada para a pergunta.
João Matos
33

Montei com êxito a /home/<user-name>pasta do meu host na /mntpasta do contêiner existente (não em execução). Você pode fazer isso da seguinte maneira:

  1. Abra o arquivo de configuração correspondente ao contêiner parado, que pode ser encontrado em /var/lib/docker/containers/99d...1fb/config.v2.json(pode ser config.jsonpara versões mais antigas do docker).

  2. Encontrar MountPointsseção, que estava vazio no meu caso: "MountPoints":{}. Em seguida, substitua o conteúdo por algo assim (você pode copiar o conteúdo adequado de outro contêiner com as configurações adequadas):

"MountPoints":{"/mnt":{"Source":"/home/<user-name>","Destination":"/mnt","RW":true,"Name":"","Driver":"","Type":"bind","Propagation":"rprivate","Spec":{"Type":"bind","Source":"/home/<user-name>","Target":"/mnt"},"SkipMountpointCreation":false}}

ou o mesmo (formatado):

  "MountPoints": {
    "/mnt": {
      "Source": "/home/<user-name>",
      "Destination": "/mnt",
      "RW": true,
      "Name": "",
      "Driver": "",
      "Type": "bind",
      "Propagation": "rprivate",
      "Spec": {
        "Type": "bind",
        "Source": "/home/<user-name>",
        "Target": "/mnt"
      },
      "SkipMountpointCreation": false
    }
  }
  1. Reinicie o serviço da janela de encaixe: service docker restart

Isso funciona para mim com o Ubuntu 18.04.1 e o Docker 18.09.0

Igor Bendrup
fonte
3
Obrigado pela resposta. O passo 3 é crucial. Eu também acrescentaria que é melhor parar o contêiner do docker antes de fazer a gravação.
buzypi
7
Esta é a melhor resposta, pois preserva totalmente o contêiner existente. Foi o que fiz: 1. Pare o mecanismo do docker: systemctl stop docker.service2. Edite config.v2.json: vim <(jq . /var/lib/docker/containers/<container-ID>/config.v2.json)3. Salve as atualizações em um arquivo: :w config.v2.json4. Saia do vim: :q!5. Atualize o arquivo existente: jq -c . config.v2.json > /var/lib/docker/containers/<container-ID>/config.v2.json6. Inicie o mecanismo do docker: systemctl start docker.service7. Inicie o contêiner, se necessário : docker start <container-name/ID>8. Aproveite :-)
Android Control
2
Um passo fundamental é service docker restart. Eu tentei, docker restart <container>então a nova configuração não é escolhida e está sendo substituída pela antiga configuração.
KFL
1
Também jqajudará a imprimir bastante o JSON, por isso é mais humano editável:cat config.v2.json | jq . > config.json
KFL
14

Jérôme Petazzoni tem uma postagem de blog bastante interessante sobre como anexar um volume a um contêiner enquanto estiver em execução . Isso não é algo embutido no Docker, mas é possível.

Como ele também aponta

Isso não funcionará em sistemas de arquivos que não são baseados em dispositivos de bloco.

Ele só funcionará se / proc / mounts listar corretamente o nó do dispositivo de bloco (que, como vimos acima, não é necessariamente verdadeiro).

Além disso, eu só testei isso no meu ambiente local; Eu nem tentei em uma instância de nuvem ou algo assim

YMMV

R0MANARMY
fonte
8

Infelizmente, a opção de alternar para montar um volume é encontrada apenas no runcomando

docker run --help

-v, --volume list Bind mount a volume (default [])

Existe uma maneira de solucionar isso, para que você não precise reinstalar os aplicativos que você já configurou no seu contêiner.

  1. Exportar seu contêiner docker container export -o ./myimage.docker mycontainer
  2. Importar como imagem docker import ./myimage.docker myimage
  3. Então docker run -i -t -v /somedir --name mycontainer myimage /bin/bash
Adel Helal
fonte
1
FYI - docker containernão é um comando válido no 1.11.2 (que é a versão mais recente suportada pela Synology até o momento em que este documento foi escrito). Não consigo encontrar nenhum documento dizendo quando foi adicionado. Nesse caso, o primeiro comando é docker export -o ./myimage.docker mycontainer.
22817 Chris R. Donnelly
2

Uma observação sobre o uso de contêineres do Docker Windows depois que tive que procurar esse problema por um longo tempo!

Condições:

  • Windows 10
  • Docker Desktop (versão mais recente)
  • usando o Docker Windows Container para imagem microsoft / mssql-server-windows-developer

Problema:

  • Eu queria montar um dicionário de host no meu contêiner do Windows.

Solução parcialmente descrita aqui:

  • criar contêiner de janela de encaixe

docker run -d -p 1433:1433 -e sa_password=<STRONG_PASSWORD> -e ACCEPT_EULA=Y microsoft/mssql-server-windows-developer

  • vá para o shell de comando no contêiner

docker exec -it <CONTAINERID> cmd.exe

  • criar DIR

mkdir DirForMount

  • parar o recipiente

docker container stop <CONTAINERID>

  • confirmar o contêiner

docker commit <CONTAINERID> <NEWIMAGENAME>

  • excluir contêiner antigo

docker container rm <CONTAINERID>

  • crie um novo contêiner com nova imagem e montagem de volume

docker run -d -p 1433:1433 -e sa_password=<STRONG_PASSWORD> -e ACCEPT_EULA=Y -v C:\DirToMount:C:\DirForMount <NEWIMAGENAME>

Depois disso, resolvi esse problema nos contêineres do Windows docker.

droebi
fonte
-3

A melhor maneira é copiar todos os arquivos e pastas dentro de um diretório em seu sistema de arquivos local: docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH

SRC_PATHestá no contêiner DEST_PATHestá no host local

Em seguida, docker-compose downanexe um volume ao mesmo DEST_PATHe execute os contêineres do Docker usandodocker-compose up -d

Adicione volume seguindo em docker-compose.yml

volumes:
 - DEST_PATH:SRC_PATH
Vatsal Mishra
fonte
Existem outras opções melhores acima.
MRR
De fato, existem opções melhores acima e a cópia de arquivos não os está montando. Além disso, a definição de "volumes" fornecida para a opção docker-compose é o contrário: volumes: - HOST_PATH: CONTAINER_PATH
Guillaume S.