Blog

Fortalecimento de Contêineres Docker para Hospedagem Multi-Inquilino: Um Guia de Isolamento Passo a Passo

Aprenda a proteger contêineres Docker para ambientes multi-inquilino com medidas práticas de segurança, como usuários não-root, capacidades removidas, sistemas de arquivos somente leitura e isolamento de rede.

Resumo

Executar uma plataforma de hospedagem Docker multi-inquilino exige um isolamento hermético de contêineres para evitar que inquilinos interfiram entre si ou escapem para o host. Este guia fornece um processo concreto de fortalecimento passo a passo que você pode aplicar hoje. Você aprenderá a configurar usuários não-root, remover capacidades Linux desnecessárias, montar sistemas de arquivos como somente leitura, aplicar limites de recursos via cgroups, segmentar redes e usar perfis seccomp ou AppArmor. Também abordaremos quando complementar contêineres com máquinas virtuais para máxima segurança. Ao final, você terá uma lista de verificação para eliminar sistematicamente vetores comuns de escape de contêineres e manter sua infraestrutura multi-inquilino verdadeiramente isolada.

O Problema Real com Contêineres Multi-Inquilino

Contêineres Docker compartilham o kernel do host e, se o isolamento estiver mal configurado, um inquilino pode teoricamente acessar dados de outro, consumir toda a CPU ou até mesmo escapar para o host. Como provedor de hospedagem, você precisa de limites herméticos sem sacrificar os benefícios de desempenho dos contêineres. Muitas equipes começam com as configurações padrão do Docker, que são projetadas para desenvolvimento, não para produção multi-inquilino. A boa notícia: com uma lista de verificação sistemática de fortalecimento, você pode bloquear cada contêiner a níveis de isolamento próximos a VMs, mantendo a velocidade do Docker.

Este artigo percorre cada etapa de fortalecimento com exemplos práticos e ressalvas. Ao final, você terá um processo repetível para implantar contêineres multi-inquilino seguros.

Passo 1: Executar Contêineres como Não-Root

Por padrão, contêineres Docker são executados como root. Se um contêiner for comprometido, o invasor ganha privilégios de root dentro do contêiner e pode tentar um escape. Primeiro, crie um usuário dedicado em seu Dockerfile e mude para ele:

FROM ubuntu:22.04
RUN useradd -m appuser
USER appuser

Ressalva: Alguns processos (ex.: vinculação a portas < 1024) exigem root. Nesses casos, use a flag --cap-add para conceder apenas a capacidade necessária, como --cap-add=NET_BIND_SERVICE, e ainda execute o processo sob um usuário não-root.

Para mais sobre isolamento fundamental, veja nosso guia sobre alcançando isolamento multi-inquilino verdadeiro no Docker.

Passo 2: Remover Todas as Capacidades Linux e Adicionar Apenas o Necessário

As capacidades Linux dividem os privilégios de root em pequenas unidades. Contêineres Docker vêm com um conjunto padrão de capacidades que são muito permissivas para hospedagem multi-inquilino. Remova todas e adicione apenas o que sua aplicação requer:

docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE my-app

Capacidades comuns a evitar: SYS_ADMIN (escape de contêiner), NET_RAW (sniffing de pacotes), SYS_PTRACE (depuração de processos). Use docker run com --security-opt no-new-privileges para evitar escalonamento de privilégios via binários setuid.

Passo 3: Montar o Sistema de Arquivos Raiz como Somente Leitura

Invasores frequentemente escrevem scripts maliciosos no sistema de arquivos do contêiner. Tornando o sistema de arquivos raiz somente leitura, você impede isso:

docker run --read-only --tmpfs /tmp:rw,noexec,nosuid,size=64m my-app

--tmpfs cria uma montagem temporária gravável para diretórios como /tmp e /var/run. A flag noexec impede a execução a partir dessa montagem. Essa abordagem força os invasores a passar por diretórios graváveis, que você pode monitorar.

