Formatos de imagens de contêiner por dentro
Agata Krajewska
18 de novembro de 2020
0 minutos de leituraNos últimos anos, desde o lançamento do Docker, os contêineres se tornaram cada vez mais o padrão para distribuir software.
Vemos um número crescente de soluções baseadas em contêineres. Embora a inovação nesse espaço seja sempre bem-vinda, é necessário estabelecer alguns padrões para formatos e ambientes de execução.
Com o rápido crescimento do projeto Docker, as imagens Docker se tornaram padrão para diversas finalidades. Mas há um interesse claro em uma especificação única e aberta para contêineres, que seja:
independente de construções de nível mais alto, como um cliente específico ou uma pilha de orquestração;
não estar fortemente associada a nenhum fornecedor comercial ou projeto específico;
portátil em diversos sistemas operacionais, hardwares, arquiteturas de CPU, nuvens públicas etc.
A OCI (Open Container Initiative) é um projeto da Linux Foundation que desenvolve padrões abertos para virtualização no nível do sistema operacional, sobretudo para contêineres Linux.
Hoje, várias ferramentas de build de código aberto oferecem suporte ao formato de imagem OCI, incluindo:
BuildKit: uma reimplementação otimizada do mecanismo de build do Docker
Podman: uma implementação alternativa da ferramenta de linha de comando do Docker
Buildah: uma alternativa de linha de comando para escrever Dockerfiles
A Snyk oferece suporte a todos os formatos comuns de imagens de contêineres. Por isso, podemos nos integrar a uma ampla variedade de ferramentas do ecossistema. Neste post, vamos conhecer algumas delas e mostrar como a Snyk funciona com cada uma!
Arquivo Docker
Primeiro, vamos conhecer o formato de arquivo Docker. Ele faz parte da v1 obsoleta da especificação de imagens do Docker. Você encontra a especificação completa aqui. Quando você executa docker save, esse é o formato padrão gerado pelo cliente Docker, usado para garantir a compatibilidade com versões anteriores de outras ferramentas. Os registros de contêineres usam um formato mais recente para armazenar imagens.
Se você estiver executando o Docker localmente e usando a CLI da Snyk ou qualquer uma das nossas integrações para contêineres, usaremos sua instância local do Docker para baixar a imagem, salvá-la no sistema de arquivos e iniciar a análise.
Vamos explorar a estrutura desse arquivo e descobrir o que interessa à Snyk!
Neste post, vou usar a imagem ubuntu:bionic. Primeiro, vamos salvar o arquivo no seu sistema de arquivos local:
docker save --output ubuntu-docker.tar ubuntu:bionic
A distribuição bionic tem três camadas de imagem, que vamos analisar mais de perto.
Depois de descompactar o arquivo tar, podemos conferir o que há dentro dele:
Vamos dar uma olhada em manifest.json:
O arquivo aponta para a configuração do contêiner, onde encontramos informações muito úteis, como arquitetura, configuração, camadas do sistema de arquivos raiz etc. E, provavelmente a parte mais interessante para a Snyk, a propriedade Layers aponta para as camadas reais da imagem, que são apenas diretórios dentro do arquivo. Se entrarmos em um desses diretórios, veremos o que ele contém:
Vamos nos aprofundar um pouco mais e descompactar o layer.tar:
Como você pode ver acima, o layer.tar contém apenas as alterações no sistema de arquivos da camada da imagem, incluindo dependências e outros binários, conforme o conteúdo da imagem. Depois de extrair e analisar o conteúdo
dessas camadas, podemos mostrar a lista de caminhos vulneráveis.
Agora, vamos executar snyk test na imagem salva no arquivo Docker. Para testar um arquivo local, basta especificar o prefixo docker-archive::
snyk container test docker-archive:ubuntu-docker.tar ou analisar a imagem do seu repositório Docker local:
snyk container test ubuntu:bionic
Nos dois casos, o resultado será exatamente o mesmo:
Imagem OCI
Nos últimos meses, também adicionamos à CLI da Snyk a análise de arquivos OCI.
Vamos conferir a especificação e ver o que encontramos no arquivo! Nesta seção, também vou usar ubuntu:bionic.
Se você quiser inspecionar um arquivo tar OCI, execute o seguinte comando:
skopeo copy --override-os linux docker://ubuntu:bionic oci-archive:ubuntu.tar
Vou usar o Skopeo para salvar a imagem. É um utilitário de cli que facilita muito a execução de várias operações em imagens.
Para salvar uma imagem ubuntu no formato OCI, basta especificar o prefixo oci-archive: na saída tar.
Repare que também estou usando a opção --override-os — isso acontece porque estou no macOS e as imagens do Docker Hub para o Ubuntu só estão disponíveis para Linux. Também vamos falar sobre imagens com várias arquiteturas mais adiante.
Depois de descompactar o arquivo tar, podemos conferir o conteúdo:
Na raiz, temos um index.json interessante. Vamos conferir o conteúdo:
Este é o nosso manifesto opcional de nível mais alto, que aponta para manifestos de imagens específicos. Ele contém informações sobre um conjunto de imagens que pode abranger várias arquiteturas e sistemas operacionais. Se quiser saber mais, confira a especificação completa.
Agora, vamos inspecionar o manifesto específico da imagem, indicado por index.json, no diretório blobs/sha256:
Começamos a encontrar conteúdos interessantes, como a configuração do contêiner, que mais uma vez reúne informações úteis sobre a arquitetura das imagens, as camadas da imagem base, a configuração etc. Também temos informações sobre as camadas da imagem, que apontam para as camadas disponíveis na imagem ubuntu:bionic.
Como vemos abaixo, o conteúdo da primeira camada é exatamente igual ao do arquivo Docker mostrado acima.
Você pode analisar seu arquivo OCI local executando:
snyk container test oci-archive:ubuntu.tar
Plataformas e arquiteturas variadas
Ao inspecionar os manifestos do arquivo Docker e da imagem OCI, vimos que ambos continham informações sobre a arquitetura. Vamos voltar e conferir o conteúdo do manifesto de configuração do contêiner no diretório ubuntu-docker, onde salvamos nosso docker archive:
Entre outras informações, vemos a arquitetura e o sistema operacional. No meu caso, são amd64 e linux. E se nossa imagem fosse baseada em arm64 ou estivéssemos usando a plataforma windows?
Boa notícia: a Snyk também oferece suporte a outras plataformas. Basta passar a opção -—platform para a CLI da Snyk.
Já falamos sobre o formato de arquivo gerado por docker save. Agora, vamos conhecer o formato v2 schema usado para armazenar imagens no Docker Hub — há detalhes bem interessantes por trás dele. Esta é a segunda versão do v2 schema, criada para atender a dois objetivos principais. Segundo a documentação do Docker:
O primeiro é permitir imagens com várias arquiteturas por meio de um “manifesto fat”, que faz referência a manifestos de imagens para versões específicas de cada plataforma. O segundo é aproximar o mecanismo do Docker de imagens endereçáveis por conteúdo, com suporte a um modelo em que a configuração da imagem pode ser submetida a hash para gerar seu ID.
Usando o Docker local, podemos primeiro inspecionar o “manifesto fat” da imagem desejada para conferir quais variantes de plataforma estão disponíveis. Como explicamos acima, isso significa que um único repositório pode armazenar várias imagens para diferentes arquiteturas.
docker manifest inspect ubuntu:bionic
Como resultado, veremos uma matriz de manifestos:
Agora que confirmamos que a imagem ubuntu está disponível para várias plataformas, vamos ver como analisar a imagem ubuntu para a arquitetura arm64.
Verifique se os recursos experimentais estão ativados no Docker do seu host e execute:
snyk container test --platform=linux/arm64 ubuntu:bionic
Vamos conferir o resultado:
Podemos ver todos os caminhos vulneráveis encontrados e também as informações de plataforma no resultado da análise.
Neste post, exploramos os dois principais formatos de imagens de contêineres — Docker e OCI — e mostramos como a Snyk funciona com ambos, inclusive em várias arquiteturas.
Para finalizar, confira estas boas práticas de segurança para criar imagens Docker otimizadas para aplicações Node.js e Java:
10 boas práticas de segurança para Docker — conheça as práticas de segurança que você deve seguir ao criar imagens base do Docker e ao baixá-las. O artigo também apresenta o Docker Content Trust.
Você é desenvolvedor Java? Este recurso é para você: Docker para desenvolvedores Java: 5 coisas que você precisa saber para não comprometer sua segurança
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 do Docker seguras e eficientes para suas aplicações Node.js.
Você pode acessar todos esses recursos da Snyk gratuitamente — crie uma conta.
Comece a jogar Capture the Flag
Aprenda a resolver desafios de Capture the Flag assistindo à gravação sob demanda do nosso workshop virtual introdutório.



