Como executo um comando em um contêiner do Docker já existente?

493

Criei um contêiner -dpara que não seja interativo.

docker run -d shykes/pybuilder bin/bash

Vejo que o contêiner saiu:

CONTAINER ID        IMAGE                     COMMAND             CREATED             STATUS                      PORTS               NAMES
d6c45e8cc5f0        shykes/pybuilder:latest   "bin/bash"          41 minutes ago      Exited (0) 2 seconds ago                        clever_bardeen

Agora eu gostaria de executar comandos ocasionais na máquina e sair. Apenas para obter a resposta.

Eu tentei ligar a máquina. Eu tentei anexar. Eu pensei que poderia ligar runcom um contêiner, mas isso não parece ser permitido. Usar startapenas parece funcionar e depois existe rapidamente.

Gostaria de voltar ao modo interativo depois de sair.

Eu tentei:

docker attach d6c45e8cc5f0

Mas eu entendo:

2014/10/01 22:33:34 You cannot attach to a stopped container, start it first

Mas se eu iniciar, ele sai de qualquer maneira. Catch 22. Eu não posso ganhar.

Johnston
fonte
como você sabia que o contêiner do docker havia saído? que comando você executou?
Thufir #
docker container ls -a
Brandon Manchester
Se você só precisa do sistema de arquivos: Como iniciar um contêiner do Docker parado com um comando diferente? (Note-se que as variáveis de ambiente e outras coisas na memória já são perdidos quando o recipiente parado.)
Franklin Yu

Respostas:

548

Em outubro de 2014, a equipedocker exec do Docker introduziu o comando : https://docs.docker.com/engine/reference/commandline/exec/

Portanto, agora você pode executar qualquer comando em um contêiner em execução apenas sabendo seu ID (ou nome):

docker exec -it <container_id_or_name> echo "Hello from container!"

Observe que o execcomando funciona apenas no contêiner já em execução. Se o contêiner estiver parado no momento, você deve primeiro executá-lo com o seguinte comando:

docker run -it -d shykes/pybuilder /bin/bash

A coisa mais importante aqui é a -dopção, que significa detached. Isso significa que o comando que você forneceu inicialmente ao contêiner ( /bin/bash) será executado em segundo plano e o contêiner não será interrompido imediatamente .

Scadge
fonte
120
Isso não funciona em um contêiner parado, apenas em um contêiner em execução. Portanto, se você tiver um contêiner que se interrompe imediatamente, como na pergunta, isso não funcionará realmente para executar outra coisa dentro dele.
interfect
4
O @interfect está certo e o CDR LDN tem uma resposta mais abrangente.
Dr. Jan-Philip Gehrcke
6
@ Jan-PhilipGehrcke Btw nome de usuário dessa pessoa mudou de CDR LDNpara cdreva resposta abaixo ( stackoverflow.com/a/26181666/149428 ).
Taylor Edmiston
3
Por que passar -it?
Iulian Onofrei
4
omg, por que isso é tão complicado? Parece a coisa mais básica que você precisa fazer. Não devemos usá-lo da maneira que eles pretendem.
sudo
287

Seu contêiner será fechado quando o comando que você deu terminar. Use as seguintes opções para mantê-lo ativo:

  • -i Mantenha o STDIN aberto, mesmo que não esteja conectado.
  • -t Aloque um pseudo-TTY.

Portanto, seu novo runcomando é:

docker run -it -d shykes/pybuilder bin/bash

Se você deseja anexar a um contêiner já em execução:

docker exec -it CONTAINER_ID /bin/bash

Nestes exemplos /bin/bashé usado como o comando.

cdrev
fonte
2
docker exec -it CONTAINER_ID /bin/bash -c "export VAR=1 && echo $VAR"Variável vazia tentada e impressa (esperada 1). o que estou perdendo?
precisa saber é o seguinte
depois de executar o 'docker exec -it CONTAINER_ID / bin / bash', ele entra no bash corretamente, mas não pode interagir com ele.
Blue Clouds
1
Mas se eu estiver usando o docker-compose, o item -itnão estará disponível.
adnanmuttaleb
120

Então, acho que a resposta é mais simples do que muitas respostas enganosas acima.

