Criando imagens Docker sem Dockerfile com Cloud Native Buildpacks

Lírio
Devspoint
Published in
7 min readOct 12, 2021

O que vamos abordar?

  • Aplicações Nativas de Nuvem
  • Cloud Native Buildpacks
  • Paketo Buildpacks

Microserviços ou agora também conhecidos como Cloud Native Apps deixaram de ser hype e hoje são algo comum. Netflix OSS teve um papel forte de impulsionar alguns padrões, como Service Discovery, Circuit Breaker, Configurações Centralizadas, Tracing e etc. A Netflix não criou os padrões mas implementou-os tão bem que virou referencia, tem um artigo do então VP da Amazon (ex CNCF e Netflix) Adrian Cockcroft que conta um pouco dessa história.

Basicamente esse padrões foram implementados no lado do desenvolvimento e com tempo foram abstraídos para infraestutura como o próprio Kubernetes tem feito junto com o Istio, Envoy e alguns outros operators. Há um artigo do Alibaba Cloud que conta exatamente essa trajetória e as evoluções, recomendo muito a leitura.

Esses padrões estão mais forte no nosso dia-a-dia e evoluindo como sempre, hoje as aplicações nativas de nuvem tem tomado novas formas para rodar em ambientes cada vez menores ou mesmo rodando 100% em Serverless como algumas startups tem feito.

Cloud Native Computing Foundation (CNCF)

A CNCF faz parte da organização sem fins lucrativos Linux Foundation, mantendo componentes de tecnologia de infraestrutura. CNCF reúne os principais desenvolvedores, usuários e fornecedores do mundo.

O CNCF mantem alguns projetos, como Kubernetes para orquestração de containers, Prometheus para monitoramento, Jaeger para tracing distribuído, Fluentd para Logging, Linkerd para malha de serviço, gRPC para chamadas remotas, CoreDNS para descoberta de serviço, Containerd para containers, CNI para rede de containers.

Todos os projetos hospedados pela CNCF estão em seu site.

Os projetos CNCF têm níveis de maturidade, sandbox, incubating ou graduated. O Buildpacks.io está no nível incubating e falaremos sobre ele nesse artigo.

No site também mostra os projetos que estarão sendo incubado pela CNCF.

Buildpacks.io

Buildpacks foram criados pela Heroku em 2011. Desde então, eles foram adotados pelo Cloud Foundry e outros PaaS, como Google App Engine, Gitlab, Knative, você pode ver a lista dos Heroku Buildpacks aqui.

Você já criou uma aplicação Spring Boot com Maven e subiu para o Heroku com o comando git push heroku master, o buildpack detecta sua aplicação como Java se ele tiver um arquivo pom.xml, ou um dos outros formatos POM suportados pelo plugin Maven em seu diretório raiz. Ele usará o Maven para executar a compilação definida por seu pom.xml e baixar suas dependências e fazer o build.

Cloud Native Buildpacks

Em 2018, Pivotal e Heroku uniram forças e iniciaram o projeto Cloud Native Buildpacks (CNB) e em outubro de 2018 se juntou à CNCF.

O objetivo do projeto CNB é transformar o código-fonte em imagens de Container compatíveis com Open Container Initiative (OCI), eles examinam seu código-fonte, criam uma imagem de container com todas as dependências necessárias para executar sua aplicação com foco na produtividade do desenvolvedor, segurança do Container. O projeto também visa unificar os ecossistemas buildpacks do passado com um contrato bem definido, ideal para plataformas Cloud Native.

OCI é um projeto da Linux Foundation, iniciado pela Docker em 2015 com o objetivo principal é criar um padrão de mercado seguido por todas as empresas que trabalham com containers de forma que todos sigam as mesmas interfaces para os formatos de containers e imagens. Isto facilita muito a interoperabilidade entre ferramentas e runtimes de forma que uma imagem que seja compatível com a OCI possa ser executada por qualquer runtime também compatível.

Mas o que ganhamos ao utilizar CNB, um Dockerfile já não bastaria? E porque manter containers padronizados OCI?

Padronização

Você deve ter ficado sabendo que o Kubernetes descontinuou o suporte ao Docker, isso repercutiu muito no mercado e todos pensaram e agora o que eu faço. Nada!!! Graças ao OCI você pode criar imagens docker na sua maquina local, subir para o Registry e o Kubernetes rodará ele normalmente. Com o tempo as atualizações sempre acontece e seu time precisa estar ligado nesses assuntos, tirar essa responsabilidade do seu time e automatizar já seria um ganho grande.

Dockerfile

Embora a flexibilidade do Dockerfile é algo que pode ser bom, configurar e gerar uma imagem da maneira que você desejar, existem desvantagens também. Cada Dockerfile se torna outra parte do código customizado que você possui. Você deve levar em conta a correção, performance e segurança. Ao longo da vida útil da sua aplicação, você também deve estar sempre atento quando o sistema operacional pode exigir patches e atualizações.

