É possível iniciar uma sessão de shell em um contêiner em execução (sem ssh)

341

Eu esperava ingenuamente que este comando executasse um shell bash em um contêiner em execução:

docker run "id of running container" /bin/bash

parece que não é possível, recebo o erro:

2013/07/27 20:00:24 Internal server error: 404 trying to fetch remote history for 27d757283842

Portanto, se eu quiser executar o bash shell em um contêiner em execução (por exemplo, para fins de diagnóstico)

eu tenho que rodar um servidor SSH nele e loggin via ssh?

Max L.
fonte
11
docker run CONTAINERestá planejado em 1.0
kolypto 27/05
7
Desde o docker 1.3, você realmente deve fazer como descrito nesta resposta
Thomasleveil 22/10
11
apenasdocker attach container_name
maxbellec
11
Parece que a segunda resposta é muito melhor hoje em dia do que a aceita - você poderia reconsiderar alterar a resposta aceita?
Jsbueno

Respostas:

285

EDIT: agora você pode usar docker exec -it "id of running container" bash( doc )

Anteriormente, a resposta a esta pergunta era:

Se você realmente precisa e está em um ambiente de depuração, pode fazer o seguinte: sudo lxc-attach -n <ID> Observe que o ID precisa ser completo ( docker ps -notrunc).

No entanto, eu recomendo fortemente contra isso.

aviso: -notruncestá descontinuado, será substituído por em --no-truncbreve.

creack
fonte
11
por que você recomenda contra isso?
Max L.
7
Eu recomendo isso porque 1) requer um kernel muito recente; 2) você está fazendo coisas fora do docker para não poder rastreá-lo (logs, anexar etc.). Além disso, o docker pode usar o lxc agora, mas não há garantia de que o fará para sempre.
creack 30/07/2013
11
Tente atualizar para 0.7.6. O Docker ainda está usando o lxc no momento e lxc-attachdeve funcionar bem. Acabei de dobrar o cheque e funciona para mim. (Observe que ele não funcionará com o kernel anterior ao 3.8).
creack
2
a partir do docker 0.9 não é mais executado com o LXC por padrão. Você teria que iniciar o deamon janela de encaixe comdocker -d -e lxc
kevzettler
2
Max L., seu caso de uso pode ser resolvido com volumes de dados . Exemplo não ensaiado: 1) do recipiente ser executado com registos nginx em volume de dados: docker run -v /var/log/nginx -name somename imagename command; 2) executar um outro recipiente para visualizar o conteúdo do volume de dados: docker run -volumes-from somename -i -t busybox /bin/sh.
Ciastek
615

Com a janela de encaixe 1.3, há um novo comando docker exec. Isso permite que você insira uma janela de encaixe em execução:

docker exec -it "id of running container" bash
Michael_Scharf
fonte
2
Isso funcionou muito bem para mim. Além muito útil para executar docker.
Oraserrata 03/12/2018
E se eu fizesse alterações enquanto executava um contêiner em execução e quisesse refletir as alterações online? quais são as melhores práticas?
MediaRoot
Muito útil. Obrigado você
luongnv89
usar docker pspara obter id de instâncias em execução
múon
Nota: O contêiner pode não ter bash (»exec:" bash ": arquivo executável não encontrado«). Use docker inspect <image>para ver qual shell está disponível. Por exemplo, corra docker exec -it <container id> /bin/sh.
pixelbrackets
14

Apenas faça

docker attach container_name

Conforme mencionado nos comentários, para desconectar do contêiner sem pará-lo, digite Ctrlpentão Ctrlq.

maxbellec
fonte
5
Obrigado!! Ajudou. E no contexto da pergunta real, eu gostaria de acrescentar algo. Após depurar nosso contêiner usando, docker attach container_nameuse ctrl pe em ctrl qvez de exit. exitcomando pára o recipiente, onde, como ctrlpe ctrl qapenas destaca que recipiente e mantém funcionando
Phoenix
10

Como as coisas estão mudando, no momento está sendo usada a maneira recomendada de acessar um contêiner em execução nsenter.

Você pode encontrar mais informações neste repositório do github . Mas, em geral, você pode usar o nsenter assim:

PID=$(docker inspect --format {{.State.Pid}} <container_name_or_ID>)
nsenter --target $PID --mount --uts --ipc --net --pid

ou você pode usar o wrapper docker-enter:

docker-enter <container_name_or_ID>

Uma boa explicação sobre o assunto pode ser encontrada na entrada do blog de Jérôme Petazzoni: Por que você não precisa executar o sshd nos contêineres do docker

