Eu já vi vários tutoriais que parecem fazer a mesma coisa que estou tentando fazer, mas por algum motivo meus contêineres do Docker saem. Basicamente, estou configurando um servidor Web e alguns daemons dentro de um contêiner do Docker. Eu faço as partes finais disso por meio de um script bash chamado run-all.sh
que eu corro pelo CMD no meu Dockerfile. run-all.sh
se parece com isso:
service supervisor start
service nginx start
E inicio-o dentro do meu Dockerfile da seguinte maneira:
CMD ["sh", "/root/credentialize_and_run.sh"]
Percebo que todos os serviços iniciam corretamente quando executo as coisas manualmente (por exemplo, acessando a imagem com -i -t / bin / bash), e tudo parece funcionar corretamente quando executo a imagem, mas sai uma vez termina iniciando meus processos. Eu gostaria que os processos fossem executados indefinidamente e, pelo que entendi, o contêiner precisa continuar em execução para que isso aconteça. No entanto, quando corro docker ps -a
, vejo:
➜ docker_test docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c7706edc4189 some_name/some_repo:blah "sh /root/run-all.sh 8 minutes ago Exited (0) 8 minutes ago grave_jones
O que da? Por que está saindo? Eu sei que eu poderia colocar um loop while no final do meu script bash para continuar, mas qual é a maneira certa de impedir que ele saia?
Respostas:
Não é assim que você deve projetar seus contêineres do Docker.
Ao projetar um contêiner do Docker, você deve construí-lo para que exista apenas um processo em execução (ou seja, você deve ter um contêiner para o Nginx e outro para o supervisord ou o aplicativo em execução); Além disso, esse processo deve ser executado em primeiro plano.
O contêiner "sairá" quando o processo em si for encerrado (no seu caso, esse processo é seu script bash).
No entanto, se você realmente precisar (ou desejar) executar vários serviços no seu contêiner Docker, considere iniciar a partir de "Imagem Base do Docker" , que usa
runit
como um processo pseudo-init (runit
permanecerá online enquanto o Nginx e o Supervisor executam), que permanecerá em primeiro plano, enquanto seus outros processos fazem as coisas deles.Eles têm documentos substanciais; portanto, você deve conseguir o que está tentando fazer razoavelmente facilmente.
fonte
--nodaemon
opçãoSe você estiver usando um Dockerfile, tente:
(Obviamente, isso é apenas para fins de desenvolvimento, você não precisa manter um contêiner vivo, a menos que esteja executando um processo, por exemplo, nginx ...)
fonte
CMD["sleep", "1d"]
, mas sua solução parece melhorCMD["sleep", "infinity"]
.exec tail -f /dev/null
mas usartail
como um ponto de entrada é uma resposta errada.Acabei de ter o mesmo problema e descobri que, se você estiver executando seu contêiner com o sinalizador
-t
e-d
, ele continuará sendo executado.Aqui está o que as bandeiras fazem (de acordo com
docker run --help
):O mais importante é a
-t
bandeira.-d
permite executar o contêiner em segundo plano.fonte
docker logs <image>
para garantir que foi um erro que causou a saída do contêiner do Docker. O estado de saída é0
ea última saída é confimation que meulighttpd
servidor está em execução:[ ok ] Starting web server: lighttpd.
exec bash
ouexec sh
se o bash não estiver instalado, até o final do start.sh. Então você pode usar a bandeira -tA razão pela qual ele sai é porque o script do shell é executado primeiro como PID 1 e, quando concluído, o PID 1 desaparece e o docker é executado apenas enquanto o PID 1 está.
Você pode usar o supervisor para fazer tudo; se for executado com o sinalizador "-n", é solicitado que você não daemonize, portanto, ele permanecerá como o primeiro processo:
E seu supervisord.conf:
Em seguida, você poderá ter quantos outros processos desejar e o supervisor cuidará da reinicialização deles, se necessário.
Dessa forma, você pode usar o supervisord nos casos em que possa precisar de nginx e php5-fpm e não faz muito sentido separá-los.
fonte
If the "init" process of a PID namespace terminates, the kernel terminates all of the processes in the namespace via a SIGKILL signal. This behavior reflects the fact that the "init" process is essential for the correct operation of a PID namespace.
você pode executar
cat
sem nenhum argumento, como mencionado por bro @ Sa'ad, para simplesmente manter o contêiner funcionando (na verdade, nada mais é do que aguardar a entrada do usuário) (o plugin Docker do Jenkins faz a mesma coisa)fonte
cat
. O plugin docker de jenkin faz isso.Certifique-se de adicionar
daemon off;
o nginx.conf ou executá-loCMD ["nginx", "-g", "daemon off;"]
conforme a imagem oficial do nginxEm seguida, use o seguinte para executar o processo de supervisor como serviço e nginx como primeiro plano que impedirá a saída do contêiner
service supervisor start && nginx
Em alguns casos, você precisará ter mais de um processo em seu contêiner, portanto, forçar o contêiner a ter exatamente um processo não funcionará e poderá criar mais problemas na implantação.
Portanto, você precisa entender as compensações e tomar sua decisão de acordo.
fonte
Motivação:
Não há nada de errado em executar vários processos dentro de um contêiner de docker . Se alguém gosta de usar o docker como uma VM leve - que assim seja. Outros gostam de dividir seus aplicativos em microsserviços. Eu pensa: Uma pilha LAMP em um contêiner? Apenas ótimo.
A resposta:
Fique com uma boa imagem de base, como a imagem de base do phusion . Pode haver outros. Por favor comente.
E este é apenas mais um pedido de supervisor. Como a imagem base do phusion está fornecendo supervisor, além de outras coisas, como cron e configuração de localidade. Coisas que você gosta de configurar ao executar uma VM tão leve. Pelo que vale a pena, também fornece conexões ssh no contêiner.
A própria imagem do phusion será iniciada e continuará sendo executada se você emitir esta instrução básica de execução do docker:
Ou simplesmente simples:
Se uma imagem base não é para você ... Para o CMD rápido para mantê-lo em execução, eu suponho algo assim para o bash:
Ou isso para o busybox:
Isso é bom, porque sairá imediatamente em um
docker stop
. Simplesmentesleep
oucat
levará alguns segundos antes que o contêiner saia.fonte
Capture o PID do processo ngnix em uma variável (por exemplo, $ NGNIX_PID) e, no final do arquivo do ponto de entrada,
Dessa forma, seu contêiner deve ser executado até que o ngnix esteja ativo; quando o ngnix para, o contêiner também pára
fonte
Que tal usar a forma de serviço de supervisão, se disponível?
serviço YOUR_SERVICE supervisionar
Economiza a necessidade de criar um
supervisord.conf
fonte