Como editar arquivos em um contêiner docker interrompido / não iniciado

93

Tentando corrigir erros e depurar problemas com meu aplicativo dividido em vários contêineres, frequentemente edito arquivos em contêineres:

  • ou sou totalmente preguiçoso e instalo o nano e edito diretamente no container ou

  • Eu encaixo e retiro o arquivo do contêiner, edito, copio de volta e reinicio o contêiner

Essas são etapas intermediárias antes de chegar a um novo conteúdo para a construção de contêiner, o que leva muito mais tempo do que fazer o acima (o que, obviamente, é apenas intermediário / fiddling).

Agora, frequentemente, interrompo o programa inicial do contêiner, que nos casos de quebra é um script de nó ou um script de servidor da web python, ambos normalmente falham devido a erros de sintaxe.

Existe alguma maneira de salvar esses contêineres? Como eles não iniciam, não posso encaixar o exec neles e, portanto, eles estão perdidos para mim. Em seguida, sigo a rota rm / rmi / build / run depois de corrigir o arquivo incorreto na entrada de compilação.

Como posso editar arquivos em um contêiner interrompido, copiá-los ou iniciar um shell em um contêiner interrompido - qualquer coisa que me permita consertar esse contêiner?

(Parece um pouco como trabalhar em um computador remoto e interromper a configuração de rede - a conexão é perdida "para sempre" dessa forma e é necessário usar um fallback, se houver.)

Como editar arquivos de contêiner Docker do host? parece relevante, mas está desatualizado.

Andreas Reiff
fonte
Este também pode ser uma solução alternativa stackoverflow.com/a/32353134/586754 - esperando por uma solução ainda melhor.
Andreas Reiff
1
talvez você deva considerar montar um volume para que possa editar arquivos em seu host em vez de dentro do contêiner. Quando estiver satisfeito com seu código, você estará livre para colocar docker cpos arquivos no contêiner (ou criar uma nova imagem)
Thomasleveil
Sim, seria um pouco tarde se eu não tivesse configurado as coisas assim desde o início. Isso não funciona para recuperação, eu acho.
Andreas Reiff
Muitos leitores desejam apenas visualizar os arquivos em vez de editá-los. Nestes casos, você pode usar o docker commitcomando para quebrar uma nova imagem. name=$(docker commit); docker run -it $name /bin/shvai fazer o que você quiser.
Att Righ
então parece que os sistemas de arquivos de contêineres parados são relativamente permanentes no final?
Webwoman

Respostas:

138

Tive um problema com um contêiner que não inicializava devido a uma alteração incorreta na configuração. Consegui copiar o arquivo do contêiner interrompido e editá-lo. algo como:

docker cp docker_web_1:/etc/apache2/sites-enabled/apache2.conf .

(corrija o arquivo)

docker cp apache.conf docker_web_1:/etc/apache2/sites-enabled/apache2.conf
tomurie
fonte
22
Esta deve ser a resposta aceita. Por alguma razão, não achei que o CP funcionasse em contêineres parados. Agradável!
Proximo
Perfeito. Copiei um arquivo do contêiner (sabia seu caminho), editei-o e copiei de volta para o contêiner no mesmo local. Funcionou para mim! Obrigado!
Nawaz
Existe uma maneira de remover um arquivo?
kodlan
1
@kodlan Somente se ele aparecer apenas em UpperDirvocê obter de docker container inspect- você terá que experimentar para ver como o sistema de sobreposição representa os arquivos na estrutura subjacente que foram excluídos na camada superior.
Tim Baverstock
Obrigado, isso me ajudou a consertar meu contêiner MySQL em execução no docker no macOS.
mazedlx
60

Respondendo minha própria pergunta .. ainda esperando por uma resposta melhor de uma pessoa mais qualificada !!

Existem 2 possibilidades.

1) Editando o sistema de arquivos diretamente no host . Isso é um tanto perigoso e pode quebrar completamente o contêiner, possivelmente outros dados, dependendo do que estiver errado.

2) Alterar o script de inicialização para algo que nunca falha como iniciar um bash, fazer as correções / edições e, em seguida, alterar o programa de inicialização novamente para o desejado (como um nó ou o que quer que fosse antes).

Mais detalhes:

1) Usando

docker ps

para encontrar os contêineres em execução ou

docker ps -a

para encontrar todos os contêineres (incluindo aqueles parados) e

docker inspect (containername)

procure o "Id", um dos primeiros valores.

Esta é a parte que contém detalhes de implementação e pode mudar, esteja ciente de que você pode perder seu contêiner dessa forma.