A simplicidade do Dockerfile apresenta desafios. É apenas um script que provavelmente está no mesmo repositório que o código da sua aplicação. Qualquer esforço para examinar, padronizar ou reutilizar Dockerfiles em aplicações ou equipes de desenvolvimento depende de você. Qualquer automação para construir e manter imagens como parte de ferramentas DevOps também depende de você.

Paketo Buildpacks

Scripts de Build da aplicação, qual imagem base utilizar e a construção da imagem da sua aplicação agora deixa de estar do lado do código (dev) e passa a estar do lado da pipeline (ops), no entanto essa responsabilidade não fica com o profissional de infraestrutura se na sua empresa existe a separação time de plataforma e desenvolvimento, isso deixa de estar em mãos humanas e passa a ser automatizado.

Para isso a primeira tarefa é deixar de usar docker build para construir imagens e NÃO teremos mais o Dockerfile no código-fonte da aplicação. Usaremos o Pack CLI.

O CNB fornece uma maneira opinativa de construir imagens, detectando características da sua aplicação e adicionando buildpacks necessários para construir sua imagem de container.

Vantagens

Produtividade, Manutenibilidade e Segurança são algumas vantagens, alguns engenheiros mesmo com experiência precisam sempre se atentar ao escrever um Dockerfile podendo cometer alguns erros. Com CNB você não precisa necessariamente de um especialista no assunto, lembrando que sua imagem precisa ser construída e reconstruída de forma pequena, segura e performática. Normalmente as equipes de desenvolvimento acabam pegando uma aplicação de referência que possui um arquivo Dockerfile no repositório git simplesmente copiando e colando e nem se perguntam se vulnerabilidades apareceram.

Imagem retirada do site buildpacks.io

Na imagem acima há algumas comparações entre CNB e outras alternativas, pontos de comparação como Advanced Caching, Auto-detection, Multi-language, Multi-Cloud…

Construindo imagens com Paketo Buildpacks

Pré-requisitos para criarmos uma imagem é ter instalado Pack CLI.

No artigo "A Decisão de Escolher o Framework do Momento (ou do futuro)" criamos uma aplicação Kotlin, Spring Boot, Gradle, Webflux e geramos a imagem com o comando ./gradlew clean bootBuildImage, agora vamos gerar a imagem com pack-cli utilizando essa mesma aplicação.

git clone https://github.com/devspoint/tutorials.gitcd tutorials/spring-webflux-reactivepack build spring-webflux-reactive --builder \ paketobuildpacks/builder:base

Clonamos e executamos o comando pack build, o auto-detection foi feito identificando uma aplicação Spring-Boot, Gradle, baixou as dependências que a aplicação irá utilizar, compilou, gerou o build da aplicação e gerou uma imagem, sem script e sem Dockerfile.

→ Successfully built image spring-webflux-reactive

Agora basta rodar seu container com a imagem gerada

docker run -p 8080:8080 spring-web-imperative:0.0.1-SNAPSHOT

Integração com GraalVM

Geramos a imagem da aplicação com a JVM e para gerar com GraalVM é muito simples, basta adicionar → . — env BP_NATIVE_IMAGE=true

pack build spring-webflux-reactive-native --builder \ paketobuildpacks/builder:base --env BP_NATIVE_IMAGE=true

No passo de DETECTING cada buildpack detecta se deve participar do processo, quando detectado o mesmo contribui para a geração da imagem, desta vez 2 novos, o graalvm 6.5.0 e native-image 4.3.2

===> DETECTING
6 of 13 buildpacks participating
paketo-buildpacks/ca-certificates 2.4.2
paketo-buildpacks/graalvm 6.5.0
paketo-buildpacks/gradle 5.7.0
paketo-buildpacks/executable-jar 5.3.1
paketo-buildpacks/spring-boot 4.7.0
paketo-buildpacks/native-image 4.3.2

→ Successfully built image spring-webflux-reactive-native

Multi-Linguagens

Na documentação do paketo.io tem alguns How to Build de outras linguagens, como NodeJS, .NET Core, Python. Vamos construir uma imagem agora de uma aplicação Go!

git clone https://github.com/paketo-buildpacks/samplescd samples/go/modpack build my-app --buildpack gcr.io/paketo-buildpacks/go \
--builder paketobuildpacks/builder:base

Conclusão

Assim como API Gateway, Circuit Breaker, Service Discovery, Tracing Distribuídos e outras padrões muito utilizados em microserviços, scripts e build de imagens também estão sendo abstraídos para a infraestrutura, não importando a linguagem, fazendo com que o Dev passa a pensar mais na regra de negócio. Com o tempo patches de atualização de segurança e outras situações que poderiam causar problemas passam a ser responsabilidade do CNB que sempre são atualizados, gerando imagens seguras, pequenas e performáticas prontos para rodar em um cluster Kubernetes.

Ref.:

--

--