Como obter bash ou ssh em um contêiner em execução no modo de plano de fundo?

933

Eu quero ssh ou bash em um contêiner de docker em execução. Por favor, veja o exemplo:

$ sudo docker run -d webserver
webserver is clean image from ubuntu:14.04
$ sudo docker ps
CONTAINER ID  IMAGE            COMMAND    CREATED STATUS  PORTS          NAMES
665b4a1e17b6  webserver:latest /bin/bash  ...     ...     22/tcp, 80/tcp loving_heisenberg 

agora eu quero obter algo assim (vá para o contêiner em execução):

$ sudo docker run -t -i webserver (or maybe 665b4a1e17b6 instead)
$ root@665b4a1e17b6:/# 
However when I run the line above I get new CONTAINER ID
$ root@42f1e37bd0e5:/#

Eu usei o Vagrant e gostaria de ter um comportamento semelhante ao vagrant ssh.

Timur Fayzrakhmanov
fonte
alternativamente, sudo docker exec -i -t 665b4a1e17b6 /bin/shpara ser capaz de instalar programas apt e pacotes
fonjeekay
1
Observe que usar o SSH para bater em contêiner em execução é uma prática ruim - veja a justificativa aqui . sudo docker exec -i -t container-name /bin/bashé um caminho a percorrer.
patryk.beza 22/03

Respostas:

1306

A resposta é o attachcomando do Docker . Portanto, para o meu exemplo acima, a solução será:

$ sudo docker attach 665b4a1e17b6 #by ID
or
$ sudo docker attach loving_heisenberg #by Name
$ root@665b4a1e17b6:/#

Para o Docker versão 1.3 ou posterior: Obrigado ao usuário WiR3D, que sugeriu outra maneira de obter o shell de um contêiner. Se usarmos attach, podemos usar apenas uma instância do shell. Portanto, se queremos abrir um novo terminal com uma nova instância do shell de um contêiner, precisamos apenas executar o seguinte:

$ sudo docker exec -i -t 665b4a1e17b6 /bin/bash #by ID

ou

$ sudo docker exec -i -t loving_heisenberg /bin/bash #by Name
$ root@665b4a1e17b6:/#
Timur Fayzrakhmanov
fonte
5
Como alternativa, executesudo docker attach loving_heisenberg
Thiago Perrotta
51
o comando attach não funciona para mim, faz com que a janela de encaixe congele .. alguma idéia de por que está acontecendo?
Mo J. Mughrabi
10
Um lembrete para os usuários do boot2docker: remove sudo :)
Henno
17
-i -té igual a-it
pasha.zhukov
47
Esta é uma resposta perigosa a ser selecionada e muito votada. docker attachA instalação em uma instância do MongoDB, por exemplo, matará a instância. Como explicado em mais detalhes nesta pergunta attach e execsão animais diferentes.
fwc 10/05/19
675

Do Docker 1.3 em diante:

docker exec -it <containerIdOrName> bash

Basicamente, se o recipiente Docker foi iniciado usando o /bin/bashcomando que você pode acessá-lo usando attach. Caso contrário, será necessário executar o comando para criar uma instância do Bash dentro do contêiner usando exec.

Também para sair do Bash sem deixá-lo em execução em um processo não autorizado:

exit

Sim, é simples assim.

WiR3D
fonte
Ainda não descobrimos como fazer o nano funcionar. Acha que pode envolver a janela de encaixe-ssh a partir phusion
WiR3D
Existe alguma maneira de definir o bash por padrão nas janelas de encaixe?
Ipeacocks
@ipeacocks sim, se o RUNcomando no dockerfile for /bin/bash. Mas depende do que você quer dizer. Se você deseja executar o recipiente e têm o bash disponível imediatamente naquele mesmo terminal, em seguida, correr com -itdeve fazê-lo
WiR3D
10
Usar o grupo de encaixe é uma prática recomendada. Qualquer usuário que esteja no grupo de janelas de encaixe é essencialmente usado com permissões de root, sem a necessidade de usar o sudo. projectatomic.io/blog/2015/08/…
Maiku Mori 7/16
1
Eu acho que não faz muita diferença, do ponto de vista da segurança do host, se você usa o sudovs dockergroup. De qualquer forma, existe uma falha de segurança incorporada à janela de encaixe que pode fornecer privilégios completos no sistema de arquivos host do convidado - independentemente de você usar o grupo de janela de encaixe ou sudopara iniciar o contêiner.
Nobar
123

Embora o autor da pergunta tenha dito especificamente que está interessado em um contêiner em execução, também vale a pena notar que, se o contêiner não estiver em execução, mas você deseja executá-lo para bisbilhotar, é possível executar:

docker run -i -t --entrypoint /bin/bash <imageID>

Adam Kalnas
fonte
10
Isso fornece um contêiner diferente, assim como a resposta do @ kraxor.
Blaisorblade
27

Tente o seguinte:

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

Fonte: https://docs.docker.com/articles/basics/#running-an-interactive-shell

