Uso do Supervisor no Docker

Eu não estou perguntando sobre o uso de supervisor com dockers, mas apenas quero ter meu entendimento validado.

Eu entendo que o docker executa um único processo quando é executado. Além disso, o supervisor é usado quando precisamos executar vários processos no contêiner.

Vi vários exemplos em que um contêiner é iniciado a partir da imagem base e vários serviços são instalados e o contêiner é confirmado para formar uma nova imagem, tudo sem supervisor.

Então, minha dúvida básica era qual é a diferença entre as duas abordagens.

Meu entendimento é que, quando o contêiner do docker é parado, ele envia um sinal kill ao processo com PID 1, o PID 1 gerencia o processo filho e interrompe todos os filhos, exatamente o que é feito pelo supervisor, enquanto podemos instalar vários processos sem supervisor O processo pode ser executado quando a execução do docker é emitida e, quando o contêiner é parado, somente os sinais PID 1 serão enviados e o processo de execução não será interrompido normalmente.

Por favor, confirme o quanto meu entendimento sobre o uso do supervisord está correto.

obrigado

Embora possamos instalar vários processos sem supervisor, somente um processo pode ser executado quando a execução do docker é emitida e quando o contêiner é interrompido, somente os sinais PID 1 serão enviados e outro processo em execução não será interrompido normalmente.

Sim, embora dependa de como o processo principal é executado (primeiro plano ou plano de fundo) e como ele coleta processos filhos.

Isso é o que é detalhado em ” Trapping signals in Docker containers ”

docker stop interrompe um contêiner em execução enviando-lhe um sinal SIGTERM , permite que o processo principal o processe e, após um período de tolerância, utiliza o SIGKILL para encerrar o aplicativo.

O sinal enviado ao contêiner é tratado pelo processo principal em execução (PID 1).

Se o aplicativo estiver em primeiro plano, significando que o aplicativo é o processo principal em um contêiner (PID1), ele poderia manipular os sinais diretamente.

Mas:

O processo a ser sinalizado pode ser o de fundo e você não pode enviar nenhum sinal diretamente. Nesse caso, uma solução é configurar um script de shell como o ponto de input e orquestrar todo o processamento de sinal nesse script.

A questão é detalhada em ” Docker and the PID 1 zombie harvesting problem ”

O Unix é projetado de tal forma que os processos pai devem explicitamente “esperar” pelo término do processo filho, a fim de coletar seu status de saída. O processo zumbi existe até que o processo pai tenha executado essa ação, usando a família waitpid() das chamadas do sistema.

A ação de chamar waitpid () em um processo filho para eliminar o zumbi é chamada de “reaping”.

O processo de init – PID 1 – tem uma tarefa especial. Sua tarefa é “adotar” processos filhos órfãos.

https://blog.phusion.nl/wp-content/uploads/2015/01/adoption.png

O sistema operacional espera que o processo init também aproveite as crianças.

Problema com o Docker:

Vemos que muitas pessoas executam apenas um processo em seu contêiner e pensam que, quando executam esse processo único, acabam.
Mas o mais provável é que esse processo não seja escrito para se comportar como um processo init adequado.
Isto é, em vez de colher apropriadamente processos adotados, é provável que esteja esperando outro processo de init para fazer esse trabalho, e com razão.

O uso de uma imagem como phusion/baseimage-docker ajuda a gerenciar um (ou vários) processo (s) enquanto mantém um processo principal compatível com init.

Ele usa o runit vez do supervisord , para gerenciamento multi-processo:

Runit não está lá para resolver o problema da colheita. Pelo contrário, é para suportar vários processos. Múltiplos processos são encorajados para segurança (através de isolamento de processo e usuário).
Runit usa menos memory que Supervisord porque Runit é escrito em C e Supervisord em Python.
E, em alguns casos de uso, as reinicializações de processo no contêiner são preferíveis às reinicializações de todo o contêiner.

Essa imagem inclui um script my_init que cuida do problema de “colheita”.

No baseimage-docker, incentivamos a execução de vários processos em um único contêiner. Não necessariamente vários serviços embora.
Um serviço lógico pode consistir em vários processos do sistema operacional, e nós fornecemos as facilidades para fazer isso facilmente.

Atualização de setembro de 2016 para o docker 1.12 (Q4 2016 / Q1 2017)

Arnaud Porterie acabou de twittar :

[🐳] Apenas fundido: com o docker run --init , Rick Grimes cuidará de todos os seus zumbis.

( commit eabae09 )

Veja PR 26061 : ” Adicionar processo de boot para combate a zumbis e manipulação de sinais ” (e PR 26736 )

Isso adiciona um pequeno binário C para combater zumbis. Ele é montado em / dev / init e é prefixado aos argumentos especificados pelo usuário. Você o habilita por meio de um sinalizador daemon, dockerd –init, já que é desabilitado por padrão para o backwards compat.

Você também pode replace a opção daemon ou especificá-la em uma base por contêiner com o docker run --init=true|false .

Você pode testar isso executando um processo como o pid 1 em um contêiner e ver o zumbi extra que aparece no contêiner enquanto ele está em execução.

 int main(int argc, char ** argv) { pid_t pid = fork(); if (pid == 0) { pid = fork(); if (pid == 0) { exit(0); } sleep(3); exit(0); } printf("got pid %d and exited\n", pid); sleep(20); } 

O daemon do docker agora tem a opção

 --init 

Executar um init dentro de contêineres para encaminhar sinais e colher processos