10 práticas recomendadas de segurança do Docker
8 de janeiro de 2025
0 minutos de leituraPrincipais aspectos da segurança do Docker
A segurança do Docker abrange aspectos de criação, execução e orquestração de contêineres Docker. Isso inclui a segurança do Dockerfile e das imagens base do Docker, além dos aspectos de segurança dos contêineres em tempo de execução, como privilégios de usuário, daemon do Docker, controles adequados de CPU para um contêiner e outras preocupações relacionadas à orquestração de contêineres Docker em escala.
O cenário de segurança dos contêineres Docker se divide em quatro problemas principais:
Segurança e práticas recomendadas para Dockerfiles
Segurança de contêineres Docker em tempo de execução
Riscos à segurança da cadeia de suprimentos no Docker Hub e seu impacto nas imagens de contêineres Docker
Aspectos de segurança da orquestração de contêineres nativos da nuvem relacionados ao Kubernetes e ao Helm

Segurança de contêineres para DevSecOps
Encontre e corrija vulnerabilidades em contêineres gratuitamente com a Snyk.
10 práticas recomendadas de segurança do Docker
1. Prefira imagens base mínimas
Um problema comum de segurança em contêineres Docker é acabar com imagens grandes. Em geral, quanto mais software houver no contêiner, maior será a superfície de ataque potencial. Por isso, o princípio deve ser incluir apenas o mínimo necessário para executar sua aplicação. O caminho mais simples costuma ser usar uma imagem genérica de contêiner Docker para começar rapidamente. Pode ser uma imagem de sistema operacional, como Debian, ou uma imagem oficial de ambiente de execução, como Node. Se o seu projeto não precisa de bibliotecas ou utilitários gerais do sistema, é melhor evitar usar um sistema operacional completo como imagem base.
Por natureza, as imagens genéricas de ambientes de execução contêm tudo o que é necessário para executar aplicações na maioria das situações e provavelmente incluem muito software que sua aplicação não usa. A prática recomendada é aproveitar as compilações em vários estágios: você pode usar uma imagem genérica durante a compilação, com as ferramentas necessárias, e depois transferir a aplicação compilada para uma imagem enxuta, com um ambiente mínimo adequado para produção.
Você também pode considerar distribuições especializadas para contêineres, como as imagens distroless do Google ou o Alpine Linux, que é bem menor por padrão. Para linguagens compiladas, como Go ou C, você pode até criar contêineres completamente vazios usando scratch no Dockerfile, já que esse tipo de binário pode não ter dependências externas.
2. Use um usuário com o mínimo de privilégios
Quando um Dockerfile não especifica um USER, o padrão é executar o contêiner como usuário root. Na prática, há pouquíssimos motivos para um contêiner precisar de privilégios de root, e isso pode se tornar um problema de segurança do Docker. Por padrão, o Docker executa contêineres como usuário root. Quando esse namespace é mapeado para o usuário root no contêiner em execução, o contêiner pode ter acesso de root ao host Docker. Executar uma aplicação no contêiner como root facilita a elevação de privilégios caso a própria aplicação seja vulnerável à exploração.
Para reduzir a exposição, crie um usuário e um grupo dedicados para a aplicação na imagem Docker. Use a diretiva USER no Dockerfile para garantir que o contêiner execute a aplicação com o menor nível de privilégio possível.
Lembre-se de que novos usuários ou grupos talvez não existam na imagem; crie-os usando as instruções no Dockerfile.
Veja a seguir um exemplo completo de como fazer isso com uma imagem genérica do Ubuntu:
O exemplo acima:
cria um usuário do sistema (-r) sem senha, sem diretório pessoal definido e sem shell
adiciona o usuário criado a um grupo existente, que criamos previamente usando groupadd
adiciona um argumento final com o nome do usuário que queremos criar associado ao grupo criado
Se você gosta de Node.js e imagens Alpine, elas já incluem um usuário genérico chamado node. Veja um exemplo com Node.js que usa esse usuário:
Se você desenvolve aplicações Node.js, consulte as práticas recomendadas oficiais para Docker e Node.js.
Segurança de contêineres para DevSecOps
Encontre e corrija vulnerabilidades em contêineres gratuitamente com a Snyk.
3. Assine e verifique as imagens para reduzir ataques MITM
A autenticidade das imagens Docker é um desafio. Confiamos muito nessas imagens, pois literalmente as usamos como contêineres para executar nosso código em produção. Por isso, é fundamental garantir que a imagem que baixamos seja a mesma publicada pelo fornecedor e que ninguém a tenha alterado. A adulteração pode ocorrer durante a transmissão, entre o cliente Docker e o registro, ou por meio do comprometimento da conta do proprietário do registro para publicar uma imagem maliciosa.
A assinatura de imagens e outros artefatos relacionados é um tema fundamental para proteger sua cadeia de suprimentos de software, e as tecnologias dessa área estão amadurecendo rapidamente. Atualmente, as duas ferramentas mais usadas para isso são:
Docker Notary v1, que serve de base para a funcionalidade Docker Content Trust (DCT) integrada à CLI do Docker
O projeto SigStore, incluindo a ferramenta cosign, permite assinar, armazenar e verificar artefatos com facilidade.
Docker Content Trust
O Docker Content Trust (DCT) existe há vários anos e permite que autores de imagens assinem as tags que publicam em servidores de registro de imagens compatíveis com a API Docker Notary, como o DockerHub. Quando ativado no host Docker, o DCT impede que uma imagem seja baixada, publicada ou executada se não for possível verificar sua assinatura.
Assinar sua imagem de contêiner com o DCT é simples: basta definir a variável de ambiente `DOCKER_CONTENT_TRUST=1`. Ao publicar sua imagem no DockerHub ou em outro registro de imagens compatível com Notary, o Docker aplica a assinatura e a armazena com a tag da imagem.
Na inicialização do contêiner, basta definir a mesma variável de ambiente para exigir a assinatura. A CLI do Docker se recusará a baixar ou iniciar uma imagem de contêiner cuja tag não tenha assinatura ou tenha uma assinatura inválida.
Assuntos mais complexos, como a revogação de chaves, são tratados pela ferramenta binária notary. Para saber mais sobre o Notary v1 e o DCT, consulte a documentação oficial.
Sigstore
As ferramentas do projeto Sigstore buscam viabilizar não apenas assinaturas de imagens de contêineres, mas também de quaisquer artefatos, como uma lista de materiais de software (SBOM), atestações sobre um artefato (ou seja, metadados de compilação) ou até mesmo um arquivo binário que não seja uma imagem, ou “blob”.
No caso mais simples, assinar uma imagem é tão fácil quanto executar o binário `cosign sign` e informar o registro e a imagem:tag que você quer assinar. O comando correspondente `cosign verify` valida a assinatura.
A partir da versão 1.9, o cosign exige que você gere e gerencie seus próprios pares de chaves. Embora também ofereça o comando `generate-key-pair`, muito fácil de usar (mostrado acima), a próxima versão GA incluirá suporte a assinaturas sem chave. Esse recurso usa um mecanismo de autorização OpenID Connect (OIDC) que gera automaticamente pares de chaves efêmeras com seu endereço de e-mail como anotação. O recurso já está disponível: basta definir `COSIGN_EXPERIMENTAL=1` antes de executar os comandos `sign` ou `verify`.
Outro ponto a considerar em relação às assinaturas de imagens é como você executará os contêineres. Para a maioria de nós, o Kubernetes é a plataforma preferida, mas ele não oferece suporte nativo ao DCT. Portanto, a menos que você use uma distribuição específica que o implemente, será necessário fornecer algum tipo de aplicação de políticas em tempo de execução. Felizmente, é possível aproveitar a API do controlador de admissão do Kubernetes para isso. Projetos de código aberto como o Connaisseur podem cuidar do processo para assinaturas DCT / Notary v1 e Cosign.
4. ENCONTRE, CORRIJA E MONITORE VULNERABILIDADES DE CÓDIGO ABERTO
Ao escolher uma imagem base para seu contêiner Docker, você assume indiretamente os riscos de todas as questões de segurança de contêineres associadas a ela. Isso inclui configurações padrão inadequadas, que não contribuem para a segurança do sistema operacional, e bibliotecas do sistema incluídas na imagem base escolhida.
Um bom primeiro passo é usar a imagem base mais enxuta possível, desde que sua aplicação continue funcionando sem problemas. Isso ajuda a reduzir a superfície de ataque ao limitar a exposição a vulnerabilidades. Por outro lado, essa medida não executa auditorias por conta própria nem protege você contra vulnerabilidades futuras que possam ser divulgadas para a versão da imagem base em uso.
Por isso, uma forma de se proteger contra vulnerabilidades em softwares de segurança de código aberto é usar ferramentas como o Snyk para adicionar análises de segurança contínuas do Docker e monitorar vulnerabilidades em todas as camadas das imagens Docker em uso.

