Era 23h de uma terça-feira quando uma ligação foi recebida.
O contêiner de um cliente havia sido comprometido.
Um invasor explorou uma vulnerabilidade no aplicativo Node.js, obteve acesso ao shell dentro do contêiner e, como ele estava sendo executado como root com privilégios excessivos, conseguiu acessar o sistema host.
Foram três horas de controle de danos.
Dados de clientes expostos.
Um relatório de incidente a ser redigido.
Tudo isso poderia ter sido evitado.
O problema é que, quando se trata de segurança no Docker, a maior parte das medidas não é complexa — apenas ignorada. As equipes colocam o contêiner em funcionamento, validam que “funciona”, fazem o deploy e a segurança fica para “resolver depois”.
O depois nunca chega… até que algo quebra.
Este guia reúne práticas que deveriam ter sido aplicadas antes daquela terça-feira à noite. Não exige conhecimento profundo em segurança, apenas passos práticos capazes de reduzir drasticamente o risco.
☕
Café com Deus Pai Vol. 6 - 2026: Porções Diárias de Amor
oferece 365 mensagens diárias que convidam você a um encontro íntimo com Deus, fortalecendo a fé e nutrindo a alma.
👉
Confira na Amazon
.
Nas compras você contribui para manter o site no ar.
Por que a segurança no Docker é importante
Existe um equívoco comum de que contêineres são automaticamente seguros. Eles são isolados, certo?
Mais ou menos.
Os contêineres compartilham o kernel do host. Eles não são máquinas virtuais com isolamento completo. Uma vulnerabilidade de escape de contêiner — e elas existem — pode conceder a um invasor acesso ao sistema host e a todos os outros contêineres que rodam nele.
Mesmo sem escapar, um contêiner comprometido pode causar grandes danos:
- Mineração de criptomoedas
- Vazamento de dados
- Movimentação lateral para serviços conectados
- Uso do ambiente para lançar ataques contra outros sistemas
O objetivo do endurecimento de segurança é simples: se algo der errado, limitar o impacto. Dificultar o acesso e, caso alguém consiga entrar, garantir que o estrago possível seja mínimo.
Vamos dividir isso em etapas práticas.
Passo 1: Pare de executar como root
Esta é a mudança mais impactante que você pode fazer.
Por padrão, os processos dentro de contêineres Docker são executados como root. Não como um usuário limitado, mas como o usuário root real (UID 0).
Por que isso importa?
Se um invasor explorar sua aplicação e conseguir execução de código, ele terá acesso root dentro do contêiner. Poderá ler qualquer arquivo, modificar qualquer coisa e, se combinado com outras falhas, possivelmente escapar para o host.
Executar a aplicação como um usuário sem privilégios não impede a exploração inicial, mas reduz drasticamente o que um invasor pode fazer depois.
Como corrigir
Crie um usuário dedicado no Dockerfile e execute a aplicação com ele:
FROM node:20-alpine
WORKDIR /app
# Cria um usuário sem privilégios
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
# Copia os arquivos ajustando o dono
COPY --chown=appuser:appgroup . .
# Instala dependências
RUN npm ci --only=production
# Usa o usuário não root
USER appuser
CMD ["node", "server.js"]
Pontos importantes:
addgroupeaddusercriam grupo e usuário de sistema- A flag
-Scria uma conta sem senha e sem diretório home --chowngarante permissões corretas nos arquivos- A instrução
USERforça todos os processos a rodarem sem privilégios
Algumas aplicações passam a apresentar erros de permissão após essa mudança. Normalmente isso acontece porque tentam escrever em diretórios onde não deveriam. Corrija a aplicação — não remova a segurança.
Verificação rápida
docker run myapp whoami
Se o resultado for root, ainda há trabalho a fazer.
Passo 2: Use imagens base mínimas
Cada pacote instalado no contêiner é uma superfície de ataque em potencial. Mais software significa mais vulnerabilidades, mais CVEs para corrigir e mais caminhos para um invasor.
É comum encontrar contêineres baseados em imagens completas do Ubuntu ou Debian, com centenas de pacotes que a aplicação nunca usa, mas que facilitam a vida de um atacante.
A solução
Use imagens base mínimas.
Alpine Linux:
FROM node:20-alpine
O Alpine é extremamente pequeno (cerca de 5 MB) e atende a maioria das aplicações.
Imagens distroless:
FROM gcr.io/distroless/nodejs20-debian12
Aqui não há shell, gerenciador de pacotes ou ferramentas extras. Mesmo que alguém consiga executar código, não há comandos básicos disponíveis.
Variantes slim:
FROM python:3.12-slim
Uma boa alternativa quando Alpine não é compatível.
Impacto
Uma imagem de mais de 1 GB baseada em Ubuntu frequentemente cai para menos de 100 MB. Menos pacotes, menos vulnerabilidades e uma superfície de ataque muito menor.
Passo 3: Escaneie suas imagens em busca de vulnerabilidades
Sua imagem base tem vulnerabilidades. Suas dependências também. Isso é normal.
O problema é não saber disso antes de um invasor.
Docker Scout
docker scout cves myapp:latest
Mostra vulnerabilidades conhecidas organizadas por gravidade.
Trivy
trivy image myapp:latest
O Trivy verifica:
- Vulnerabilidades do sistema operacional
- Dependências da aplicação
- Erros de configuração
- Segredos acidentalmente incluídos na imagem
Como lidar com os resultados
Na primeira execução, o volume de alertas pode assustar. Priorize:
- Vulnerabilidades críticas e altas
- Pacotes realmente usados pela aplicação
- Falhas com exploração ativa conhecida
Atualize a imagem base e dependências e faça rebuild. Muitas falhas desaparecem apenas com versões atualizadas.
Automatize
Inclua o escaneamento no pipeline de CI e bloqueie deploys inseguros:
trivy image --exit-code 1 --severity CRITICAL myapp:${{ github.sha }}
Isso não é opcional — é higiene básica.
Passo 4: Nunca coloque segredos dentro da imagem
Ainda é comum encontrar senhas, tokens e chaves diretamente no Dockerfile. Isso é extremamente perigoso.
Qualquer pessoa com acesso à imagem pode extrair esses dados. Eles ficam armazenados no histórico da imagem, no registry e em sistemas de CI, mesmo que você os remova depois.
O que não fazer
ENV DATABASE_PASSWORD=supersecretpassword
Forma correta
Passe segredos apenas em tempo de execução ou use gerenciadores de segredos. Nada sensível deve existir dentro da imagem.
Passo 5: Use sistema de arquivos somente leitura
Se um invasor entra no contêiner, uma das primeiras ações é escrever arquivos: malware, backdoors, persistência.
Um sistema de arquivos somente leitura bloqueia isso imediatamente.
docker run --read-only myapp
Para diretórios que precisam ser graváveis, use tmpfs:
docker run --read-only --tmpfs /tmp --tmpfs /app/cache myapp
Isso impede:
- Alteração do código da aplicação
- Persistência de malware
- Modificação de arquivos de configuração
Passo 6: Remova capabilities desnecessárias
Mesmo sem root, contêineres ainda possuem capacidades do Linux além do necessário.
Por padrão, eles podem:
- Alterar dono de arquivos
- Ignorar permissões
- Usar portas privilegiadas
A maioria das aplicações não precisa disso.
docker run --cap-drop=ALL myapp
Adicione apenas o que for realmente necessário:
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE myapp
Nunca use --privileged em produção
docker run --privileged myapp
Isso praticamente desativa o isolamento do contêiner.
Passo 7: Defina limites de recursos
Sem limites, um contêiner pode consumir toda a CPU e memória do host — problema de performance e de segurança.
docker run --memory=512m --memory-swap=512m myapp
docker run --cpus=1.5 myapp
Isso impede ataques de negação de serviço e uso abusivo de recursos.
Passo 8: Isole suas redes
Por padrão, todos os contêineres em uma mesma rede Docker podem se comunicar livremente.
Separe redes por função:
- Frontend → Backend → Database
Assim, se o frontend for comprometido, o banco não fica exposto diretamente.
Passo 9: Use perfis de segurança
Docker suporta mecanismos como seccomp e AppArmor.
Nunca desative:
docker run --security-opt seccomp=unconfined myapp
Ative também:
docker run --security-opt=no-new-privileges:true myapp
Isso impede escalonamento de privilégios.
Passo 10: Ative o Docker Content Trust
export DOCKER_CONTENT_TRUST=1
Garante que apenas imagens assinadas digitalmente sejam utilizadas.
Passo 11: Mantenha tudo atualizado
Docker Engine, imagens base e dependências acumulam vulnerabilidades ao longo do tempo.
Atualize regularmente e use ferramentas como Dependabot ou Renovate.
Exemplo completo de Dockerfile endurecido
FROM node:20.11.1-alpine3.19 AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
FROM node:20.11.1-alpine3.19
RUN apk add --no-cache dumb-init
WORKDIR /app
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules
COPY --from=builder --chown=appuser:appgroup /app/package.json ./
ENV NODE_ENV=production
USER appuser
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD node -e "require('http').get('http://localhost:3000/health', r => process.exit(r.statusCode === 200 ? 0 : 1))"
ENTRYPOINT ["dumb-init", "--"]
CMD ["node", "dist/server.js"]
Checklist de segurança
Antes de ir para produção:
- Usuário não root
- Imagem base mínima
- Nenhum segredo na imagem
- Escaneamento de vulnerabilidades
- Limites de CPU e memória
- Sistema de arquivos protegido
- Capabilities reduzidas
- Redes isoladas
- Dependências atualizadas
O custo real de ignorar segurança
O incidente citado no início custou cerca de US$ 10.000, considerando resposta ao incidente, comunicação com clientes, análise jurídica e correções.
As medidas deste guia? Algumas horas de trabalho.
Segurança não é paranoia. É realismo.
Comece pelo básico: não rodar como root e escanear imagens. Esses dois passos sozinhos já elevam drasticamente o nível de segurança. Depois, evolua gradualmente.
LEIA TAMBÉM:
- Kubernetes explicado – com diagramas que fazem sentido
- Engenharia de Prompt: PASSEF e COSTAR e a Criação de Agentes de IA
- Segurança de IA em 2026: 6 estratégias que sua Equipe Deve Dominar
☕
Café com Deus Pai Vol. 6 - 2026: Porções Diárias de Amor
oferece 365 mensagens diárias que convidam você a um encontro íntimo com Deus, fortalecendo a fé e nutrindo a alma.
👉
Confira na Amazon
.
Nas compras você contribui para manter o site no ar.