Teudimundo
fonte
infelizmente, as variáveis ​​env são desarrumadas usando essa abordagem (se você quiser verificar as variáveis ​​criadas por link). Eu sugiro fazer source /proc/*/environ.
Tomas Tomecek 15/10
8

Primeira coisa que você não pode executar

docker run "existing container" command

Como esse comando espera uma imagem e não um contêiner e, de qualquer maneira, resultaria em um novo contêiner (o que você queria ver)

Concordo com o fato de que, com o docker, devemos nos esforçar para pensar de uma maneira diferente (para que você encontre maneiras de não precisar fazer logon no contêiner), mas ainda acho útil e é assim que trabalho em torno dele.

Eu executo meus comandos através do supervisor no modo DEAMON.

Em seguida, executo o que chamo de docker_loop.sh conteúdo:

#!/bin/bash
/usr/bin/supervisord
/usr/bin/supervisorctl
while ( true )
    do
    echo "Detach with Ctrl-p Ctrl-q. Dropping to shell"
    sleep 1
    /bin/bash
done

O que ele faz é que ele permite que você "se conecte" ao contêiner e seja apresentado à supervisorctlinterface para parar / iniciar / reiniciar e verificar os logs. Se isso não for suficiente, você pode Ctrl+De vai cair em um shell que permitirá que você dê uma olhada como se fosse um sistema normal.

POR FAVOR, TENHA EM CONTA TAMBÉM que este sistema não é tão seguro quanto ter o contêiner sem casca, portanto, tome todas as medidas necessárias para proteger seu contêiner.

Alessandro
fonte
5

Fique de olho nesta solicitação de recebimento : https://github.com/docker/docker/pull/7409

O que implementa o próximo docker exec <container_id> <command>utilitário. Quando disponível, deve ser possível, por exemplo, iniciar e parar o serviço ssh dentro de um contêiner em execução.

Também é nsinitnecessário fazer o seguinte: "O nsinit fornece uma maneira útil de acessar um shell dentro do namespace de um contêiner em execução" , mas parece difícil continuar executando. https://gist.github.com/ubergarm/ed42ebbea293350c30a6

foz
fonte
docker execdesembarcou em Docker 1.3, por isso agora é possível criar e participar de uma nova sessão de shell em um recipiente correndo
foz
3

Você pode usar

docker exec -it <container_name> bash
antikytheraton
fonte
1

Na verdade, existe uma maneira de ter um shell no contêiner.

Suponha que você /root/run.shinicie o processo, o gerente de processos (supervisor) ou o que for.

Crie /root/runme.shcom alguns truques da tela gnu:

# Spawn a screen with two tabs
screen -AdmS 'main' /root/run.sh
screen -S 'main' -X screen bash -l
screen -r 'main'

Agora, você tem seus daemons na guia 0 e um shell interativo na guia 1. docker attacha qualquer momento para ver o que está acontecendo dentro do contêiner.

Outro conselho é criar uma imagem de "pacote de desenvolvimento" em cima da imagem de produção com todas as ferramentas necessárias, incluindo este truque de tela.

Kolypto
fonte
1

aqui está a minha solução

parte do DOckerfile:

...
RUN mkdir -p /opt
ADD initd.sh /opt/
RUN chmod +x /opt/initd.sh
ENTRYPOINT ["/opt/initd.sh"]

parte de "initd.sh"

#!/bin/bash
...
/etc/init.d/gearman-job-server start
/etc/init.d/supervisor start
#very important!!!
/bin/bash

depois que a imagem é criada, você tem duas opções usando exec e anexar:

  1. com exec (que eu uso), execute:

docker run --name $ CONTAINER_NAME -dt $ IMAGE_NAME

então

docker exec -it $ CONTAINER_NAME / bin / bash

E use

CTRL + D para desanexar

  1. com anexar, execute:

docker run --name $ CONTAINER_NAME -ditar $ IMAGE_NAME

então

docker anexar $ CONTAINER_NAME

E use

CTRL + P e CTRL + Q para desanexar

diferença entre as opções está no parâmetro -i

tim
fonte
1

Existem duas maneiras.

Com anexo

$ sudo docker attach 665b4a1e17b6 #by ID

Com exec

$ sudo docker exec - -t 665b4a1e17b6 #by ID
gurubelli
fonte
0

É útil atribuir um nome ao executar o contêiner. Você não precisa consultar container_id.

docker run --name container_name yourimage docker exec -it container_name bash

Matsumoto Kazuya
fonte
0

primeiro, obtenha o ID do contêiner desejado,

docker ps

você obterá algo como isto:

CONTAINER ID        IMAGE                  COMMAND             CREATED             STATUS                          PORTS                    NAMES
3ac548b6b315        frontend_react-web     "npm run start"     48 seconds ago      Up 47 seconds                   0.0.0.0:3000->3000/tcp   frontend_react-web_1

agora copie esse ID de contêiner e execute o seguinte comando:

docker exec -it container_id sh

docker exec -it 3ac548b6b315 sh

Umesh
fonte
-2

Talvez você tenha se enganado, como eu, pensando em termos de VMs ao desenvolver contêineres. Meu conselho: tente não.

Os contêineres são como qualquer outro processo. De fato, você pode querer "anexar" a eles para fins de depuração (pense em / proc // env ou strace -p), mas esse é um caso muito especial.

Normalmente, você apenas "executa" o processo; portanto, se você deseja modificar a configuração ou ler os logs, crie um novo contêiner e certifique-se de gravar os logs fora dele compartilhando diretórios, gravando no stdout (para que os logs do estivador funcionem) ou algo assim.

Para fins de depuração, você pode querer iniciar um shell, depois seu código, e pressionar CTRL-p + CTRL-q para deixar o shell intacto. Dessa forma, você pode reconectar usando:

docker attach <container_id>

Se você deseja depurar o contêiner porque está fazendo algo que não esperava, tente depurá-lo: /server/596994/how-can-i-debug-a-docker-container -inicialização

estani
fonte
Isso está completamente errado. Ser capaz de inspecionar o namespace LXC no qual seu aplicativo está executando não é um "caso muito especial", é uma atividade comum / diária para qualquer desenvolvedor.
precisa saber é
@sleepycal "qualquer desenvolvedor" parece um pouco tendencioso. Em qualquer caso, eu uso a introspecção de processos para que o mesmo se aplique aos contêineres. Essa é a ideia por trás da depuração. Você anexa um depurador ao processo (que pode ter um CLI). Pensar que você "está" logado no contêiner ainda me parece enganador.
estani 6/08/14
-4

Não. Isso não é possível. Use algo como supervisordpara obter um servidor ssh, se necessário. Embora eu definitivamente questione a necessidade.

Nick Stinemates
fonte