Analise uma imagem Docker em busca de vulnerabilidades conhecidas com estes comandos:
Monitore uma imagem Docker em busca de vulnerabilidades conhecidas. Quando novas vulnerabilidades forem encontradas, o Snyk poderá notificar você e oferecer orientações para corrigi-las:
Com base nas análises realizadas por usuários do Snyk, descobrimos que 44% das imagens Docker analisadas tinham vulnerabilidades conhecidas e que havia imagens base mais novas e seguras disponíveis. Essa orientação para correção é exclusiva do Snyk e ajuda desenvolvedores a agir e atualizar suas imagens Docker.
O Snyk também descobriu que, em 20% de todas as análises de imagens Docker, bastava recriar a imagem Docker para reduzir o número de vulnerabilidades.
Como auditar a segurança de contêineres?
É essencial analisar seu projeto de contêiner baseado em Linux em busca de vulnerabilidades conhecidas para garantir a segurança do seu ambiente. Para isso, o Snyk analisa a imagem base, os pacotes do sistema operacional (SO) instalados e gerenciados pelo gerenciador de pacotes, além dos binários importantes nas camadas que não foram instalados por meio do gerenciador de pacotes.
Snyk Container oferece orientações para corrigir e proteger imagens públicas do Docker Hub, indicando recomendações de imagens base, a camada do Dockerfile em que uma vulnerabilidade foi encontrada e muito mais.
5. NÃO EXPONHA INFORMAÇÕES CONFIDENCIAIS EM IMAGENS DO DOCKER
Às vezes, ao criar uma aplicação dentro de uma imagem Docker, você precisa de segredos, como uma chave privada SSH para baixar código de um repositório privado ou tokens para instalar pacotes privados. Se você copiá-los para um contêiner intermediário do Docker, eles ficarão armazenados em cache na camada em que foram adicionados, mesmo que você os exclua depois. Mantenha esses tokens e chaves fora do Dockerfile.
Use compilações em vários estágios
Outra forma de melhorar a segurança dos contêineres Docker é usar compilações em vários estágios. Aproveite o suporte do Docker a esse tipo de compilação para buscar e gerenciar segredos em uma camada intermediária da imagem, que será descartada depois, garantindo que nenhum dado confidencial chegue à imagem final. Use código para adicionar segredos a essa camada intermediária, como no exemplo a seguir:
Use os segredos do Docker BuildKit
Use um recurso do BuildKit no Docker para gerenciar segredos e montar arquivos confidenciais sem armazená-los em cache, como no exemplo a seguir:
Saiba mais sobre os segredos de compilação do Docker no site oficial.
Cuidado com a cópia recursiva
Tenha cuidado também ao copiar arquivos para a imagem em criação. Por exemplo, o comando a seguir copia recursivamente toda a pasta de contexto da compilação para a imagem Docker, o que pode incluir arquivos confidenciais:
Se houver arquivos confidenciais na pasta, remova-os ou use .dockerignore para ignorá-los:
Como proteger um contêiner Docker?
Use compilações em vários estágios para garantir que a imagem de contêiner criada para produção não inclua recursos de desenvolvimento nem segredos ou tokens.
Além disso, use uma ferramenta de segurança para contêineres para verificar suas imagens Docker pela CLI, diretamente no Docker Hub ou nas imagens implantadas em produção usando Amazon ECR, Google GCR ou outros serviços.
6. Use tags fixas para garantir a imutabilidade
Cada imagem Docker pode ter várias tags, que são variantes da mesma imagem. A tag mais comum é latest, que representa a versão mais recente da imagem. As tags de imagem não são imutáveis, e quem publica as imagens pode publicar a mesma tag várias vezes.
Isso significa que a imagem base do seu Dockerfile pode mudar entre compilações. Essas mudanças podem causar comportamentos inconsistentes. Há várias maneiras de reduzir esse risco e melhorar a segurança do Docker:
Prefira a tag mais específica disponível. Se a imagem tiver várias tags, como :8 e :8.0.1 ou até mesmo :8.0.1-alpine, prefira a última, pois ela identifica a imagem com mais precisão. Evite tags genéricas, como latest. Lembre-se de que uma tag específica pode ser excluída com o tempo.
Para evitar que uma tag específica fique indisponível e impeça o trabalho das equipes que dependem dela, considere manter uma cópia local dessa imagem em um registro ou conta sob seu controle. Leve em conta o esforço de manutenção necessário para essa abordagem, pois será preciso manter um registro. Replicar a imagem que você quer usar em um registro próprio é uma boa prática para garantir que ela não mude.
Seja muito específico! Em vez de baixar uma tag, baixe a imagem usando sua referência SHA256 específica. Assim, você garante que receberá a mesma imagem em cada download. No entanto, usar uma referência SHA256 pode ser arriscado: se a imagem mudar, esse hash talvez deixe de existir.
As imagens Docker são seguras?
As imagens Docker podem ser baseadas em distribuições Linux de código aberto e incluir softwares e bibliotecas de código aberto. Uma pesquisa recente da Snyk sobre segurança de código aberto constatou que as imagens Docker mais populares contêm pelo menos 30 vulnerabilidades.
7. Use COPY em vez de ADD
O Docker oferece dois comandos para copiar arquivos do host para a imagem Docker durante a compilação: COPY e ADD. As instruções são semelhantes, mas têm funções diferentes e podem gerar problemas de segurança no contêiner Docker da imagem:
COPY — copia arquivos locais recursivamente, com arquivos ou diretórios de origem e destino especificados. Com COPY, é necessário declarar os locais.
ADD — copia arquivos locais recursivamente, cria o diretório de destino automaticamente se ele não existir e aceita arquivos compactados como origem local ou URLs remotas, que são extraídos ou baixados, respectivamente, para o diretório de destino.
Embora sutis, as diferenças entre ADD e COPY são importantes. Conheça essas diferenças para evitar possíveis problemas de segurança:
Quando URLs remotas são usadas para baixar dados diretamente para um local de origem, podem ocorrer ataques man-in-the-middle que modificam o conteúdo do arquivo baixado. Além disso, é preciso validar melhor a origem e a autenticidade das URLs remotas. Ao usar COPY, a origem dos arquivos baixados de URLs remotas deve ser declarada por meio de uma conexão TLS segura, e as origens também precisam ser validadas.
Considerações sobre espaço e camadas da imagem: usar COPY permite separar a adição de um arquivo compactado de um local remoto da sua descompactação, criando camadas diferentes e otimizando o cache da imagem. Se precisar de arquivos remotos, reúna o download, a extração e a limpeza em um único comando RUN. Isso otimiza a operação em uma só camada, em vez de usar várias camadas, como seria necessário com ADD.
Quando arquivos compactados locais são usados, ADD os extrai automaticamente para o diretório de destino. Embora isso possa ser aceitável, também cria o risco de zip bombs e de vulnerabilidades Zip Slip, que podem ser acionadas automaticamente.
8. Use rótulos de metadados
Os rótulos da imagem fornecem metadados sobre a imagem que você está criando. Isso ajuda as pessoas a entenderem facilmente como usá-la. O rótulo mais comum é “maintainer”, que informa o nome e o endereço de e-mail da pessoa responsável pela manutenção da imagem. Adicione metadados com o seguinte comando LABEL:
Além do contato da pessoa responsável pela manutenção, adicione todos os metadados importantes para você. Eles podem incluir: hash de commit, link para a compilação correspondente, status de qualidade (todos os testes passaram?), código-fonte, referência ao local do arquivo SECURITY.TXT e muito mais.
É uma boa prática adotar um arquivo SECURITY.TXT (RFC5785) que indique sua política de divulgação responsável no esquema de rótulos do Docker, por exemplo:
Veja mais informações sobre rótulos para imagens Docker.
9. Use compilações em vários estágios para criar imagens Docker menores e mais seguras
Ao compilar sua aplicação com um Dockerfile, muitos artefatos são criados, mas só são necessários durante a compilação. Eles podem ser pacotes, como ferramentas e bibliotecas de desenvolvimento necessárias para compilar, dependências para executar testes unitários, arquivos temporários, segredos e muito mais.
Manter esses artefatos na imagem base, que talvez seja usada em produção, aumenta o tamanho da imagem Docker. Isso pode aumentar bastante o tempo de download e ampliar a superfície de ataque, pois há mais pacotes instalados. O mesmo vale para a imagem Docker que você usa: talvez seja necessária uma imagem específica para a compilação, mas não para executar o código da aplicação.
Go é um ótimo exemplo. Para compilar uma aplicação em Go, você precisa do compilador Go. Ele gera um executável que roda em qualquer sistema operacional, sem dependências, inclusive em imagens scratch.
Esse é um bom motivo para usar o recurso de compilação em vários estágios do Docker. Ele permite usar várias imagens temporárias durante o processo de compilação e manter apenas a imagem final, junto com as informações copiadas para ela. Dessa forma, você tem duas imagens:
Primeira imagem — muito grande e com várias dependências usadas para compilar a aplicação e executar os testes.
Segunda imagem — muito menor, tanto em tamanho quanto no número de bibliotecas, contendo apenas uma cópia dos artefatos necessários para executar a aplicação em produção.
10. Use um linter
Use um linter para evitar erros comuns e estabelecer práticas recomendadas que os engenheiros possam seguir de forma automatizada. Essa é uma etapa útil da análise de segurança do Docker para detectar estaticamente problemas de segurança no Dockerfile.
Um exemplo de linter é o hadolint. Ele analisa um Dockerfile e mostra avisos para erros que não seguem suas regras de boas práticas.

