Como iniciar um contêiner do Docker parado com um comando diferente?

251

Gostaria de iniciar um contêiner do Docker parado com um comando diferente, pois o comando padrão falha - o que significa que não posso iniciar o contêiner e depois usar 'docker exec'.

Basicamente, gostaria de iniciar um shell para poder inspecionar o conteúdo do contêiner.

Felizmente, criei o contêiner com a opção -it!

aaa90210
fonte

Respostas:

380

Encontre seu ID de contêiner parado

docker ps -a

Confirme o contêiner parado:

Este comando salva o estado do contêiner modificado em uma nova imagem user/test_image

docker commit $CONTAINER_ID user/test_image

Iniciar / executar com um ponto de entrada diferente:

docker run -ti --entrypoint=sh user/test_image

Descrição do argumento do ponto de entrada: https://docs.docker.com/engine/reference/run/#/entrypoint-default-command-to-execute-at-runtime

Nota:

As etapas acima apenas iniciam um contêiner parado com o mesmo estado do sistema de arquivos. Isso é ótimo para uma investigação rápida. Mas variáveis ​​de ambiente, configuração de rede, volumes conectados e outras equipes não são herdadas, você deve especificar todos esses argumentos explicitamente.

As etapas para iniciar um contêiner parado foram emprestadas a partir daqui: (último comentário) https://github.com/docker/docker/issues/18078

Dmitriusan
fonte
1
não, as imagens são somente leitura. Ele salva modificado estado recipiente em um novo test_image imagem
Dmitriusan
4
este perde quase toda a configuração sobre env, volumes, UID, ... Tudo o que tem em comum com o recipiente parado é o sistema de arquivos (que é talvez o suficiente para alguns)
Florian Klein
4
Seria ótimo se eu pudesse, de alguma forma, obter o mesmo ambiente, configuração de rede, volumes anexados. É possível converter a inspectsaída em uma configuração usada na execução subsequente?
Otheus
2
@ Webman, sim, mas isso não é verdade para os volumes montados antes de parar um contêiner. Você terá de anexar os mesmos volumes explicitamente quando você iniciar o recipiente próxima vez
Dmitriusan
1
@ EmreTapcı, acho que fazer isso é contra a ideologia do Docker. Os contêineres devem ser uma entidade de uso e descarte de uso único, em contraste com as máquinas virtuais. Você pode tentar seguir a resposta aaa90210 , mas seria um hack.
Dmitriusan
126

Edite este arquivo (correspondente ao seu contêiner parado):

vi /var/lib/docker/containers/923...4f6/config.json

Mude o parâmetro "Path" para apontar para o seu novo comando, por exemplo, / bin / bash. Você também pode definir o parâmetro "Args" para passar argumentos para o comando.

Reinicie o serviço docker (observe que isso interromperá todos os contêineres em execução):

service docker restart

Liste seus contêineres e verifique se o comando foi alterado:

docker ps -a

Inicie o contêiner e prenda-o, agora você deve estar em sua concha!

docker start -ai mad_brattain

Trabalhou no Fedora 22 usando o Docker 1.7.1.

NOTA: Se o seu shell não for interativo (por exemplo, você não criou o contêiner original com a opção -it), você pode alterar o comando para "/ bin / sleep 600" ou "/ bin / tail -f / dev / null" para lhe dar tempo suficiente para executar o "docker exec -it CONTID / bin / bash" como outra maneira de obter um shell.

NOTA2: As versões mais recentes do docker têm o config.v2.json, onde você precisará alterar o Ponto de entrada ou o Cmd (obrigado user60561).

aaa90210
fonte
44
meus olhos. meus olhos. Espero que este seja um pedido de recurso em algum lugar para lidar com isso corretamente no Docker.
gertvdijk
2
@AlexeyStrakh, você pode tentar executar "/ usr / bin / sleep 600" e depois executar "docker exec -it / bin / bash" para obter um shell. Embora eu não tenha certeza de como colocar parâmetros nessa variável Path. Caso contrário, tente encontrar outro comando que permanecerá vivo por tempo suficiente para você executar um executivo ou ver a resposta de Dmitriusan.
aaa90210
3
essa é a resposta só é realmente preciso para a questão: todas as outras proposições executar um "quase o mesmo" container, mas esquecem-se os volumes, env, UIDs, ...
Florian Klein
3
No meu caso, / usr / bin / sleep não estava disponível. Eu tive sucesso com..."Path":"tail","Args":["-f","/dev/null"]...
nevrome
4
Versões mais recentes do docker possuem config.v2.json, onde você precisará alterar um Entrypointou outro Cmd.
user60561
20

Adicione uma verificação ao topo do seu script do Ponto de Entrada

O Docker realmente precisa implementar isso como um novo recurso, mas aqui está outra opção de solução alternativa para situações nas quais você tem um Ponto de Entrada que termina após sucesso ou falha, o que pode dificultar a depuração.

Se você ainda não possui um script de Ponto de Entrada, crie um que execute os comandos necessários para o seu contêiner. Em seguida, na parte superior deste arquivo, adicione estas linhas a entrypoint.sh:

# Run once, hold otherwise
if [ -f "already_ran" ]; then
    echo "Already ran the Entrypoint once. Holding indefinitely for debugging."
    cat
fi
touch already_ran

# Do your main things down here

