O processo no meu container Docker não aceita control+c.. Como resolver?
Você já deve ter passado por isso, em alguns casos, com alguns softwares, quando rodando em um Container Docker parecem não reconhecer corretamente sinais Unix.
Atenção: Nesse artigo, simplificarei a figura de linguagem, então não reclame dizendo “ei, não é bem assim que acontece…”
O Problema:
Toda vez que você pressiona CTRL+C em um processo, um signal unix especial chamado SIGTERM é enviado a esse programa, é uma “forma educada” de se dizer a esse programa que você quer abordar seja lá o que ele estiver fazendo.
Quando você inicia um container o comando especificado (ou o padrãop caso não especificado) irá receber o PID 1, que por convenção, é o processo que segura o container rodando, se esse processo parar, o container também irá.
Até aí tudo bem, nada de anormal, porem o kernel, gerencia de forma especial os sinais enviados aos processos de pid 1, Causando problemas a alguns softwares que não irão atender corretamente os sinais enviados.
Se não entendeu, olha o desenho:
Como Solucionar:
Mais simples do que você imagina… por padrão, quando não especificado um ENTRYPOINT em uma imagem docker, o padrão é /bin/sh -c $argumento.
onde $argumento, é aquilo que você definiu ou sobrescreveu como COMMAND ou CMD.
Uma forma de evitar que o seu processo, que precisa interagir com os sinais unix possa funcionar livremente, é utilizar algum sistema de “init” que irá receber o PID 1, e iniciará o seu processo (como subprocesso?) e automaticamente, encaminhar de forma correta os sinais a que forem enviados.
Entenda o fluxo a seguir:
Mas, vou ter que fazer um script cabuloso pra poder gerenciar os sinas corretamente?
Não jovem gafanhoto, você pode utilizar o tini (https://github.com/krallin/tini) ou o dumb-init (https://github.com/Yelp/dumb-init).
Nos meus testes, o dumb-init funcionou muito bem, porem ele não adicionava interatividade correta quando o processo principal (que agora é um sub processo de init) era um shell (bash ou sh), então vou optar por demonstrar o funcionamento do tini.
Tini é uma forma curta de “tiny init”, ou inicializador pequeno (galera vai me bater por essa tradução porca).
Sei que você já deve estar puto por que esse artigo está imenso já, pra algo “tiny”, então vamos lá, pra bom entendedor meias palavras bastam:
# Adicionando o Tini como entrypointENV TINI_VERSION v0.10.0ADD https://github.com/krallin/tini/releases/download/v0.10.0/tini /tini
RUN chmod +x /tiniENTRYPOINT ["/tini", "--"]
Muito simples né? Mas se você já tem algum comando ou script sendo usado como ENTRYPOINT, só usar o ENTRYPOINT dessa forma aqui
ENTRYPOINT ["/tini", "--", "/mundo/meu-entrypoint-original.sh"]
Pronto, era só isso! Hasta la vista, baby!
P.S. Se quiser entender de verdade como tudo isso funciona, uma explicação que vá alem de gráficos porcos, dê uma lida no readme do dumb-init.
/whoami
Oi, eu sou o Diego Hernandes, sou Co-Fundador do CODECASTS e CTO da Kino Contabilidade Online.
Se você gostou desse artigo, talvez queira me acompanhar em outras redes sociais, como Facebook, Github e Twitter.