Por que o contêiner do docker sai imediatamente


239

Eu corro um contêiner em segundo plano usando

 docker run -d --name hadoop h_Service

sai rapidamente. Mas se eu correr em primeiro plano, funciona bem. Eu verifiquei logs usando

docker logs hadoop

não houve erro. Alguma ideia?

DOCKERFILE

 FROM java_ubuntu_new
 RUN wget http://archive.cloudera.com/cdh4/one-click-install/precise/amd64/cdh4-repository_1.0_all.deb
 RUN dpkg -i cdh4-repository_1.0_all.deb
 RUN curl -s http://archive.cloudera.com/cdh4/ubuntu/precise/amd64/cdh/archive.key | apt-key add -
 RUN  apt-get update
 RUN apt-get install -y hadoop-0.20-conf-pseudo
 RUN dpkg -L hadoop-0.20-conf-pseudo
 USER hdfs
 RUN hdfs namenode -format
 USER root
 RUN apt-get install -y sudo
 ADD . /usr/local/
 RUN chmod 777 /usr/local/start-all.sh
 CMD ["/usr/local/start-all.sh"]

start-all.sh

 #!/usr/bin/env bash
 /etc/init.d/hadoop-hdfs-namenode start
 /etc/init.d/hadoop-hdfs-datanode start
 /etc/init.d/hadoop-hdfs-secondarynamenode start
 /etc/init.d/hadoop-0.20-mapreduce-tasktracker start
 sudo -u hdfs hadoop fs -chmod 777 /
 /etc/init.d/hadoop-0.20-mapreduce-jobtracker start
 /bin/bash

1
A regra de ouro é que você deve impedir que seus servidores dockerizados sejam daemonizados. A maioria dos pacotes de servidores tem opções para forçá-los em primeiro plano, pois daemonizing é o caso normal.
Arnaud Meuret 22/09/2015

Tudo o que você está esperando para realizar, chmod 777é insegura e errado. Você deve reverter para permissões sãs (provavelmente 755 neste caso).
Tripleee

Respostas:


125

Um contêiner de docker sai quando o processo principal é concluído.

Nesse caso, ele será encerrado quando o start-all.shscript terminar. Eu não sei o suficiente sobre o hadoop para dizer como fazê-lo nesse caso, mas você precisa deixar algo em execução em primeiro plano ou usar um gerenciador de processos como runit ou supervisord para executar os processos.

Eu acho que você deve estar enganado sobre isso funcionando se você não especificar -d; deve ter exatamente o mesmo efeito. Eu suspeito que você o lançou com um comando ou uso ligeiramente diferente, o -itque mudará as coisas.

Uma solução simples pode ser adicionar algo como:

while true; do sleep 1000; done

até o final do script. No entanto, não gosto disso, pois o script deve realmente monitorar os processos que ele iniciou.

