Publicar imagem para amd64 e arm64
Times com máquinas Apple Silicon e clusters com instâncias ARM (Graviton, Ampere) precisam da mesma imagem em duas arquiteturas. A solução é uma manifest list: uma única referência que aponta para uma imagem por plataforma, e o runtime escolhe a certa sozinho.
1. Configure o builder
Seção intitulada “1. Configure o builder”O driver padrão do Docker não faz build multiplataforma. Crie um builder com o driver
docker-container:
docker buildx create --name multi --driver docker-container --usedocker buildx inspect --bootstrap # confirme as plataformas suportadasPara emular a arquitetura ausente no seu host:
docker run --privileged --rm tonistiigi/binfmt --install allEmulação funciona e é lenta — de 5 a 20 vezes mais devagar em builds que compilam. O passo 5 mostra a alternativa.
2. Faça o build para as duas plataformas
Seção intitulada “2. Faça o build para as duas plataformas”docker buildx build \ --platform linux/amd64,linux/arm64 \ -t registry.exemplo.com/loja:1.8.3 \ --push . # multiplataforma exige push diretoNão existe --load para várias plataformas: o armazenamento local do Docker guarda uma
imagem por vez. Ou você envia para o registry, ou faz build de uma plataforma só.
Se o seu Dockerfile compila código, use os argumentos que o buildx injeta para compilar sem emulação:
FROM --platform=$BUILDPLATFORM golang:1.23 AS buildARG TARGETOS TARGETARCHWORKDIR /srcCOPY . .# compila NA arquitetura do host, PARA a arquitetura de destino: rápidoRUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -o /bin/loja ./cmd/loja
FROM gcr.io/distroless/static-debian12:nonrootCOPY --from=build /bin/loja /bin/lojaENTRYPOINT ["/bin/loja"]Esse padrão — --platform=$BUILDPLATFORM no estágio de build, destino no estágio final —
é o que torna o build multiplataforma viável em Go, Rust e qualquer linguagem com
compilação cruzada.
3. Verifique o que foi publicado
Seção intitulada “3. Verifique o que foi publicado”docker buildx imagetools inspect registry.exemplo.com/loja:1.8.3A saída deve listar linux/amd64 e linux/arm64 sob o mesmo digest de manifest list.
Teste puxando de cada arquitetura:
docker run --rm --platform linux/arm64 registry.exemplo.com/loja:1.8.3 --versiondocker run --rm --platform linux/amd64 registry.exemplo.com/loja:1.8.3 --version4. No CI
Seção intitulada “4. No CI”- uses: docker/setup-qemu-action@v3- uses: docker/setup-buildx-action@v3- uses: docker/build-push-action@v6 with: platforms: linux/amd64,linux/arm64 push: true tags: registry.exemplo.com/loja:${{ github.sha }} cache-from: type=registry,ref=registry.exemplo.com/loja:buildcache cache-to: type=registry,ref=registry.exemplo.com/loja:buildcache,mode=max provenance: true sbom: true5. Custo e tempo
Seção intitulada “5. Custo e tempo”Duas plataformas custam mais que uma — a questão é quanto:
- Compilação cruzada (passo 2): custo próximo de zero. Prefira sempre que a linguagem permitir.
- Runners nativos por arquitetura, com a manifest list montada no fim: rápido, e a
opção certa quando há compilação de dependências nativas (Python, Node com módulos
binários).
Janela do terminal # cada runner publica sua própria tag por arquitetura...docker buildx build --platform linux/arm64 -t loja:1.8.3-arm64 --push .# ...e um job final junta tudo numa referência sódocker buildx imagetools create -t registry.exemplo.com/loja:1.8.3 \registry.exemplo.com/loja:1.8.3-amd64 registry.exemplo.com/loja:1.8.3-arm64 - Emulação por QEMU: simples de configurar e caro em tempo. Aceitável para imagens que só copiam artefatos prontos.
Antes de publicar as duas, confirme que você precisa das duas: se o cluster é só amd64 e
o ARM serve apenas para o notebook do time, talvez baste uma imagem de desenvolvimento.
Se der errado
Seção intitulada “Se der errado”| Sintoma | Causa provável |
|---|---|
exec format error |
A plataforma pedida não está na manifest list |
multiple platforms feature is currently not supported |
Builder com driver padrão; crie o docker-container |
| Build ARM eterno | Emulação compilando; use compilação cruzada ou runner nativo |
--load falha |
Esperado com várias plataformas: use --push |
| Dependência nativa quebra só em ARM | Wheel/binário indisponível; compile no runner nativo |
Checklist de pronto
Seção intitulada “Checklist de pronto”- Builder
docker-containerativo. - Build usando compilação cruzada quando possível.
-
imagetools inspectlistando as duas plataformas. - Execução testada em cada arquitetura.
- Cache de build configurado no CI.
- Tempo de build medido e aceitável.