Entregue o sinal de parada

DockerBeginner
Pratique Agora

Introdução

A Paper & Pine transforma programas de eventos enfileirados em PDFs reais. Antes de pausar a produção, ela deve concluir o folheto atual de três páginas, deixar o próximo trabalho pendente e preservar o PDF da manhã já concluído. O worker Python fornecido já sabe terminar seu trabalho atual após uma solicitação de parada, mas seu shell de entrada atualmente impede que essa solicitação chegue até ele.

Você deve conhecer caminhos no terminal, Docker básico e logs de contêineres. O pequeno arquivo Compose e o comportamento do shell usados aqui são explicados antes do uso. Não é necessário programar em Python nem ter uma impressora física: o produto é um PDF para download que pode ser decodificado.

Use Workstation e Print Desk. Filas independentes de prática e entrega permitem examinar uma falha controlada sem perder o progresso da entrega. O modo de treinamento pausa após a primeira página renderizada até chegar uma solicitação de parada; depois acrescenta uma pausa informada de 0,5 segundo entre as páginas restantes. Essas pausas tornam a decisão visível, não representam uma avaliação de velocidade de produção. Reserve cerca de 45 minutos para leitura e erros comuns; essa é uma estimativa do autor.

Entregue a solicitação de parada ao worker

Nesta etapa, você observará uma parada de prática com falha, reparará o shell de entrada e concluirá uma entrega real no mesmo worker que recebe sua solicitação de parada.

Comece com um programa real concluído

Comece em Print Desk. Em Delivery attempt, abra Preview text de Morning welcome handout e selecione Download PDF. A prévia é decodificada desse PDF salvo de duas páginas, não reconstruída a partir do texto de origem. Volte com Back to Print Desk. O folheto atual Community open day handout está pendente; Volunteer notes deve permanecer pendente após esta entrega.

O painel separa prática e entrega e começa com apenas os folhetos anteriores disponíveis:

Print Desk antes da produção do folheto atual

A coluna Practice attempt é uma cópia separada da fila de treinamento, não uma segunda máquina. Cada coluna tem sua própria saída e estado do worker. Um PDF atual só fica disponível para download depois que o documento inteiro é finalizado. Renderizar internamente a página 1 ainda não produz um arquivo PDF completo.

Observe por que uma parada de prática falha

Mude para Workstation, que inicia em /home/labex/project/print-signal. cd volta para lá e cat lê um arquivo:

cd /home/labex/project/print-signal
cat compose.trial.yaml

O Compose agrupa configurações em services.worker. Sua imagem preparada contém o worker e as bibliotecas PDF. user já corresponde aos IDs numéricos reais da sua conta, para que a saída continue editável; não substitua esses valores. O /input somente de leitura contém os trabalhos originais, /work é o estado/saída gravável desta tentativa, e /entry.sh é seu script de entrada somente de leitura. :ro significa somente leitura. entrypoint: ["/bin/sh", "/entry.sh"] inicia esse shell diretamente como processo 1 do contêiner, chamado PID 1. Um contêiner compartilha o kernel da VM, mas tem sua própria visão dos processos.

stop_grace_period: 10s dá à aplicação uma janela finita de dez segundos para encerrar. O Docker primeiro envia SIGTERM, a solicitação normal de término. Quando o período de tolerância termina, ele pode enviar SIGKILL, que encerra os processos à força e não pode ser tratado para terminar o trabalho. Enviar um sinal ao PID 1 não o encaminha automaticamente a todos os filhos.

A entrada de prática existente inicia Python como filho em segundo plano com &, depois wait aguarda por ele. O shell permanece PID 1. Leia esse script fornecido:

cat trial-entry.sh

O shell não tem um tratador de encaminhamento. O PID 1 de um contêiner tem um comportamento padrão especial para sinais; assim, esse shell pode continuar vivo enquanto Python nunca recebe a solicitação TERM.

Inicie somente o projeto de prática. -f seleciona seu arquivo, -p agrupa seus recursos, up -d o inicia em segundo plano, e as últimas opções usam imagens preparadas sem pulls nem builds:

docker compose -f compose.trial.yaml -p print-trial up -d --pull never --no-build

Mude para Print Desk, recarregue e aguarde até Practice attempt mostrar Training pause after page 1; waiting for stop request. O worker realmente renderizou a página 1 e está aguardando deliberadamente. Não há uma janela estreita de tempo.

Mude para Workstation. docker exec executa um comando em um contêiner existente. O Linux expõe informações de processos em /proc; /proc/1/comm dentro deste contêiner nomeia seu comando PID 1. Esta observação somente de leitura deve mostrar sh:

docker exec print-trial cat /proc/1/comm

stop solicita que esse serviço pare usando seu período de tolerância configurado:

