O contêiner do Docker para automaticamente após "docker run -d"

333

De acordo com o tutorial que li até agora, o uso " docker run -d" iniciará um contêiner a partir da imagem e o contêiner será executado em segundo plano. É assim que parece, podemos ver que já temos o ID do contêiner.

root@docker:/home/root# docker run -d centos
605e3928cdddb844526bab691af51d0c9262e0a1fc3d41de3f59be1a58e1bd1d

Mas se eu corri " docker ps", nada foi retornado.

Então eu tentei " docker ps -a", posso ver o container já encerrado:

root@docker:/home/root# docker ps -a
CONTAINER ID        IMAGE                 COMMAND             CREATED             STATUS                         PORTS               NAMES
605e3928cddd        centos:latest         "/bin/bash"         31 minutes ago      Exited (0) 31 minutes ago                          kickass_swartz

Algo que fiz de errado? Como posso solucionar esse problema?

J John
fonte
1
"docker run hello-world" <== funciona perfeitamente, mas se eu executar "docker run -d hello-world", ainda não consigo obter um contêiner em execução.
J John
5
Eu tive um problema semelhante, mas consegui trabalhar usando docker run -it -d <image> /bin/bashisso inicia um shell bash interativamente e não fecha o contêiner porque o processo do shell está ativo.
Rtsne42

Respostas:

495

O arquivo de docker centos possui um comando padrão bash.

Isso significa que, quando executado em background ( -d), o shell sai imediatamente.

Atualização 2017

Versões mais recentes do authorize janela de encaixe para executar um recipiente tanto no modo independente e em modo de primeiro plano ( -t, -iou -it)

Nesse caso, você não precisa de nenhum comando adicional e isso é suficiente:

docker run -t -d centos

O bash aguardará em segundo plano.
Que foi inicialmente relatada em Kalyani-chaudhari 's resposta e detalhado na camisa de feijão ' s resposta .

vonc@voncvb:~$ d ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
4a50fd9e9189        centos              "/bin/bash"         8 seconds ago       Up 2 seconds                            wonderful_wright

Observe que, para os alpinos , Marinos An relata nos comentários :

docker run -t -d alpine/gitnão mantém o processo.
Tive que fazer:docker run --entrypoint "/bin/sh" -it alpine/git


Resposta original (2015)

Conforme mencionado neste artigo :

Em vez de executar com docker run -i -t image your-command, -dé recomendável usar porque você pode executar seu contêiner com apenas um comando e não precisa desconectar o terminal do contêiner pressionando Ctrl+ P+ Q.

No entanto, há um problema com a -dopção. Seu contêiner para imediatamente, a menos que os comandos não estejam sendo executados em primeiro plano .
O Docker requer que seu comando continue em execução em primeiro plano. Caso contrário, ele acha que seus aplicativos param e encerram o contêiner.

O problema é que alguns aplicativos não são executados em primeiro plano. Como podemos facilitar?

Nesta situação, você pode adicionar tail -f /dev/nullao seu comando.
Ao fazer isso, mesmo que seu comando principal seja executado em segundo plano, seu contêiner não pára porque a cauda continua em execução em primeiro plano.

Então, isso funcionaria:

docker run -d centos tail -f /dev/null

A docker psmostraria o contêiner de centos ainda em execução.

A partir daí, você pode anexá-lo ou desanexá-lo (ou docker execalguns comandos).

VonC
fonte
Desculpe, mais uma pergunta, eu tenho que executar um script na inicialização, parece que /etc/rc.d/rc.local não funciona mais (minha mentalidade ainda trata o docker como sistema operacional), presumo que o arquivo docker seja a melhor opção neste caso?
J John
5
@GuruprasadGV Isso é esperado. Em vez de usar o docker attach, use docker exec -it <yourContainer> bash.
VonC
3
Isso também funciona se você adicionar o comando tail no final de um arquivo de ponto de entrada.
Yara
2
Eu usei o sshd como meu último comando (de longa execução). Você também pode ssh no seu contêiner como faria em uma VM (depois de definir .ssh / allowed_keys etc) ... Você também pode configurar o contêiner usando ansible.
andrew pate
1
Acabei fazendo isso para executar meu comando mais a correção mais velho listados acima: estivador prazo image_name / bin / bash -c "meu comando / && tail -f / dev / null"
Geordie
58

De acordo com esta resposta , adicionar o -tsinalizador impedirá a saída do contêiner ao executar em segundo plano. Você pode usar docker exec -i -t <image> /bin/bashpara entrar em um prompt de shell.

docker run -t -d <image> <command>

Parece que a opção -t não está muito bem documentada , embora a ajuda diga que "aloca um pseudo-TTY".

cjsimon
fonte
10
Agradável. Parece menos hacky de acrescentartail -f /dev/null
Scarysize
Obrigado! Na pequena chance de ajudar alguém, isso não se comporta bem no Emacs Eshell.
Peter Becich
2
docker run -t -d --name mysql -p 3306:3306 mysql- não funciona para mim (ubuntu 14.04.5): STATUS = Saído (1) 4 segundos atrás
Putnik
Descobri que você não precisa de <comando> aqui, a menos que queira. Estranhamente, ele também trabalha para substituir -t por -i (interativo). O documento menciona o uso de -t e -i combinados se comportará como um shell.
jersey bean
43