Para iniciar um contêiner existente que está parado

docker start <container-name/ID>

Para parar um contêiner em execução

docker stop <container-name/ID>

Em seguida, faça login no shell interativo de um contêiner

docker exec -it <container-name/ID> bash

Para iniciar um contêiner existente e anexá-lo a um comando

docker start -ai <container-name/ID>

Cuidado, isso irá parar o contêiner na saída. Mas, em geral, você precisa iniciar o contêiner, anexá-lo e pará-lo após concluir.

Peter T.
fonte
docker anexar <container-name / ID>, que está sendo executado
KunMing Xie
9
@ Peter T. Na verdade, achei sua resposta muito mais concisa do que as que outras pessoas forneceram. Não entendo por que as pessoas preferem complicar uma pergunta muito simples. Obrigado Peter esta resposta.
22617 Helen Neely
1
isso requer que, quando você criou o docker, o fez com -it stackoverflow.com/questions/45216612/… caso contrário, ele não será iniciado. e você verá que não está funcionando após o início. e então o anexo falharia. Então, também é necessário criar com -it.
barlop
1
@ Peter A resposta mais relevante
Nilanjan Sarkar
1
Esta é a resposta mais precisa!
Nagendra547 23/04/19
91

Para expandir a resposta do katrmr, se o contêiner estiver parado e não puder ser iniciado devido a um erro, você precisará commitdele em uma imagem. Então você pode iniciar o bash na nova imagem:

docker commit [CONTAINER_ID] temporary_image
docker run --entrypoint=bash -it temporary_image
Aaron V
fonte
1
FYI, eu faço isso tanto que eu coloquei um comando chamado dshella fazê-lo automaticamente em uma variedade de situações - github.com/avirshup/docker-cli-sugar
Aaron V
41

Algumas das respostas aqui são enganosas porque dizem respeito a contêineres em execução, e não parados.