Para garantir que cata conexão seja mantida, você pode precisar fornecer um TTY. Estou executando o contêiner com meu script Entrypoint da seguinte forma:

docker run -t --entrypoint entrypoint.sh image_name

Isso fará com que o script seja executado uma vez, criando um arquivo que indica que ele já foi executado (no sistema de arquivos virtual do contêiner). Você pode reiniciar o contêiner para executar a depuração:

docker start container_name

Quando você reinicia o contêiner, o already_ranarquivo será encontrado, fazendo com que o script do Ponto de Entrada seja interrompido cat(o que apenas espera eternamente pela entrada que nunca chegará, mas mantém o contêiner ativo). Você pode executar uma bashsessão de depuração :

docker exec -i container_name bash

Enquanto o contêiner estiver em execução, você também poderá remover already_rane executar manualmente o entrypoint.shscript para executá -lo novamente, se precisar depurar dessa maneira.

Ethan T
fonte
3
Além disso, você pode executar o ponto de entrada em /bin/shvez de cat- então você sempre pode entrar apenas reiniciando. Sua solução é demais!
Danny Dulai
4

Meu problema:

  • Comecei um contêiner com docker run <IMAGE_NAME>
  • E, em seguida, adicionamos alguns arquivos a este contêiner
  • Depois fechei o contêiner e tentei iniciá-lo novamente com o mesmo comando acima.
  • Mas quando eu verifiquei os novos arquivos, eles estavam faltando
  • quando corro docker ps -a, pude ver dois contêineres.
  • Isso significa que toda vez que eu estava executando o docker run <IMAGE_NAME>comando, uma nova imagem era criada

Solução: Para trabalhar no mesmo contêiner criado em primeiro lugar, execute estas etapas

  • docker ps para obter contêiner do seu contêiner
  • docker container start <CONTAINER_ID> para iniciar o contêiner existente
  • Então você pode continuar de onde você saiu. por exemplodocker exec -it <CONTAINER_ID> /bin/bash
  • Você pode então criar uma nova imagem a partir dela.
Amit Dudhbade
fonte
Isso não responde à pergunta. O OP quer saber como reiniciar o recipiente, mas com argumentos diferentes do que aqueles usados emdocker run <containerID>
CodeBlooded
2

Peguei a resposta de @ Dmitriusan e criei um pseudônimo:

alias docker-run-prev-container = 'prev_container_id = "$ (docker ps-aq | head -n1)" && docker commit "$ prev_container_id" "prev_container / $ prev_container_id" && docker run -it --entrypoint = bash "prev_container / $ prev_container_id "'

Adicione isso ao seu ~/.bashrcarquivo de alias e você terá um novo docker-run-prev-containeralias bacana que o colocará em um shell no contêiner anterior.

Útil para depuração docker builds com falha .

Dean Rather
fonte
2

Não é exatamente isso que você está pedindo, mas você pode usar docker exportem um contêiner parado se tudo o que você deseja é inspecionar os arquivos.

mkdir $TARGET_DIR
docker export $CONTAINER_ID | tar -x -C $TARGET_DIR
Lars Christian Jensen
fonte
1

Não foi especificado se o contêiner está saindo, apenas que seu código falha e você precisa ver o que está acontecendo no contêiner. Se não estiver saindo, aqui está outra solução em potencial.

Obtenha o ID do contêiner com docker ps

docker exec -it 665b4a1e17b6 /bin/sh

Se o ponto de entrada estiver definido como algo problemático, ele também poderá ser substituído, conforme sugerido na resposta de Dmitriusan. Também deve ser observado que você pode anexar a qualquer contêiner em execução docker attach. Tantas soluções soluções diferentes. Só não vejo a necessidade de me comprometer com a imagem. Parece desnecessário.

Documentos para o executivo do Docker - https://docs.docker.com/engine/reference/commandline/exec/

Anexo do Docs for Docker - https://docs.docker.com/engine/reference/commandline/attach/

deadbabykitten
fonte
-12

Na verdade, eu discordo de ambas as respostas. Se você quiser apenas ver o que há no contêiner, execute este comando para obter um shell. Não há necessidade de alterar o ponto de entrada em nenhuma ou em nenhuma das configurações.

docker run -it <image_name> bash
deadbabykitten
fonte
12
Isso não funciona, pois a operação está perguntando sobre um contêiner, não uma imagem.
Peter Vrabel
Suponho que você esteja certo, mas não vejo uma razão para fazer isso. Você pode canalizar logs para o stdout e docker logs <container_id> --followfornecerá o que você precisa. Outra alternativa é usar o comando acima e iniciar o serviço de falha nessa imagem com o mesmo comando no dockerfile e depurar a partir daí.
deadbabykitten
4
O comando run cria um novo contêiner a partir de uma imagem. Não inicia um contêiner parado.
Waleed Abdulla
2
Ummm ... não é o objetivo do docker que todas as imagens possam ser exibidas exatamente da mesma maneira? Isso nega seu argumento. Ele não precisa iniciar um contêiner parado. Qualquer contêiner é exatamente o mesmo, portanto não importa qual ele inicia ou para. Ele está apenas tentando inspecionar o conteúdo. A maneira mais fácil de fazer isso é bash e executar o comando ou canalizar a saída do comando para os logs. Vocês, às vezes, apresentam as soluções mais complexas para problemas simples.
deadbabykitten
-12
docker container start <CONTAINER_ID>
Oscar Calderón
fonte