fundo

Um contêiner do Docker executa um processo (o "comando" ou "ponto de entrada") que o mantém ativo. O contêiner continuará sendo executado enquanto o comando continuar sendo executado.

No seu caso, o comando ( /bin/bashpor padrão, centos:latestativado) sai imediatamente (como o bash faz quando não está conectado a um terminal e não tem nada para executar).

Normalmente, quando você executa um contêiner no modo daemon (com -d), o contêiner está executando algum tipo de processo daemon (como httpd). Nesse caso, enquanto o daemon httpd estiver em execução, o contêiner permanecerá ativo.

O que você parece estar tentando fazer é manter o contêiner vivo sem que um processo daemon seja executado dentro do contêiner. Isso é um pouco estranho (porque o contêiner não está fazendo nada útil até você interagir com ele, talvez com docker exec), mas há certos casos em que pode fazer sentido fazer algo assim.

(Você quis chegar a um prompt do bash dentro do contêiner? Isso é fácil! docker run -it centos:latest)

Solução

Uma maneira simples de manter um contêiner ativo no modo daemon indefinidamente é executar sleep infinitycomo o comando do contêiner. Isso não depende de coisas estranhas, como alocar um TTY no modo daemon. Embora dependa de fazer coisas estranhas, como usar sleepcomo seu comando principal.

$ docker run -d centos:latest sleep infinity
$ docker ps
CONTAINER ID  IMAGE         COMMAND          CREATED       STATUS       PORTS NAMES
d651c7a9e0ad  centos:latest "sleep infinity" 2 seconds ago Up 2 seconds       nervous_visvesvaraya

Solução alternativa

Conforme indicado por cjsimon, a -topção aloca um "pseudo-tty". Isso ajuda a continuar executando indefinidamente, porque pensa que está conectado a um TTY interativo (mesmo que você não tenha como interagir com esse TTY em particular, se não for aprovado -i). De qualquer forma, isso também deve funcionar:

$ docker run -t -d centos:latest

Não tenho 100% de certeza se -tproduzirá outras interações estranhas; talvez deixe um comentário abaixo, se houver.

mkasberg
fonte
Observe que isso não funciona em alpino, pois o sono do BusyBox não aceita infinity.
John Kugelman
isso me ajudou a solucionar uma imagem do amazon-linux, obrigado
influente
18

Olá, esse problema ocorre porque os contêineres do docker saem se não houver aplicativo em execução no contêiner.

-d 

A opção é apenas executar um contêiner no modo deamon.

Portanto, o truque para tornar seu contêiner em execução contínua é apontar para um arquivo shell no docker que manterá seu aplicativo em execução. Você pode tentar com um arquivo start.sh

Eg: docker run -d centos sh /yourlocation/start.sh

Este start.sh deve apontar para um aplicativo sem fim.

Caso você não queira que nenhum aplicativo esteja em execução, você pode instalar o monitque manterá o contêiner do docker em execução. Informe-nos se esses dois casos funcionaram para você manter seu contêiner em funcionamento.

Muito bem sucedida

Pratik
fonte
12

Você pode realizar o que deseja com:

docker run -t -d <image-name>

ou

docker run -i -d <image-name>

ou

docker run -it -d <image-name>

O parâmetro de comando, conforme sugerido por outras respostas (ou seja, tail -f / dev / null) é totalmente opcional e NÃO é necessário para que seu contêiner permaneça em execução em segundo plano.

Observe também que a documentação do Docker sugere que a combinação das opções -i e -t fará com que ele se comporte como um shell.

Vejo:

https://docs.docker.com/engine/reference/run/#foreground

feijão jersey
fonte
9

Eu tenho esse snippet de código executado ENTRYPOINTno arquivo docker:

while true
do
    echo "Press [CTRL+C] to stop.."
    sleep 1
done

Execute a imagem da janela de encaixe incorporada como:

docker run -td <image name>

Efetue login no shell do contêiner:

docker exec -it <container id> /bin/bash
Binita Bharati
fonte
esta é a solução que você criou loop infinito para isso? : D
Muhammad SaLman
8

execute o comando da seguinte maneira:

docker run -t -d <image-name>

Se você deseja especificar porta, então comando como abaixo:

docker run -t -d -p <port-no> <image-name>

verifique o contêiner em execução usando o seguinte comando:

docker ps
Kalyani Chaudhari
fonte
Na verdade, eu gosto mais dessa resposta, porque a resposta mais popular sugere que você precisa de um comando (ou seja, tail -f / dev / null). O comando é completamente opcional. A chave aqui é usar -t. Eu também encontrei -i trabalho no lugar de -t, ou você também pode usar os dois -it combinados (como a documentação sugere que seja executado como um shell).
jersey bean
Existe alguma vantagem em usar -t -dvs -i -d? Ambos manterão o contêiner em funcionamento.
wisbucky
5

