<h2>Segurança em Containers Docker: Rootless, Capabilities e Scanning</h2>
<p>Quando falamos em segurança em containers, é essencial compreender que estamos lidando com um ambiente que compartilha o kernel do host. Isso significa que uma vulnerabilidade em um container pode potencialmente afetar o sistema inteiro. O Docker oferece várias camadas de proteção, e três delas são fundamentais: executar containers sem privilégios root, limitar capabilities do sistema operacional e realizar scanning de vulnerabilidades em imagens. Este artigo aborda cada uma dessas estratégias de forma prática e detalhada.</p>
<h2>Docker Rootless: Executando Containers sem Privilégios Root</h2>
<h3>Entendendo o Problema do Root em Containers</h3>
<p>Por padrão, processos dentro de um container executam como root (UID 0). Isso parecia conveniente historicamente, mas representa um risco significativo. Se um atacante conseguir escapar do container, ele terá acesso root no host. O Docker Rootless é uma abordagem que executa tanto o daemon do Docker quanto os containers com um usuário não-root, criando uma camada adicional de segurança através de user namespaces.</p>
<p>A diferença é fundamental: em um Docker padrão, o usuário root dentro do container é mapeado para o usuário root do host. No Docker Rootless, o usuário root do container é mapeado para um usuário normal (como <code>dockremap</code>) no host, eliminando esse privilégio.</p>
<h3>Instalando e Configurando Docker Rootless</h3>
<p>A instalação do Docker Rootless envolve algumas etapas específicas. Primeiro, desinstalamos a versão padrão (se instalada) e configuramos o ambiente de forma adequada. Veja como fazer isso em um sistema Linux moderno:</p>
<pre><code class="language-bash"># 1. Remover Docker padrão (se necessário)
sudo apt-get remove docker docker-engine docker.io containerd runc
2. Instalar dependências necessárias
sudo apt-get install -y uidmap dbus-user-session
3. Baixar e instalar Docker Rootless
curl https://get.docker.com/builds/Linux/x86_64/docker-latest.tgz | tar xz -C /tmp/
/tmp/docker/dockerd-rootless-setuptool.sh install
4. Ativar o serviço para iniciar automaticamente
systemctl --user enable docker
systemctl --user start docker
5. Verificar instalação
dockerd-rootless-setuptool.sh check</code></pre>
<p>Após a instalação, você deve configurar variáveis de ambiente para usar a instância rootless. Adicione ao seu <code>.bashrc</code> ou <code>.zshrc</code>:</p>
<pre><code class="language-bash">export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock</code></pre>
<h3>Validando o Comportamento Rootless</h3>
<p>Uma maneira simples de validar que seu Docker está realmente em modo rootless é executar um container e verificar o UID do processo. Compare o comportamento entre um docker padrão e rootless:</p>
<pre><code class="language-bash"># Em Docker Rootless
docker run --rm ubuntu id
Saída esperada:
uid=0(root) gid=0(root) groups=0(root)
Mas se você verificar no host:
ps aux | grep "docker run"
O processo estará rodando com UID do usuário não-root</code></pre>
<p>A questão é sutil: dentro do container ele parece ser root (pelo namespace), mas no host real, ele é um usuário normal. Isso oferece proteção significativa contra privilege escalation.</p>
<h2>Capabilities: Controlando Privilégios no Nível do Kernel</h2>
<h3>O que são Capabilities e por que importam</h3>
<p>Linux capabilities dividem os privilégios tradicionais do root em unidades específicas e menores. Ao invés de dar permissão total de root, você pode conceder apenas as capacidades específicas que um processo realmente precisa. Docker, por padrão, mantém um conjunto de capabilities "seguras" e remove outras perigosas.</p>
<p>Um container executando um servidor web nginx, por exemplo, não precisa de <code>CAP_NET_ADMIN</code>, que permite configuração avançada de rede. Não precisa de <code>CAP_SYS_MODULE</code>, que permite carregar módulos do kernel. Ao remover essas capabilities, você reduz drasticamente a superfície de ataque.</p>
<h3>Capabilities Padrão em Docker</h3>
<p>Docker inicia containers com um conjunto padrão de capabilities. Você pode visualizar e modificar esse comportamento. As capabilities padrão incluem permissões básicas para networking e operações de arquivo, mas excluem as mais perigosas:</p>
<pre><code class="language-bash"># Ver capabilities padrão
docker inspect <container_id> | grep -i "cap"
Exemplo de saída esperada:
"CapAdd": [],
"CapDrop": [
"NET_RAW",
"SYS_CHROOT",
"KILL",
"SETFCAP",
"SETPCAP",
"NET_BIND_SERVICE",
"SYS_CHROOT",
"KILL",
"AUDIT_WRITE"
]</code></pre>
<h3>Removendo e Adicionando Capabilities Seletivamente</h3>
<p>A estratégia "least privilege" significa que você deve começar sem capabilities e adicionar apenas as necessárias. Vamos ver um exemplo prático com um Dockerfile que executa um aplicativo específico:</p>
<pre><code class="language-dockerfile">FROM ubuntu:22.04
RUN apt-get update && apt-get install -y curl
Criamos um usuário não-root para executar a aplicação
RUN useradd -m -u 1000 appuser
COPY app.sh /home/appuser/
RUN chmod +x /home/appuser/app.sh
USER appuser
ENTRYPOINT ["/home/appuser/app.sh"]</code></pre>
<p>Agora, ao executar esse container, você pode especificar exatamente quais capabilities são necessárias:</p>
<pre><code class="language-bash"># Executar com ALL capabilities removidas (máxima segurança)
docker run --cap-drop=ALL minha-app
Se o app precisa fazer binding em portas < 1024, adicione apenas CAP_NET_BIND_SERVICE
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE minha-app
Para um servidor web que precisa binding em porta 80
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE --cap-add=CHOWN minha-app</code></pre>
<h3>Exemplo Prático: Servidor Web Seguro</h3>
<p>Vamos criar um exemplo realista de um container nginx com capabilities otimizadas:</p>
<pre><code class="language-bash"># Executar nginx com apenas as capabilities necessárias
docker run -d \
--name nginx-seguro \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
--cap-add=CHOWN \
--cap-add=SETUID \
--cap-add=SETGID \
--read-only \
--tmpfs /var/run \
--tmpfs /var/cache/nginx \
-p 80:80 \
nginx:latest</code></pre>
<p>Cada capability tem um propósito específico:</p>
<ul>
<li><code>NET_BIND_SERVICE</code>: permite fazer bind em portas < 1024</li>
<li><code>CHOWN</code>: permite mudar proprietário de arquivos</li>
<li><code>SETUID/SETGID</code>: permite mudar UID/GID de processos</li>
</ul>
<p>Remover capabilities desnecessárias reduz dramaticamente o potencial de dano se a aplicação for comprometida.</p>
<h2>Scanning de Vulnerabilidades em Imagens Docker</h2>
<h3>Por que Scanning é Essencial</h3>
<p>Uma imagem Docker é uma combinação de múltiplas camadas: a imagem base (como Ubuntu ou Alpine), dependências do sistema operacional e dependências de aplicação. Qualquer uma dessas camadas pode conter vulnerabilidades conhecidas (CVEs - Common Vulnerabilities and Exposures). O scanning verifica essas vulnerabilidades antes de colocar a imagem em produção, evitando deploy de código comprometido.</p>
<p>Existem várias ferramentas disponíveis: Trivy (gratuita, open-source e muito usada), Snyk (comercial com plano gratuito), Docker Scout (integrado ao Docker Desktop), e outras. Vamos focar em Trivy por ser a mais acessível e poderosa.</p>
<h3>Instalando e Usando Trivy</h3>
<p>Trivy é uma ferramenta de scanning leve e rápida. Aqui está como instalá-la e usá-la:</p>
<pre><code class="language-bash"># Instalação no Ubuntu/Debian
sudo apt-get install wget apt-transport-https gnupg lsb-release
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add - echo "deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | sudo tee -a /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install trivy
Verificar instalação
trivy version</code></pre>
<h3>Executando Scans Básicos em Imagens</h3>
<p>Depois de instalado, você pode escanear qualquer imagem Docker. O Trivy verifica vulnerabilidades na imagem, analisando o sistema de arquivos e detectando pacotes vulneráveis:</p>
<pre><code class="language-bash"># Scan simples em uma imagem local
trivy image ubuntu:22.04
Scan com saída em formato JSON (útil para integração)
trivy image --format json ubuntu:22.04 > scan-results.json
Scan com saída em tabela resumida
trivy image --severity HIGH,CRITICAL ubuntu:22.04
Scan de uma imagem que ainda não foi baixada
trivy image --download-db-only
trivy image gcr.io/distroless/python3-debian11</code></pre>
<h3>Exemplo Realista: CI/CD com Scanning</h3>
<p>Em um pipeline de CI/CD (usando Docker, Kubernetes ou qualquer orquestrador), você quer falhar o build se vulnerabilidades críticas forem encontradas. Aqui está um exemplo de script que você pode integrar:</p>
<pre><code class="language-bash"></code></pre>
<h3>Integrando Scanning em Docker Compose</h3>
<p>Se você usa Docker Compose, pode adicionar um estágio de scanning antes de colocar imagens em produção:</p>
<pre><code class="language-yaml">version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
image: minha-app:${VERSION:-latest}
security_opt:
- no-new-privileges:true
cap-drop:
- ALL
cap-add:
- NET_BIND_SERVICE
user: "1000"
read_only: true
tmpfs:
- /tmp
- /var/run
security-check:
image: aquasec/trivy:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./scan-results:/results
command:
- image
- --exit-code
- "1"
- --severity
- HIGH,CRITICAL
- --format
- json
- --output
- /results/scan.json
- minha-app:${VERSION:-latest}
depends_on:
- app</code></pre>
<h2>Boas Práticas Integradas</h2>
<h3>Criando um Container Verdadeiramente Seguro</h3>
<p>Combinar todas essas técnicas resulta em um container muito mais seguro. Aqui está um exemplo completo que integra rootless, capabilities limitadas e scanning:</p>
<pre><code class="language-dockerfile">FROM alpine:3.18
Instalar apenas o necessário
RUN apk add --no-cache python3 py3-pip
Criar usuário não-root
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
Copiar aplicação
COPY app.py .
RUN chown -R appuser:appgroup /app
Rodar como usuário não-root
USER appuser
EXPOSE 8000
Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD python3 -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"
ENTRYPOINT ["python3", "app.py"]</code></pre>
<p>Para executar esse container com máxima segurança:</p>
<pre><code class="language-bash"># Build
docker build -t minha-app-segura .
Escanear antes de usar
trivy image --severity HIGH,CRITICAL minha-app-segura
Rodar com todas as proteções
docker run \
--name app-segura \
--read-only \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
--user appuser \
--tmpfs /tmp \
--tmpfs /run \
--security-opt=no-new-privileges:true \
--memory=256m \
--cpus=0.5 \
--pids-limit=100 \
-p 8000:8000 \
minha-app-segura</code></pre>
<h2>Conclusão</h2>
<p>Aprendemos três pilares fundamentais de segurança em Docker que trabalham juntos para proteger seus containers. <strong>Primeiro, Docker Rootless elimina o risco de privilege escalation ao nível do host</strong>, mapeando o usuário root do container para um usuário normal no sistema operacional. <strong>Segundo, capabilities permitem aplicar o princípio de least privilege de forma granular</strong>, concedendo apenas as permissões específicas que cada aplicação realmente necessita. <strong>Terceiro, scanning com ferramentas como Trivy detecta vulnerabilidades conhecidas em imagens antes da produção</strong>, prevenindo deploys de código comprometido. A combinação dessas três estratégias, aplicadas desde o desenvolvimento até a produção, cria uma postura de segurança robusta e defensável.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://docs.docker.com/engine/security/rootless/" target="_blank" rel="noopener noreferrer">Docker Rootless Documentation</a> - Documentação oficial do Docker sobre Rootless</li>
<li><a href="https://man7.org/linux/man-pages/man7/capabilities.7.html" target="_blank" rel="noopener noreferrer">Linux Capabilities Man Page</a> - Referência completa de capabilities do Linux</li>
<li><a href="https://github.com/aquasecurity/trivy" target="_blank" rel="noopener noreferrer">Trivy GitHub Repository</a> - Ferramenta open-source de scanning de vulnerabilidades</li>
<li><a href="https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html" target="_blank" rel="noopener noreferrer">OWASP Docker Security Cheat Sheet</a> - Guia de segurança Docker da OWASP</li>
<li><a href="https://docs.docker.com/engine/security/" target="_blank" rel="noopener noreferrer">Docker Security Best Practices</a> - Documentação oficial de segurança do Docker</li>
</ul>
<p><!-- FIM --></p>