Hardening Docker: boas práticas para containers mais seguros
Containers herdam os riscos da imagem e da configuração de runtime. Veja como reduzir superfície e privilégio.
Containers prometem isolamento, mas esse isolamento depende de como a imagem foi construída e de como o container roda. Uma imagem inchada cheia de pacotes, um processo executando como root dentro do container ou o docker socket exposto transformam o container de barreira em trampolim. Hardening de Docker é, em essência, reduzir o que está dentro da imagem e reduzir o privilégio em runtime.
Este guia cobre as decisões que mais importam: construir imagens mínimas, executar sem root, gerenciar secrets corretamente, limitar capabilities e manter as bases atualizadas com scan contínuo. São práticas defensivas que diminuem o impacto caso a aplicação dentro do container seja comprometida.
Imagem mínima e usuário não root
Quanto menor a imagem, menor a superfície. Prefira imagens base mínimas e instale apenas o necessário para a aplicação rodar. Cada ferramenta extra dentro do container é uma vulnerabilidade potencial e também uma ferramenta a mais nas mãos de um atacante que consiga executar comandos.
Não rode como root. Crie um usuário sem privilégio e defina-o no Dockerfile, para que o processo principal não tenha poderes administrativos dentro do container. Isso limita bastante o que um comprometimento da aplicação consegue fazer.
RUN addgroup --system app && adduser --system --ingroup app app
USER appCadeia de suprimentos da imagem
A imagem que você executa carrega tudo o que veio da base e das dependências, então a procedência importa tanto quanto o conteúdo. Fixe a imagem base por digest, não apenas por tag: uma tag como latest pode apontar para conteúdos diferentes ao longo do tempo, enquanto o digest garante que o build usa exatamente a imagem que você revisou. Isso torna os builds reproduzíveis e evita que uma base alterada entre sem ninguém perceber.
FROM node:20-slim@sha256:CONTEUDO_DO_DIGESTPrefira bases mínimas de origem confiável e reduza o número de dependências que entram na imagem. Gerar um inventário do que a imagem contém, o chamado SBOM, ajuda a saber rapidamente se um componente vulnerável está presente quando uma nova falha é divulgada. Onde a maturidade permitir, assine as imagens no build e verifique a assinatura antes de promover para produção, de modo que só imagens produzidas pelo seu pipeline cheguem ao ambiente.
Secrets, capabilities e rede
Nunca coloque secrets dentro da imagem nem em variáveis embutidas no Dockerfile, porque eles ficam nas camadas e podem ser extraídos. Use mecanismos de secrets do orquestrador ou injeção em runtime. Em runtime, remova capabilities desnecessárias e evite o modo privilegiado, que praticamente anula o isolamento.
- Rodar como usuário sem privilégio, nunca root
- Descartar capabilities não usadas e evitar privileged
- Definir o sistema de arquivos como somente leitura quando possível
- Limitar recursos (CPU e memória) para conter abuso
- Injetar secrets em runtime, fora da imagem
Isolamento em runtime: seccomp, privilégios e read-only
Além de construir a imagem com cuidado, a forma de executar o container define quanto ele pode fazer se a aplicação for comprometida. Descarte todas as capabilities e adicione de volta apenas as poucas que o processo realmente usa. Ative a flag que impede ganho de privilégio por binários setuid, mantenha o perfil seccomp padrão, que já restringe chamadas de sistema perigosas, e rode com o sistema de arquivos somente leitura, montando um espaço gravável apenas onde a aplicação precisa escrever.
docker run --rm \
--user 10001:10001 \
--read-only --tmpfs /tmp \
--cap-drop ALL \
--security-opt no-new-privileges \
--pids-limit 200 \
minha-imagem:1.2.3Um erro comum é desligar o perfil seccomp para resolver rápido um erro de permissão. Isso abre chamadas de sistema que o container não precisa e amplia o que um comprometimento consegue alcançar. Quando uma chamada legítima é bloqueada, o caminho melhor é um perfil ajustado ao serviço, não a ausência de perfil. Segmente também a rede: containers que não precisam conversar entre si não devem compartilhar a mesma rede sem necessidade.
Scan de imagem e o docker socket
Faça scan de vulnerabilidades nas imagens, idealmente no pipeline, e atualize as bases com regularidade. Uma imagem que era segura há seis meses pode acumular CVEs conhecidas; sem atualização e scan, você empacota vulnerabilidades junto com a aplicação.
Trate o docker socket como credencial de altíssimo privilégio. Montá-lo dentro de um container é equivalente a dar acesso root ao host, porque quem controla o socket controla o daemon. Evite essa montagem; quando for inevitável, isole e restrinja o acesso ao máximo.
Checklist prático
- Usar imagem base mínima e instalar só o necessário
- Definir usuário sem privilégio com USER no Dockerfile
- Descartar capabilities não usadas e evitar modo privilegiado
- Definir filesystem somente leitura quando possível
- Injetar secrets em runtime, nunca dentro da imagem
- Limitar CPU e memória dos containers
- Fazer scan de vulnerabilidades das imagens no pipeline
- Atualizar imagens base com regularidade
- Evitar montar o docker socket dentro de containers
- Fixar versões de base por digest para builds reproduzíveis
- Aplicar --security-opt no-new-privileges nos containers
- Manter o perfil seccomp padrão ativo e nunca usar --privileged
- Rodar com sistema de arquivos somente leitura e tmpfs para diretórios graváveis
- Gerar SBOM e verificar a proveniência e a assinatura das imagens
- Usar multi-stage build para não enviar ferramentas de build à imagem final
Boas práticas
- Reduza a imagem ao mínimo para diminuir superfície e ataque
- Trate o docker socket como acesso root ao host
- Integre scan de imagem ao pipeline de build
- Use multi-stage build para não enviar ferramentas de build à imagem final
- Padronize um Dockerfile base seguro para os times reutilizarem
- Reconstrua imagens periodicamente para herdar correções da base
- Fixe a imagem base por digest e verifique a assinatura antes de promover
- Aplique isolamento de runtime (seccomp, no-new-privileges, read-only) por padrão
Erros comuns
Processo rodando como root no container
Um comprometimento da aplicação ganha privilégio elevado e facilita escape.
Secrets embutidos na imagem
Credenciais ficam nas camadas e podem ser extraídas por quem obtém a imagem.
Montar o docker socket no container
Equivale a conceder acesso root ao host inteiro.
Imagens base nunca atualizadas
A aplicação é empacotada junto com vulnerabilidades conhecidas.
Modo privilegiado por conveniência
Anula o isolamento e abre caminho para comprometer o host.
Desligar o perfil seccomp para evitar um erro de permissão
Abre chamadas de sistema que o container não precisa e amplia o escape possível.
Quando procurar apoio especializado
Definir um padrão seguro de imagens e runtime e integrá-lo ao pipeline é parte do serviço de Hardening da GUARDIASEC, que avalia imagens, configuração de runtime e superfície de contêineres, com recomendações priorizadas por risco.
Perguntas frequentes
Container já não é isolado por padrão?
Containers oferecem isolamento, mas ele é mais fraco que o de uma máquina virtual e depende da configuração. Rodar como root, usar modo privilegiado ou montar o docker socket enfraquece ou anula esse isolamento. Hardening existe justamente para manter a barreira forte e limitar o impacto de um comprometimento.
Por que não posso guardar secrets no Dockerfile?
Porque o Dockerfile gera camadas, e valores embutidos ficam armazenados nessas camadas. Quem obtém a imagem consegue inspecionar o histórico e extrair os segredos, mesmo que eles não apareçam no container em execução. O correto é injetar secrets em runtime, usando os mecanismos do orquestrador.
O que é o risco do docker socket?
O docker socket controla o daemon do Docker, que roda com privilégio de root no host. Quem tem acesso ao socket pode criar containers privilegiados, montar o sistema de arquivos do host e, na prática, assumir a máquina. Por isso montá-lo dentro de um container equivale a entregar o host.
Scan de imagem substitui o hardening?
Não. O scan encontra vulnerabilidades conhecidas nos pacotes da imagem, o que é importante, mas não corrige configuração de runtime, privilégio excessivo ou secrets mal gerenciados. Scan e hardening são complementares: um cuida do conteúdo da imagem, o outro de como ela é construída e executada.
O que é seccomp e o Docker já aplica algum perfil?
Seccomp filtra quais chamadas de sistema um processo pode fazer ao kernel. O Docker aplica um perfil padrão que já bloqueia chamadas perigosas e desnecessárias para a maioria das aplicações, sem que você precise configurar nada. O risco aparece quando alguém desativa esse perfil para contornar um erro, o que amplia a superfície. Quando uma chamada legítima é bloqueada, o ajuste correto é um perfil sob medida, não a ausência de perfil.
Devo referenciar imagens por tag ou por digest?
Por digest para builds de produção. Uma tag como latest ou uma versão pode apontar para conteúdos diferentes ao longo do tempo, então o mesmo Dockerfile pode gerar imagens distintas em momentos distintos. O digest fixa exatamente a imagem que você revisou, o que torna o build reproduzível e evita que uma base alterada entre sem revisão. Tags continuam úteis para leitura humana, mas o que garante a procedência é o digest.
O que faz o no-new-privileges e por que ativar?
A flag no-new-privileges impede que um processo dentro do container ganhe privilégios adicionais durante a execução, por exemplo através de binários setuid. Com ela ativa, mesmo que a aplicação seja comprometida, o atacante não consegue usar esse mecanismo para elevar privilégio dentro do container. É um ajuste de baixo custo que fecha um caminho conhecido de escalonamento e faz sentido como padrão.
Guias relacionados
Próximo passo
Vamos avaliar os riscos do seu ambiente?
Conte seu cenário e definimos juntos o escopo certo. O objetivo é reduzir caminhos prováveis de ataque e elevar a maturidade de segurança, sem promessas absolutas.