kraxor
fonte
14
Não é adequado, porque eu recebo diferente ID CONTAINER ( root@42f1e37bd0e5:/#e não root@665b4a1e17b6:/#)
Timur Fayzrakhmanov
link está morto, você deve atualizar
Ahmet Karakaya 15/04
19

Com base na resposta de @ Timur, criei o seguinte script útil

Configuração

Coloque o docker-ssharquivo no seu $PATHcom o seguinte conteúdo

#!/bin/bash -xe

# docker container id or name might be given as a parameter
CONTAINER=$1

if [[ "$CONTAINER" == "" ]]; then
  # if no id given simply just connect to the first running container
  CONTAINER=$(docker ps | grep -Eo "^[0-9a-z]{8,}\b")
fi

# start an interactive bash inside the container
# note some containers don't have bash, then try: ash (alpine), or simply sh
# the -l at the end stands for login shell that reads profile files (read man)
docker exec -i -t $CONTAINER bash -l

Nota : Alguns contêineres não contêm bash, mas ash, shetc. Nestes casos, bashdevem ser substituídos no script acima.

Uso

Se você tiver apenas uma instância em execução, basta executar

$> docker-ssh 

Caso contrário, forneça a ele um parâmetro de ID do docker que você obtém docker ps(primeira coluna)

$> docker-ssh 50m3r4nd0m1d
Matyas
fonte
Posso saber por que precisamos de -l no final?
Nam G VU
para começar a festa como um shell de login, lendo os parâmetros de ambiente (descrito na linha acima do comando)
Matyas
13

Se o seu contêiner não tiver o bash instalado, você pode tentar sh:

docker exec -it CONTAINER /bin/sh

Ou procure conchas em / bin primeiro:

docker export CONTAINER|tar -t|egrep ^bin/
Laktak
fonte
O que é "cônsul" ? Você tem uma referência para isso? Você quer dizer "console" ?
Peter Mortensen
9

Eu criei um servidor SSH em contêiner que fornece recursos SSH para qualquer contêiner em execução. Você não precisa mudar seu contêiner. O único requisito é que o contêiner tenha uma festança.

Se você tiver um contêiner com o nome 'web-server1'. O seguinte comando docker run iniciaria um segundo contêiner que forneceria SSH para o primeiro contêiner.

docker run -ti --name sshd-web-server1 -e CONTAINER=web-server1 -p 2222:22 \
-v /var/run/docker.sock:/var/run/docker.sock -v $(which docker):/usr/bin/docker \
jeroenpeeters/docker-ssh

Para obter mais dicas, consulte https://github.com/jeroenpeeters/docker-ssh

Jeroen Peeters
fonte
Esta deve ser a resposta aceita ^
Nam G VU
A propósito, como podemos carregar o .bashrc automaticamente ao iniciar uma sessão ssh usando sua solução? Também postou um problema no github github.com/jeroenpeeters/docker-ssh/issues/30
Nam G VU
6

@jpetazzo tem uma publicação incrível sobre esse assunto . A resposta curta seria usar nsenter:

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

PS: Não se esqueça de conferir a discussão nos comentários do post ...

Felicidades

Richard
fonte
1
Esse é um post bastante antigo que não é mais realmente necessário . A docker execsolução do @ WiR3D é bastante mais conveniente.
drevicko
4

Você também pode fornecer ao contêiner do Docker um endereço IP roteável com o Pipework e, depois disso, colocar o SSH na máquina com esse novo endereço IP.

Este será mais "tradicional" (ssh), em vez de usar um comando específico do aplicativo como docker attach, e acabará por torná-lo mais 'portátil' em todos os sistemas e versões.

radriaanse
fonte
Por favor, adicione a maneira simples de como fazê-lo. Para ser sincero, eu realmente preciso, mas não tenho tempo para procurar a solução mais simples para isso. Você poderia postar sua resposta aqui? Seria ótimo ..
Timur Fayzrakhmanov 29/10
2
Existem duas maneiras de conseguir isso, mas não é simples e se tornaria um grande post. Você pode verificar esse link por conta própria, para usar a tubulação ou esse link , o que basicamente faz o mesmo que o Pipework e é um pouco mais simples, mas você precisa fazê-lo manualmente. Portanto, depende de quantos servidores você está falando. Se você não conseguir descobrir algo mais específico, me avise. Mas também não tenho tempo para escrever um tutorial completo.
radriaanse
Você está certo - não há uma maneira óbvia e simples de fazê-lo (obrigado pelos links, acho que o revisitarei mais tarde.
Timur Fayzrakhmanov
2
docker run -it openjdk:8

Isso funciona :-)

Kishan B
fonte
1

IR PARA DENTRO

instale a goinsideferramenta de linha de comando com:

sudo npm install -g goinside

e entre em um contêiner de encaixe com um tamanho de terminal adequado com:

goinside docker_container_name

para mais detalhes, verifique isso .

Soorena
fonte
0

Para bater em um contêiner em execução, digite o seguinte:

docker exec -t -i container_name /bin/bash
Agustí Sánchez
fonte
1
Porém, esta é a mesma resposta que @AdamKalnas
Bruni
0

Apenas para informação. Se você precisar fazer login em um contêiner simples que não seja um daemon, use os seguintes comandos:

docker start {id}
docker attach {id}
Nek
fonte
-1

se o contêiner for parado como, por exemplo, um contêiner somente de dados, uma boa solução é executar um contêiner descartável toda vez que você desejar anexar ao contêiner de dados. Nesse caso, o próprio contêiner de dados poderia estar completamente vazio, pois o contêiner temporário teria as ferramentas do SO.

$ docker run --rm --volumes-from mydata -it ubuntu bash
root@645045d3cc87:/# ls /mydata
root@645045d3cc87:/# touch /mydata/foo
root@645045d3cc87:/# exit
exit
David Dehghan
fonte