(Devo dizer que eu roubei esse código de https://github.com/sequenceiq/hadoop-docker/blob/master/bootstrap.sh )


218

Isso fez o truque para mim:

docker run -dit ubuntu

Depois disso, verifiquei os processos em execução usando:

docker ps -a

Para prender novamente o contêiner

docker attach CONTAINER_NAME

DICA: Para sair sem parar o tipo de contêiner: ^P^Q


15
@Tommy, de docs.docker.com/engine/reference/commandline/run -d, --detach Modo desanexado: execute o comando em segundo plano, -i, --interactive Mantenha o STDIN aberto mesmo se não estiver conectado, -t, - -tty Aloca um pseudo-TTY -dité apenas uma abreviação #

3
@ am17torres certo, desculpe, deixe-me esclarecer minha pergunta confusa; d é desanexado e i é interativo; portanto, a combinação de d e i é confusa para mim. Eu pensei que d seria lançá-lo como um processo em segundo plano (não interativo).
Tommy

2
@ Tommy Quando essas opções combinadas, o container entra no modo interativo em segundo plano .
Yon

2
@Tommy, @ am17torres -dié o mínimo necessário, a -topção é redundante quando usado com -dse eu entendi corretamente
Renaud

2
Na verdade, você não será capaz de ver sua solicitação se reconectar sem -thabilitar ... mas como eu costumo fazer execuma nova festança toda vez que não percebo. Eu tive problemas destacando a partir de um Mac, mas talvez eu estou fazendo isso errado ..
Renaud

65

Gostaria de estender ou ousar dizer, melhorar a resposta mencionada por camposer

Quando você corre

docker run -dit ubuntu

você está basicamente executando o contêiner em segundo plano no modo interativo.

Quando você anexa e sai do contêiner por CTRL + D (maneira mais comum de fazer isso), você para o contêiner porque acabou de interromper o processo principal no qual iniciou o contêiner com o comando acima.

Tirando proveito de um contêiner já em execução, eu apenas bifurcaria outro processo de bash e obteria um pseudo TTY executando:

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

29

sempre que eu quiser que um contêiner fique acordado depois de terminar a execução do script, eu adiciono

&& tail -f /dev/null

no final do comando. Então deve ser:

/usr/local/start-all.sh && tail -f /dev/null

19

Por que o contêiner de encaixe sai imediatamente?

Se você deseja forçar a imagem a ficar por aí (para depurar algo ou examinar o estado do sistema de arquivos), você pode substituir o ponto de entrada para alterá-lo para um shell:

docker run -it --entrypoint=/bin/bash myimagename

18

Uma boa abordagem seria iniciar seus processos e serviços executando-os em segundo plano e usar o wait [n ...]comando no final do seu script. No bash, o comando wait força o processo atual a:

Aguarde cada processo especificado e retorne seu status de encerramento. Se n não for fornecido, todos os processos filhos ativos no momento serão aguardados e o status de retorno será zero.

Eu peguei essa idéia no script inicial de Sébastien Pujadas para a construção de seu alce .

Partindo da pergunta original, seu start-all.sh ficaria assim:

 #!/usr/bin/env bash
 /etc/init.d/hadoop-hdfs-namenode start &
 /etc/init.d/hadoop-hdfs-datanode start &
 /etc/init.d/hadoop-hdfs-secondarynamenode start &
 /etc/init.d/hadoop-0.20-mapreduce-tasktracker start &
 sudo -u hdfs hadoop fs -chmod 777 /
 /etc/init.d/hadoop-0.20-mapreduce-jobtracker start &
 wait

5

Adicione isso ao final do Dockerfile:

CMD tail -f /dev/null

Arquivo Docker de amostra:

FROM ubuntu:16.04

# other commands

CMD tail -f /dev/null

Referência


CMD tail -f /dev/nullexecuta isso sh -c "...". Em execvez disso, podemos usar o formulário? Ou sejaCMD ["tail", "-f", "/dev/null"]
Meglio

4

Minha prática é que no Dockerfile inicie um shell que não saia imediatamente CMD [ "sh", "-c", "service ssh start; bash"]e execute docker run -dit image_name. Dessa forma, o serviço (ssh) e o contêiner estão em execução.


1

Eu adicionei a readdeclaração do shell no final. Isso mantém o processo principal do contêiner - script do shell de inicialização - em execução.


1

Adicionando

exec "$@"

no final do meu script de shell foi a minha correção!


Isso apenas significa que ele executará seu cmd, se o cmd for apenas 'bash', ele ainda não funcionará
Shardj 14/01

1

Se você verificar o Dockerfile a partir de contêineres, por exemplo, fballiano / magento2-apache-php

você verá que no final de seu arquivo ele adiciona o seguinte comando: while true; dorme 1; feito

Agora, o que eu recomendo é que você faça isso

docker container ls --all | grep 127

Em seguida, você verá se a imagem do docker teve um erro, se sair com 0, provavelmente precisará de um desses comandos que durará para sempre.


0

Existem muitas maneiras possíveis de fazer com que uma janela de encaixe saia imediatamente. Para mim, foi o problema com o meu Dockerfile. Houve um erro nesse arquivo. Eu tinha em ENTRYPOINT ["dotnet", "M4Movie_Api.dll]vez de ENTRYPOINT ["dotnet", "M4Movie_Api.dll"]. Como você pode ver, perdi uma citação (") no final.

Para analisar o problema, iniciei meu contêiner e rapidamente o anexei para que eu pudesse ver qual era o problema exato.

C:\SVenu\M4Movie\Api\Api>docker start 4ea373efa21b


C:\SVenu\M4Movie\Api\Api>docker attach 4ea373efa21b

Onde 4ea373efa21b é o meu ID de contêiner. Isso me leva ao problema real.

insira a descrição da imagem aqui

Depois de encontrar o problema, tive que criar, restaurar, publicar meu contêiner novamente.


0

Vindo de duplicatas, não vejo nenhuma resposta aqui que lide com o antipadrão muito comum de executar sua carga de trabalho principal como um trabalho em segundo plano, e depois me pergunto por que o Docker sai.

Em termos simples, se você tiver

my-main-thing &

em seguida, retire o &para executar o trabalho em primeiro plano ou adicione

wait

no final do script, para aguardar todos os trabalhos em segundo plano.

Ele ainda será encerrado se a carga de trabalho principal terminar, portanto, talvez execute isso em while trueloop para forçá-lo a reiniciar para sempre:

while true; do
    my-main-thing &
    other things which need to happen while the main workload runs in the background
    maybe if you have such things
    wait
done

(Observe também como escrever while true. É comum ver coisas tolas como while [ true ]ou while [ 1 ]que por acaso funcionam, mas não significa o que o autor provavelmente imaginou que deveria significar.)


0

Você precisa executá-lo com o sinalizador -d para deixá-lo em execução como daemon em segundo plano.

docker executar -d -it ubuntu bash


-5

Você pode executar o contêiner usando este sinalizador de reinicialização.

docker run -d --name=<some-name> -p xxxx:xxxx ... <image-name> --restart=unless-stopped

-8

Como a imagem é linux, é preciso verificar se os scripts de shell usados ​​no contêiner possuem finais de linha unix. Se eles tiverem um ^ M no final, serão finais de linha do Windows. Uma maneira de corrigi-los é com o dos2unix em /usr/local/start-all.sh para convertê-los do Windows para o Unix. A execução da janela de encaixe no modo interativo pode ajudar a descobrir outros problemas. Você pode ter um erro de digitação do nome do arquivo ou algo assim. consulte https://en.wikipedia.org/wiki/Newline

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.