Build e publicação de imagem no GHCR com tag imutável
Objetivos desta aula
- Publicar no GHCR com metadados
- Gerar tags previsíveis
- Registrar o digest para deploy
A saída do CI é um artefato identificável. Publicar no GHCR com docker/build-push-action e docker/metadata-action gera automaticamente tags coerentes: a versão da tag Git, o SHA do commit e, opcionalmente, latest para conveniência de desenvolvimento — nunca para produção.
O digest é a identidade real da imagem. Registre-o na saída do job e use-o no deploy: assim, a mesma imagem testada é a que roda, sem chance de alguém sobrescrever uma tag no meio do caminho.
Adicione labels OCI (fonte, revisão, versão) para que qualquer pessoa consiga rastrear a imagem de volta ao commit. Em auditoria e em incidente, esse detalhe economiza muito tempo.
1. Por que tag imutável
latest não diz o que está rodando e pode mudar sob seus pés. Use o SHA do commit (sha-1a2b3c4) e a versão SemVer nas releases. Cada deploy aponta para algo que nunca muda.
2. Metadados e rótulos OCI
docker/metadata-action gera tags e labels (org.opencontainers.image.revision, source) que ligam a imagem ao commit.
3. Multi-arquitetura
Com QEMU e Buildx, uma imagem serve amd64 e arm64 (Graviton na AWS, Macs M-series), o que costuma baratear a infraestrutura.
4. Assinatura e proveniência
Cosign assina a imagem com identidade OIDC; o cluster pode recusar imagens não assinadas. Attestations registram como e onde a imagem foi construída.
5. Checagem final
Todo push na main publica ghcr.io/cloudshop-org/cloudshop-api:sha-xxxxxxx, assinada e escaneada.
Na prática
Publicação com metadados e digest
yaml
permissions:
contents: read
packages: write
jobs:
imagem:
runs-on: ubuntu-latest
outputs:
digest: ${{ steps.build.outputs.digest }}
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}/api
tags: |
type=semver,pattern={{version}}
type=sha,format=long
- id: build
uses: docker/build-push-action@v6
with:
context: ./api
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
- run: echo "publicado com digest ${{ steps.build.outputs.digest }}"Nota de segurança: GITHUB_TOKEN com packages: write é suficiente para GHCR; não crie PAT de longa duração para isso.
Build, push e assinatura
yaml
permissions: { contents: read, packages: write, id-token: write }
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with: { registry: ghcr.io, username: ${{ github.actor }}, password: ${{ secrets.GITHUB_TOKEN }} }
- id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/cloudshop-org/cloudshop-api
tags: type=sha,prefix=sha-
- id: build
uses: docker/build-push-action@v6
with:
context: api
push: true
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
- uses: sigstore/cosign-installer@v3
- run: cosign sign --yes ghcr.io/cloudshop-org/cloudshop-api@${{ steps.build.outputs.digest }}Por que isso importa
Deploy por digest é o que garante que produção roda exatamente o que passou pelos testes.
Erro comum
Deployar :latest e não conseguir dizer qual commit está rodando.
Dica de produção
Guarde a relação tag → digest → commit em um arquivo de release ou no repositório GitOps.
Pergunta de entrevista
Por que referenciar imagem por digest em produção?
Glossário
- GHCR
- GitHub Container Registry, registry de imagens integrado ao GitHub.
- OCI labels
- Metadados padronizados que descrevem origem e versão da imagem.
- GHCR
- GitHub Container Registry, registro de imagens do GitHub.
- cosign
- Ferramenta do projeto Sigstore para assinar e verificar imagens.
- Buildx
- Extensão do Docker para builds multi-plataforma com BuildKit.
Conexão com o CloudShop
Publicar ghcr.io/sua-org/cloudshop/api a cada tag de versão.
Quiz da aula
1. Qual identificador é imutável para uma imagem?
2. Por que evitar a tag latest em deploy?
3. O que o cosign adiciona?
Minhas anotações
Salvo automaticamente neste navegador.