O Hadolint é ainda mais eficiente quando usado em um ambiente de desenvolvimento integrado (IDE). Por exemplo, ao usar o hadolint como extensão do VSCode, os erros de lint aparecem enquanto você digita. Assim, fica mais fácil escrever Dockerfiles melhores e com mais rapidez.
Segurança de contêineres para DevSecOps
Encontre e corrija vulnerabilidades em contêineres gratuitamente com a Snyk.
Como reforçar a segurança de uma imagem de contêiner Docker?
Você pode usar linters, como hadolint ou dockle, para garantir que o Dockerfile tenha uma configuração segura. Não se esqueça de verificar também suas imagens de contêiner para evitar vulnerabilidades com alto impacto na segurança dos contêineres em produção.
O Docker representa um risco à segurança?
O Docker é uma tecnologia de virtualização de software que ganhou popularidade e ampla adoção. Ao compilar e implantar com Docker, é preciso seguir as boas práticas de segurança para reduzir riscos como vulnerabilidades incluídas nas imagens base do Docker ou violações de dados causadas por configurações incorretas dos contêineres.
Como proteger um contêiner Docker?
Siga as boas práticas de segurança do Docker para usar imagens base do Docker com poucas ou nenhuma vulnerabilidade conhecida, configurar o Dockerfile com segurança e monitorar os contêineres implantados para detectar diferenças entre as imagens de desenvolvimento e produção. Além disso, siga as boas práticas de Infrastructure as Code para soluções de orquestração de contêineres.
Segurança do Docker: recursos adicionais
Para concluir, se você quer acompanhar as boas práticas de segurança para criar imagens Docker otimizadas para aplicações Node.js e Java:
Você é desenvolvedor Java? Este recurso pode ser útil: Docker para desenvolvedores Java: 5 coisas que você precisa saber para não comprometer sua segurança
10 boas práticas para criar um contêiner Java com Docker — Um excelente guia detalhado sobre como criar contêineres prontos para produção para aplicações Java.
10 boas práticas para conteinerizar aplicações web Node.js com Docker — Se você desenvolve em Node.js, vai gostar deste passo a passo que mostra como criar imagens base Docker eficientes e seguras para suas aplicações Node.js.
Conheça o cenário atual da segurança de código aberto
Entenda as tendências e abordagens atuais para proteger softwares de código aberto e a cadeia de suprimentos.