O Docker requer que seu comando continue em execução em primeiro plano. Caso contrário, ele acha que seus aplicativos param e encerram o contêiner.

Portanto, se o script de entrada do docker for um processo em segundo plano, como a seguir:

/usr/local/bin/confd -interval=30 -backend etcd -node $CONFIG_CENTER &

O '&' faz o contêiner parar e sair se não houver outro processo em primeiro plano acionado posteriormente. Portanto, a solução é apenas remover o '&' ou executar outro CMD em primeiro plano , como

tail -f server.log
Peiming Hu
fonte
Talvez você queira touchesse arquivo primeiro, caso não encontre um arquivo de log.
Samuel Elh
Normalmente, o arquivo de log final é o resultado atual do log ou redirecionamento do servidor, que já deveria estar lá após o início do processo.
Peiming Hu 20/02/19
4

O contêiner do Docker sai se a tarefa interna for concluída; portanto, se você quiser mantê-lo ativo, mesmo que não tenha nenhum trabalho ou já os tenha concluído, é possível docker run -di image. Depois que docker container lsvocê o verá em execução.

Vrangz
fonte
3

Talvez seja só eu, mas no CentOS 7.3.1611 e no Docker 1.12.6, mas acabei tendo que usar uma combinação das respostas postadas por @VonC e @Christopher Simon para que isso funcione de maneira confiável. Nada que eu fiz antes disso impediria a saída do contêiner após a execução do CMD com êxito. Estou iniciando o oracle-xe-11Gr2 e o sshd.

Dockerfile

...
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N '' && systemctl enable sshd
...
CMD /etc/init.d/oracle-xe start && /sbin/sshd && tail -f /dev/null

Em seguida, adicione -d -t e -i para executar

docker run --shm-size=2g --name oracle-db -d -t -i -p 5022:22 -p 5080:8080 -p 1521:1521 centos-oracle:7.3.1611 

Finalmente, depois de horas batendo minha cabeça contra a parede

ssh -v [email protected] -p 5022
...
[email protected]'s password: 
debug1: Authentication succeeded (password).

Por qualquer motivo, o acima será encerrado após a execução do CMD se a cauda -f for removida ou se alguma das opções -t -d -i for omitida.

steven87vt
fonte
1

Eu tive o mesmo problema, basta abrir outro terminal com uma festança para mim:

criar contêiner:

docker run -d mcr.microsoft.com/mssql/server:2019-CTP3.0-ubuntu
containerid=52bbc9b30557

contêiner de início:

docker start 52bbc9b30557

inicie o bash para manter o contêiner em execução:

docker exec -it 52bbc9b30557 bash

Para iniciar o processo, você precisa:

docker exec -it 52bbc9b30557 /path_to_cool_your_app
Steef
fonte
1

Se você estiver usando o CMD no final do Dockerfile, o que você pode fazer é adicionar o código no final. Isso só funcionará se o seu docker for construído no ubuntu ou em qualquer sistema operacional que possa usar o bash.

&& /bin/bash

Resumidamente, o final do seu Dockerfile será algo como isto.

...

CMD ls && ... && /bin/bash

Portanto, se você tiver algo em execução automaticamente depois de executar sua imagem do docker e quando a tarefa for concluída, o terminal bash estará ativo dentro do docker. Assim, você pode inserir seus comandos do shell.

Ekin
fonte
1

A execução da janela de encaixe com o modo interativo pode resolver o problema.

Aqui está o exemplo para executar imagens com e sem o modo interativo

chaitra @ RSK-IND-BLR-L06: ~ / dockers $ sudo docker run -d -t -i test_again1.0 b6b9a942a79b1243bada59db19c7999cfff52d0a8744542fa843c95354966a18

chaitra @ RSK-IND-BLR-L06: ~ / dockers $ sudo docker ps

ID DE RECIPIENTE COMANDO DE IMAGEM NOMES DE PORTAS DE STATUS CRIADAS

chaitra @ RSK-IND-BLR-L06: ~ / dockers $ sudo docker run -d -t -i test_again1.0 bash c3d6a9529fd70c5b2dc2d7e90fe662d19c6dad8549e9c812fb2b7ce2105d7ff5

chaitra @ RSK-IND-BLR-L06: ~ / dockers $ sudo docker ps

ID DO RECIPIENTE COMANDO DE IMAGEM CRIADO NOMES DE PORTAS DE ESTADO c3d6a9529fd7 test_again1.0 "bash" 2 segundos atrás Acima 1 segundo awesome_haibt

Chaitra
fonte
0

se você deseja operar no contêiner, é necessário executá-lo em primeiro plano para mantê-lo vivo.

lwpro2
fonte
-1

A ordem dos argumentos é importante

A resposta de Jersey Beans (todos os 3 exemplos) funcionou para mim. Após várias tentativas e erros, percebi que a ordem dos argumentos importa.

Mantém o contêiner em execução em segundo plano: docker run -t -d <image-name>

Mantém o contêiner em execução em primeiro plano: docker run <image-name> -t -d

Não era óbvio para mim, proveniente de um histórico do Powershell.

HVL71
fonte