docker compose -f compose.trial.yaml -p print-trial stop worker

O próprio comando stop pode encerrar com 0 mesmo quando o worker foi morto à força: significa que o Docker tratou a operação de parada, não que o programa do evento terminou. docker inspect lê o contêiner mantido. O modelo entre aspas simples seleciona o código de saída do worker:

docker inspect print-trial --format '{{.State.ExitCode}}'
docker logs print-trial

Espere código de saída 137 e nenhum evento stop-received ou completed do worker. Neste teste controlado, o período de tolerância expirou e o Docker forçou a parada; 137 sozinho não é um diagnóstico geral de toda falha de contêiner. O log contém um evento JSON por linha: event nomeia a observação, job identifica o programa do evento e page registra o progresso real de renderização.

Mude para Print Desk e recarregue. A prática não tem PDF atual finalizado, enquanto seu folheto anterior e a fila de entrega intacta continuam disponíveis.

Substitua o shell pelo worker

Mude para Workstation. Edite somente o entry.sh da entrega, mantendo intactos trial-entry.sh, a entrada do programa do evento, os PDFs existentes e as demais configurações. O exec do shell substitui o processo shell atual pelo programa nomeado. Assim, Python torna-se PID 1 e seu tratador TERM fornecido recebe a solicitação do Docker.

Este here-document literal grava o script curto completo. > substitui entry.sh; o marcador SH entre aspas impede expansões do shell até a linha de fechamento. O arquivo não precisa de permissão de execução porque o /bin/sh configurado o lê:

cat > entry.sh <<'SH'
#!/bin/sh
exec python3 -B /app/worker.py
SH
cat entry.sh

Inicie o projeto independente de entrega, cujo período de tolerância de dez segundos já é suficiente para este folheto de três páginas:

docker compose -p print-delivery up -d --pull never --no-build

Mude para Print Desk, recarregue e aguarde a mensagem de pausa de treinamento em Delivery attempt. Volte para Workstation e leia PID 1 novamente:

docker exec print-delivery cat /proc/1/comm

Espere python3, em vez do shell que aguarda. Solicite uma parada normal:

docker compose -p print-delivery stop worker
docker inspect print-delivery --format '{{.State.ExitCode}}'
docker logs print-delivery

Espere código de saída 0. O mesmo worker registra stop-received, os eventos restantes page-completed, completed para o programa atual e worker-stopped. Um novo processo que depois preenchesse o PDF ausente não comprovaria que este worker terminou seu trabalho antes de parar.

Examine o arquivo entregue e a fila preservada

Mude para Print Desk, recarregue e abra Preview text do folheto atual em Delivery attempt. As três páginas decodificadas, seus títulos de seção, o ID do programa e os números de página devem estar presentes. Baixe o PDF real e abra-o. Volte ao painel: Morning welcome handout ainda deve ter suas duas páginas originais, e Volunteer notes deve permanecer pendente sem PDF gerado. Mantenha o contêiner print-delivery, encerrado normalmente, para sua evidência de inspeção nativa.

Se um nome estiver digitado incorretamente, leia o erro e use o nome de contêiner indicado; por exemplo, docker logs print-workr não encontra esta entrega, enquanto o docker logs print-delivery mostrado a lê. Não crie um PDF substituto à mão. As verificações leem os fatos reais da parada e decodificam todas as páginas, depois reproduzem sua entrada salva em um cenário de programa isolado sem alterar o progresso real.

Recupere uma entrega sem sucesso

Se sua tentativa de entrega falhar, mantenha o contêiner parado por tempo suficiente para ler seus logs e status de saída. Corrija somente a configuração de entrada ou do período de tolerância. A ação de recuperação fornecida recusa um contêiner em execução ou concluído com sucesso; para um worker parado do curso sem sucesso, ela recoloca apenas o trabalho atual na fila e mantém os artefatos com falha em delivery/attempt-history/. Ela preserva o PDF anterior, as entradas originais e o trabalho posterior pendente:

python3 /opt/labex/dk05/source/retry.py

Após essa recuperação explícita, remova somente os contêineres do projeto de entrega com falha usando docker compose -p print-delivery down e repita a sequência mostrada de início da entrega, espera pela pausa e parada. Nenhum PDF de origem é regenerado, e essa recuperação nunca é executada por uma aba ou verificação de pontuação. Não redefina a VM nem altere o JSON da fila para esconder uma tentativa com falha.

Resumo

Você viu como um shell PID 1 em espera pode ocultar uma solicitação de parada de seu filho e depois usou exec para permitir que o worker fornecido recebesse TERM diretamente. O worker de entrega original terminou seu PDF de três páginas, encerrou normalmente, preservou o documento da manhã e deixou o próximo trabalho pendente.