Vamos para

/var/lib/docker/aufs/diff/9bc343a9..(long container id)/

e lá você encontrará todos os arquivos que foram alterados em relação à imagem na qual o contêiner se baseia. Você pode substituir arquivos, adicionar ou editar arquivos.

Novamente, eu não recomendaria isso.

2) Conforme descrito em https://stackoverflow.com/a/32353134/586754, você pode encontrar a configuração json config.json em um caminho como

/var/lib/docker/containers/9bc343a99..(long container id)/config.json

Lá você pode alterar os argumentos de, por exemplo, "nodejs app.js" para "/ bin / bash". Agora reinicie o serviço docker e inicie o contêiner (você verá que agora ele inicializa corretamente). Você deveria usar

docker start -i (containername)

para ter certeza de que não pare imediatamente. Agora você pode trabalhar com o contêiner e / ou posteriormente anexar com

docker exec -ti (containername) /bin/bash

Além disso, docker cp é bastante útil para copiar arquivos que foram editados fora do contêiner.

Além disso, só se deve voltar a essas medidas se o contêiner estiver mais ou menos "perdido" de qualquer maneira, então qualquer mudança seria uma melhoria.

Andreas Reiff
fonte
Ainda esperando uma resposta melhor - sinta-se à vontade para dar uma, vou mover a tag "ansered" também.
Andreas Reiff
Usei a segunda maneira e tive que reiniciar o serviço docker para forçar a substituição dos config.jsonarquivos sempre que os editei
Vitaly Isaev
2
Eu tenho config.v2.json e toda vez que eu inicio o contêiner zumbi, ele reverte minha atualização de Path / EntryPoint e morre mais uma vez. O uso de "docker cp" para atualizar o script entrypoint.sh para apenas executar o bash corrigiu o problema.
Curtis Yallop
@CurtisYallop Estou passando pela mesma coisa. Como você resolveu isso?
Brett McLain
1
@BrettMcLain Eu usei docker cp em vez de editá-lo no host. Assim: Encontre o local do script do ponto de entrada: "docker inspect container_name | grep Entry". Obtenha o script: "docker cp container_name: /entrypoint.sh ./". (Edite-o) Coloque o script de volta no contêiner: "docker cp entrypoint.sh container_name: /entrypoint.sh". Você pode fazer o ponto de entrada executar bash ou executar um loop de sono, por exemplo, "while:; do sleep 10; done". A primeira linha do script deve ser "#! / Bin / bash".
Curtis Yallop
9

Você pode editar o sistema de arquivos do container diretamente, mas não sei se é uma boa ideia. Primeiro você precisa encontrar o caminho do diretório que é usado como raiz do tempo de execução para o contêiner. Corra docker container inspect id/name. Procure a chave UpperDirna saída JSON.

Esse é o seu diretório.

Tejas Sarade
fonte
Encontrou o diretório, mas ele não continha todos os arquivos.
aioobe
É OverlayFS, portanto, seus arquivos devem estar em um desses diretórios.
Tejas Sarade
O nome do diretório pode ser diferente de "UpperDir", por exemplo, no meu caso é Source. Mas funcionou!
Rajni Kewlani
0

Se você está tentando reiniciar um contêiner interrompido e precisa alterar o contêiner devido à configuração incorreta, mas o contêiner não está iniciando, você pode fazer o seguinte, o que funciona usando o comando "docker cp" (semelhante à sugestão anterior). Este procedimento permite remover arquivos e fazer quaisquer outras alterações necessárias. Com sorte, você pode pular muitas das etapas abaixo.

  1. Use docker inspect para encontrar o ponto de entrada, (denominado Path em algumas versões)
  2. Crie um clone do usando docker run
  3. Digite clone usando docker exec -ti bash (se * nix container)
  4. Localize a localização do arquivo de ponto de entrada olhando através do clone para encontrar
  5. Copie o script do entrypoint antigo usando docker cp: ./
  6. Modifique ou crie um novo script de ponto de entrada, por exemplo

    #!/bin/bash tail -f /etc/hosts

  7. garantir que o script tenha direitos de execução
  8. Substitua o ponto de entrada antigo usando docker cp ./:
  9. inicie o contêiner antigo usando start
  10. refaça as etapas 6 a 9 até o início
  11. Corrigir problemas no contêiner
  12. Restaure o ponto de entrada se necessário e refaça as etapas 6 a 9 conforme necessário
  13. Remova o clone se necessário
user6830669
fonte