DevOps e CloudDocker em produção: boas práticas que evitam indisponibilidade
Docker em produção exige imagens confiáveis, controle de recursos, healthchecks, backups restauráveis e deploys seguros. Veja como priorizar essas medidas e reconhecer os limites de uma infraestrutura em servidor único.
Como reduzir falhas em sites e aplicações com imagens confiáveis, recursos controlados, monitoramento, deploy seguro e recuperação testada.
Executar Docker em produção exige mais do que colocar uma aplicação dentro de um container. A disponibilidade depende também do servidor, das configurações, do banco de dados e da capacidade de detectar e corrigir problemas.
Um site pode ficar fora do ar mesmo com todos os containers em execução. Basta que a aplicação deixe de responder, o disco fique cheio ou uma integração mantenha requisições presas por tempo demais.
Para sites empresariais, lojas virtuais e aplicações de empresas em Recife, a prioridade deve acompanhar o impacto da falha: quais funções precisam continuar disponíveis, quanto tempo a recuperação pode levar e quais dados não podem ser perdidos. As boas práticas a seguir ajudam a transformar essas necessidades em decisões operacionais.
Entenda o que causa indisponibilidade no Docker em produção
Containers organizam a execução dos serviços, mas não eliminam falhas de código, banco de dados, rede ou infraestrutura. Antes de escolher ferramentas, identifique os componentes necessários para atender uma requisição.
Considere um site com proxy reverso, aplicação e banco de dados. Se o proxy falhar, o visitante pode perder o acesso público. Se a aplicação travar, o proxy continuará ativo, mas poderá devolver erros. Se o banco parar, páginas que dependem dele deixarão de funcionar.
Se todos esses componentes estiverem no mesmo servidor, a perda desse servidor interromperá o conjunto. Ter vários containers nessa máquina não remove esse ponto único de falha.
Defina prioridades pela consequência da falha
Liste os serviços críticos, o tempo aceitável de interrupção e a perda tolerável de dados. Um formulário de contato e um checkout podem exigir estratégias diferentes, mesmo quando pertencem ao mesmo site.
Sobrecarga também deve entrar no diagnóstico. Quando consultas repetidas pressionam o banco, estratégias de cache com Redis podem ajudar a reduzir esse trabalho. O cache, porém, precisa de regras de atualização e de um comportamento definido caso fique indisponível.
Recuperação automática e alta disponibilidade são objetivos distintos. Reiniciar um processo pode reduzir a duração de uma falha. Continuar atendendo durante a perda de um servidor exige uma arquitetura preparada para isso.
Crie imagens reproduzíveis e execute containers com privilégios mínimos
Uma implantação confiável começa com um artefato identificável. Fixe versões de dependências e registre qual imagem corresponde a cada versão publicada. Evite usar apenas a tag latest como referência de produção, pois ela não identifica de forma estável o conteúdo implantado.
Uma tag baseada no commit facilita o rastreamento, desde que não seja sobrescrita. A referência por digest identifica o conteúdo da imagem. Em ambos os casos, mantenha um processo para incorporar atualizações: fixar uma versão não significa deixá-la sem manutenção.
Use builds multi-stage quando fizer sentido separar compilação e execução. Assim, ferramentas necessárias para construir a aplicação podem ficar fora da imagem final, reduzindo componentes desnecessários.
Promova o mesmo artefato entre ambientes
Um pipeline pode construir a imagem, executar verificações, analisar vulnerabilidades e disponibilizá-la em homologação. Depois da validação, promova essa mesma imagem para produção. Reconstruí-la nessa etapa pode introduzir diferenças caso alguma dependência tenha mudado.
Na execução, use um usuário sem privilégios sempre que a aplicação permitir. Evite o modo privilegiado, reduza permissões adicionais e não exponha o socket Docker à aplicação sem uma necessidade avaliada. Esse acesso pode permitir controle amplo sobre o ambiente.
Atualize imagens por um processo validado, com testes proporcionais à mudança e possibilidade de recuperação. Uma imagem menor ou aprovada por um scanner não dispensa os demais controles de segurança em containers.
Separe configurações, proteja secrets e restrinja a rede
A imagem deve conter a aplicação, enquanto as configurações específicas de cada ambiente devem ser fornecidas na execução. Senhas, tokens e chaves privadas não devem entrar no repositório nem nas camadas da imagem.
Escolha um mecanismo de secrets compatível com a infraestrutura e controle quem pode ler, distribuir e alterar esses valores. Variáveis de ambiente podem ser úteis para configuração, mas não devem ser tratadas como proteção suficiente para credenciais.
Também avalie os arquivos que fornecem os secrets, suas permissões e as cópias existentes. O simples uso de um recurso chamado secret não garante proteção completa do armazenamento e da distribuição.
Valide a configuração antes de atender tráfego
A aplicação deve verificar parâmetros obrigatórios na inicialização. Uma configuração ausente precisa produzir um erro claro, sem revelar valores sensíveis nos logs. Isso evita descobrir uma falha somente quando o primeiro cliente usa determinada funcionalidade.
Em uma arquitetura comum, apenas o proxy reverso publica as portas de entrada. Aplicação e banco se comunicam pelas redes internas necessárias, sem exposição pública desnecessária do banco.
Complete essa configuração com controles de acesso do servidor e regras de rede verificadas no ambiente real. Planeje também a rotação de credenciais e a renovação de certificados TLS, com alertas antes do vencimento.
Controle CPU, memória, disco e crescimento dos logs
Sem controle de recursos, um serviço pode prejudicar os demais containers e o próprio servidor. Meça o consumo em operação normal e sob carga antes de estabelecer limites de CPU e memória.
Um limite de memória baixo demais pode provocar encerramentos por falta de memória. Um limite de CPU inadequado pode aumentar a latência. A configuração precisa considerar o comportamento da aplicação e reservar capacidade para o sistema operacional, o Docker e os serviços auxiliares.
Depois de definir os limites, confirme que foram aplicados pelo mecanismo de implantação utilizado. Não considere a presença de um valor no arquivo de configuração como prova suficiente: inspecione o container e observe seu comportamento.
Trate disco e logs como recursos finitos
Configure rotação de logs conforme o driver utilizado. Verifique se o serviço precisa ser recriado para receber a nova configuração e estabeleça retenção compatível com o diagnóstico de incidentes.
Monitore espaço disponível, inodes e crescimento de imagens, volumes e arquivos temporários. O servidor pode ficar sem capacidade de criar arquivos mesmo quando ainda há espaço em bytes.
Por exemplo, um container cujo uso de memória cresce continuamente exige investigação de retenção de objetos ou carga excessiva. Já um log que ocupa o disco exige controle de volume e retenção. Reiniciar a aplicação não resolve, por si só, nenhuma dessas causas.
Evite limpezas automáticas indiscriminadas. Antes de remover imagens ou volumes, confirme o que é necessário para dados persistentes, versões anteriores e recuperação.
Combine healthchecks, políticas de reinício e encerramento seguro
Um processo em execução não comprova que a aplicação atende requisições. O healthcheck Docker permite executar uma verificação periódica e registrar o estado de saúde do container.
No Docker Engine, um healthcheck que falha pode marcar o container como unhealthy sem reiniciá-lo automaticamente. As políticas de reinício atuam sobre a saída do processo, conforme a política configurada. Para tratar uma aplicação travada cujo processo continua ativo, é necessária uma ação adicional integrada à operação.
Separe detecção, recuperação e encaminhamento de tráfego
- Atividade: verifica se a aplicação está funcionando e consegue progredir.
- Prontidão: verifica se a instância pode receber tráfego naquele momento.
- Reinício: recupera o processo nas condições previstas pela política ou pela plataforma.
- Controle de tráfego: direciona requisições para instâncias aptas por meio do proxy, balanceador ou orquestrador.
Quando a plataforma permitir, configure atividade e prontidão separadamente. Evite que uma falha compartilhada, como a indisponibilidade do banco, provoque reinícios contínuos de todas as instâncias sem resolver a causa.
Ajuste intervalos, timeouts, número de falhas toleradas e período de inicialização ao serviço. Uma aplicação que demora para aquecer caches precisa de uma tolerância diferente de um serviço que inicia rapidamente.
Para encerrar, a aplicação deve tratar SIGTERM, concluir requisições em andamento dentro de um prazo e fechar conexões. Configure tempo suficiente antes do encerramento forçado e valide que o processo recebe o sinal.
Compare duas situações: se o processo termina, uma política de reinício pode atuar; se permanece ativo sem responder, o healthcheck pode detectar a falha. Retirar essa instância do tráfego depende da integração configurada.
Prepare a aplicação para falhas nas dependências
Iniciar o banco antes da aplicação não garante que ele esteja pronto para aceitar conexões. No Compose, dependências condicionadas à saúde ajudam a controlar a inicialização, mas não resolvem todas as falhas que surgem depois.
A aplicação precisa lidar com perdas de conexão, lentidão e respostas inesperadas durante toda a operação. Defina timeouts para conexões e chamadas externas, evitando que uma dependência retenha recursos indefinidamente.
Use retries com limite quando a operação permitir. Combine intervalos progressivos, conhecidos como backoff, com uma variação aleatória, chamada jitter, para reduzir tentativas simultâneas de muitos clientes.
Não repita automaticamente operações com efeitos colaterais sem proteção adequada. Uma chamada de pagamento que excedeu o timeout pode ter sido concluída no destino. Mecanismos de idempotência ajudam a evitar duplicações.
Mantenha disponíveis as funções independentes
Se a API de atendimento de um site institucional parar, as páginas de serviços podem continuar acessíveis. O formulário afetado deve encerrar a tentativa em prazo definido e apresentar uma mensagem clara, sem confirmar um envio que não ocorreu.
Essa degradação controlada depende de separar funcionalidades e evitar que uma integração opcional bloqueie toda a aplicação. Filas, limites de concorrência e interrupção temporária de chamadas podem ser úteis conforme o fluxo.
Proteja dados persistentes e teste a restauração dos backups
Containers devem poder ser substituídos sem destruir dados necessários. Bancos, uploads e outros arquivos persistentes precisam de armazenamento planejado para sobreviver à recriação do serviço.
Volumes não substituem backups. Um volume pode ser perdido junto com o servidor, sofrer corrupção ou receber uma exclusão indevida. A estratégia de recuperação precisa incluir cópias protegidas fora do ambiente de produção.
Para bancos de dados, use métodos compatíveis com a tecnologia e com a consistência exigida. Copiar arquivos de um banco em execução sem um procedimento adequado pode produzir uma cópia inutilizável.
Defina perda aceitável e tempo de recuperação
O RPO expressa a perda de dados tolerável, medida em tempo. O RTO expressa o tempo desejado para recuperar o serviço. Esses objetivos orientam frequência de backup, retenção, arquitetura e procedimentos.
Se um projeto admitir perder no máximo uma hora de registros, uma cópia diária isolada não atende ao objetivo. Se precisar voltar rapidamente, será necessário medir também o tempo de preparar a infraestrutura, transferir dados e validar a aplicação.
Teste a restauração em ambiente isolado. Para um site com banco e uploads, recupere ambos e verifique se os registros apontam para arquivos existentes. Considere a consistência entre essas cópias.
Registre duração, etapas, responsáveis e requisitos de acesso. Inclua configurações necessárias à retomada, proteja credenciais e monitore falhas de backup. Uma execução concluída com sucesso não comprova que a restauração funciona.
Monitore a experiência real do usuário e crie alertas acionáveis
O monitoramento de containers deve ser combinado com verificações da aplicação e do acesso público. CPU normal e processos ativos não comprovam que o visitante consegue abrir o site ou concluir uma operação.
Acompanhe erros, latência, tráfego e saturação. Use verificações externas para observar o serviço pela perspectiva do usuário, incluindo, quando necessário, uma jornada representativa além da página inicial.
Monitore também reinícios, encerramentos por falta de memória, disco disponível, validade de certificados e falhas de backup. Centralize logs relevantes e evite registrar senhas, tokens ou dados pessoais desnecessários.
Faça cada alerta apontar para uma ação
Um alerta precisa informar o serviço afetado, o sintoma, o período observado e o responsável. Inclua um procedimento de diagnóstico acessível mesmo quando o sistema principal estiver indisponível.
Por exemplo, um aumento persistente de respostas 5xx pode ser acompanhado por falha na verificação externa. O procedimento deve orientar a consultar logs, verificar dependências e identificar se o problema começou após um deploy.
Ajuste os critérios para reduzir ruído sem esconder falhas relevantes. Quando todos os eventos geram avisos iguais, a equipe perde capacidade de reconhecer o que exige intervenção imediata.
Faça deploys graduais e mantenha um rollback viável
Um deploy sem indisponibilidade depende da infraestrutura e do comportamento da aplicação. É preciso validar a nova versão, manter capacidade durante a transição e enviar tráfego somente para instâncias prontas.
Em um rolling update, instâncias são substituídas gradualmente. Em blue-green, a nova versão fica em um ambiente separado antes da troca de tráfego. Ambas as estratégias exigem cuidado com sessões, tarefas em segundo plano e dados compartilhados.
Planeje a coexistência das versões
As alterações de banco precisam funcionar com as versões que estarão ativas durante a troca. Uma abordagem possível é adicionar a nova estrutura, adaptar a aplicação e remover elementos antigos somente quando deixarem de ser necessários.
O planejamento de migrations de banco de dados deve considerar essa compatibilidade. Reverter a imagem não desfaz automaticamente uma alteração de esquema nem recupera dados removidos.
Em um exemplo blue-green, publique a nova versão, execute verificações essenciais e confirme sua prontidão. Depois, transfira o tráfego e drene conexões do ambiente anterior antes de encerrá-lo.
Preserve a versão anterior pelo período definido para observação. O retorno só será viável se ela continuar compatível com o banco, as configurações e os serviços dependentes.
Defina antecipadamente os critérios para interromper a implantação: erros persistentes, falha em uma jornada crítica ou degradação acima do limite acordado. Documente quem decide o retorno e como executá-lo.
Avalie os limites do Docker Compose e a necessidade de alta disponibilidade
Docker Compose em produção pode atender uma operação em servidor único quando os limites são conhecidos e existe um processo de manutenção e recuperação. A escolha deve acompanhar a criticidade do serviço e a capacidade da equipe.
Várias réplicas no mesmo servidor podem ajudar em determinados cenários de processo ou atualização, mas não protegem contra a perda da máquina. Alta disponibilidade exige avaliar também balanceador, banco, armazenamento e rede.
Orquestradores podem automatizar distribuição e recuperação de workloads. Ainda assim, exigem configuração, monitoramento e conhecimento operacional. A aplicação e os dados também precisam suportar a arquitetura escolhida.
Serviços gerenciados podem reduzir parte do trabalho, conforme o serviço contratado e suas responsabilidades. Avalie custo, complexidade e objetivos de recuperação antes de ampliar a infraestrutura.
Um site institucional pode aceitar recuperação documentada em outro servidor. Já uma aplicação de vendas que precisa continuar atendendo durante a falha de um nó exige redundância dos componentes críticos e testes desse cenário.
Use um checklist operacional antes de colocar Docker em produção
Transforme as recomendações em critérios verificáveis. Para cada item, registre evidência, responsável e pendências. Marcar uma opção sem testar o comportamento esperado não comprova prontidão.
Antes da publicação
- Imagem: versão identificada, artefato validado e referência anterior disponível.
- Configuração e acesso: parâmetros obrigatórios verificados, secrets protegidos e portas expostas revisadas.
- Recursos: limites aplicados, capacidade disponível e rotação de logs confirmada.
- Saúde e recuperação: healthchecks exercitados, política de reinício conferida e encerramento seguro testado.
- Dependências: timeouts definidos, retries limitados e operações com efeitos colaterais protegidas.
- Dados: restauração demonstrada e objetivos de perda de dados e tempo de recuperação registrados.
- Monitoramento: verificação externa ativa, alertas validados e responsáveis definidos.
- Deploy: procedimento ensaiado, compatibilidade do banco avaliada e condições de rollback documentadas.
Durante a operação
Mantenha uma rotina de atualização do host, do Docker e das imagens, com validação e janela adequada ao serviço. Revise capacidade, retenção de logs, validade de certificados e permissões de acesso.
Repita testes de recuperação conforme a criticidade e após mudanças relevantes. Use incidentes para melhorar os procedimentos: o que atrasou o diagnóstico, qual alerta faltou e quais etapas de recuperação precisam ser simplificadas?
Operar Docker em produção com confiabilidade significa construir um ciclo contínuo de prevenção, detecção e recuperação. Comece pelos riscos de maior impacto e só considere uma medida concluída quando houver evidência de que funciona.
Seu site ou aplicação precisa de uma operação mais confiável? Entre em contato com a Codephix para conversar sobre seu projeto de criação de sites em Recife e os requisitos de publicação, manutenção e disponibilidade.