Sven Dowideit explicou no fórum do Docker que os contêineres estão vinculados ao seu processo (e o Docker não pode alterar o processo de um contêiner parado, aparentemente devido pelo menos à sua estrutura interna: https://github.com/docker/docker/issues / 1437 ). Então, basicamente, a única opção é commito contêiner para uma imagem e runcom um comando diferente.

Consulte https://forums.docker.com/t/run-command-in-stopped-container/343
(acredito que a ENTRYPOINTabordagem " com argumentos" também não funcionaria, pois você ainda não seria capaz de alterar o argumentos para um contêiner parado.)

katrmr
fonte
2
Aviso: executar bin/bashsem -italterar nada no contêiner, portanto, confirmar isso não é realmente necessário e o CDR LDN fornece a resposta certa para a situação específica do OP. Ainda assim, commité a resposta para o problema técnico de como alterar o processo de contêiner.
Katrmr # 30/15
O comentário de candlerb no comando run-command-in-stop-container sugerindo o uso de uma imagem descartável com o volume do contêiner inativo funcionou para mim: docker run --rm --volumes-from CONTAINER -i busybox tar cO / var / DIR gzip -c> ~ / mydir_backup.tgz
eel ghEEz
Esta é a resposta real à pergunta. Os contêineres estão vinculados ao seu processo, portanto, o comando não pode ser alterado.
cjsimon
21

Eu tive que usar o bash -c para executar meu comando: docker exec -it CONTAINER_ID bash -c "mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql mysql"

velop
fonte
1
-c trabalhou para mim. maravilha porque o bash por si só, não trabalho (não recebe um prompt)
André Werlang
18

Criando um contêiner e enviando comandos para ele, um por um:

docker create --name=my_new_container -it ubuntu
docker start my_new_container
// ps -a says 'Up X seconds'
docker exec my_new_container /path/to/my/command
// ps -a still says 'Up X+Y seconds'
docker exec my_new_container /path/to/another/command
langlauf.io
fonte
Esta é a boa resposta para a pergunta. Se você deseja iniciar o contêiner após a criação e conseguir "docker exec" comandos nele, precisará criá-lo com os sinalizadores "-it" no comando docker create.
joanlofe
8

Esta é uma resposta combinada que criei usando a resposta CDR LDN acima e a resposta que encontrei aqui .

O exemplo a seguir inicia um contêiner do Arch Linux a partir de uma imagem e é instalado gitnesse contêiner usando a pacmanferramenta:

sudo docker run -it -d archlinux /bin/bash
sudo docker ps -l
sudo docker exec -it [container_ID] script /dev/null -c "pacman -S git --noconfirm"

Isso é tudo.

irritar
fonte
5

Se você estiver tentando executar o shell script, precisará executá-lo como bash.

docker exec -it containerid bash -c /path/to/your/script.sh
MrKulli
fonte
4

Canalize um comando para stdin

É necessário remover o -tpara que ele funcione:

echo 'touch myfile' | sudo docker exec -i CONTAINER_NAME bash

Isso pode ser mais conveniente do que usar as opções da CLI algumas vezes.

Testado com:

sudo docker run --name ub16 -it ubuntu:16.04 bash

depois em outro shell:

echo 'touch myfile' | sudo docker exec -i ub16 bash

Em seguida, no primeiro shell:

ls -l myfile

Testado no host do Docker 1.13.1, Ubuntu 16.04.

Ciro Santilli adicionou uma nova foto
fonte
3

Supondo que a imagem esteja usando o ponto de entrada padrão /bin/sh -c, a execução /bin/bashserá encerrada imediatamente no modo daemon (-d ). Se você deseja que esse contêiner execute um shell interativo, use em -itvez de -d. Se você deseja executar comandos arbitrários em um contêiner que normalmente executa outro processo, tente nsenterou nsinit. Consulte https://blog.codecentric.de/en/2014/07/enter-docker-container/ para obter detalhes.

Andreas Steffan
fonte
3

Infelizmente, é impossível substituir ENTRYPOINTargumentos com docker run --entrypointpara atingir esse objetivo.

Nota: você pode substituir a configuração ENTRYPOINT usando --entrypoint, mas isso só pode definir o binário como exec (nenhum sh -c será usado).

wieczorek1990
fonte
3

Gostaria de observar que a resposta principal é um pouco enganadora.

O problema com a execução docker run é que um novo contêiner é criado sempre. No entanto, há casos em que gostaríamos de revisitar contêineres antigos ou não ocupar espaço com novos contêineres.

(Dado clever_bardeen é o nome do contêiner criado ...)

No caso do OP, verifique se a imagem do docker está sendo executada executando o seguinte comando:

docker start clever_bardeen

Em seguida, execute o contêiner do docker usando o seguinte comando:

docker exec -it clever_bardeen /bin/bash
Josh
fonte
2

Para Mac:

$ docker exec -it <container-name> sh

se você deseja se conectar como usuário root:

$ docker exec -u 0 -it <container-name> sh
Lyncean Patel
fonte
1

Resposta simples: inicie e anexe ao mesmo tempo. Nesse caso, você está fazendo exatamente o que pediu.

docker start <CONTAINER_ID/CONTAINER_NAME> && docker attach <CONTAINER_ID/CONTAINER_NAME> 

certifique-se de mudar <CONTAINER_ID/CONTAINER_NAME>

user353305
fonte
1
# docker exec -d container_id command 

Ex:

# docker exec -d xcdefrdtt service jira stop 
Rajesh Gurram
fonte
1

Estou executando o contêiner do Windows e preciso procurar dentro do contêiner do docker arquivos e pastas criados e copiados.

Para fazer isso, usei o seguinte comando docker entrypoint para obter o prompt de comando em execução dentro do contêiner ou anexá-lo ao contêiner.

ENTRYPOINT ["C:\\Windows\\System32\\cmd.exe", "-D", "FOREGROUND"]

Isso me ajudou a anexar o prompt de comando ao contêiner e a manter o contêiner ativo. :)

Jenish Rabadiya
fonte
0

Uma maneira rápida de retomar e acessar o contêiner encerrado mais recentemente:

docker start -a -i `docker ps -q -l`
Pierz
fonte
0

Eu costumo usar isso:

    docker exec -it my-container-name bash

para interagir continuamente com um contêiner em execução.

Amin Shojaei
fonte