Passo 4: Aplicar Limites de Recursos com cgroups

Contêineres sem limites podem realizar ataques de negação de serviço ao exaurir memória ou CPU do host. Use restrições de tempo de execução do Docker:

docker run --memory=512m --memory-swap=512m --cpus=0.5 --pids-limit=100 my-app
  • --memory e --memory-swap definem limites rígidos (sem swap).
  • --cpus limita CPU.
  • --pids-limit evita bombas de fork ao limitar o número de processos.

Ressalva: Os limites de recursos são aplicados por cgroups, mas não impedem a exfiltração de dados via rede. Combine com isolamento de rede (próximo passo).

Passo 5: Segmentar Redes com Redes Personalizadas do Docker

Por padrão, contêineres Docker compartilham uma rede bridge. Em uma configuração multi-inquilino, você deve isolar a pilha de rede de cada inquilino. Crie uma rede dedicada por inquilino:

docker network create tenant-alpha --internal
docker run --network tenant-alpha my-app

Use a flag --internal para bloquear o acesso à internet de saída e, em seguida, exponha apenas as portas necessárias via -p. Para segmentação de rede mais avançada, considere protegendo aplicativos web com isolamento Docker.

Ressalva: Redes internas impedem a comunicação direta contêiner a contêiner entre inquilinos, mas vazamentos de DNS ainda podem ocorrer se você usar rede do host. Mantenha-se em redes bridge ou overlay.

Passo 6: Aplicar Perfis Seccomp e AppArmor

Seccomp filtra chamadas de sistema, e AppArmor (ou SELinux) aplica controles de acesso obrigatórios. O Docker fornece um perfil seccomp padrão que bloqueia chamadas de sistema perigosas como clone com certas flags. Para isolamento mais estrito, crie um perfil personalizado:

docker run --security-opt seccomp=./custom.json --security-opt apparmor=docker-default my-app

Você pode gerar um perfil base com docker run --rm -it --security-opt seccomp=unconfined my-app strace -c -S time e depois reduzir. Ressalva: Perfis excessivamente restritivos podem quebrar funcionalidades legítimas. Teste completamente em ambiente de homologação.

Passo 7: Considerar Isolamento Híbrido com Máquinas Virtuais

Se seus inquilinos exigirem isolamento absoluto (ex.: indústria regulamentada), execute contêineres dentro de uma VM leve. Ferramentas como Sysbox ou Kata Containers fornecem separação em nível de hardware sem sacrificar a velocidade do contêiner. Essa é a abordagem usada pelo Enhanced Container Isolation (ECI) do Docker. Embora a sobrecarga seja maior que a de contêineres simples, é muito menor que a de VMs completas por carga de trabalho.

Para mais informações sobre como escolher o nível de isolamento certo, leia projetando uma arquitetura Docker multi-inquilino.

Juntando Tudo: Uma Lista de Verificação de Fortalecimento

  1. Construa contêineres com usuário não-root.
  2. Remova todas as capacidades, adicione apenas as necessárias.
  3. Monte o sistema de arquivos como somente leitura com montagens temporárias graváveis.
  4. Defina limites de memória, CPU e PID.
  5. Crie redes Docker isoladas por inquilino.
  6. Aplique perfis seccomp e AppArmor personalizados.
  7. Avalie contêineres híbridos com VM para necessidades de alta segurança.

Conclusão

O fortalecimento de contêineres não é uma tarefa única—é uma disciplina contínua. Os passos acima formam uma linha de base de segurança para hospedagem multi-inquilino. Lembre-se de que nenhuma medida isolada garante segurança; a defesa em profundidade é fundamental. Comece com o básico: usuários não-root e capacidades removidas. Em seguida, adicione camadas de limites de recursos e segmentação de rede. Para as cargas de trabalho mais sensíveis, combine contêineres com VMs. Com este guia, você pode implantar com confiança ambientes Docker multi-inquilino que são eficientes e seguros.

Sources (5)