O GitHub Container Registry no Node.js armazena imagens Docker e OCI no domínio ghcr.io. Ele se integra a repositórios, organizações e GitHub Actions, permitindo construir, publicar e controlar acesso às imagens usadas em Docker Compose, Kubernetes e pipelines de entrega.
Um registry não garante que a imagem é segura ou reproduzível. É necessário fixar Actions, limitar permissões, usar tags imutáveis, registrar metadados, escanear vulnerabilidades e implantar por digest. Também é importante separar credenciais de leitura das permissões de publicação.
Neste guia, você aprenderá a autenticar no GHCR, nomear imagens, publicar com GitHub Actions, gerar tags e labels, usar cache, criar imagens multi-arquitetura, controlar visibilidade, puxar por digest e integrar com Kubernetes.
O que é GHCR?
A documentação oficial do GitHub Container Registry informa que o serviço armazena imagens Docker e OCI em contas pessoais ou organizações. O nome segue o formato:
ghcr.io/ORGANIZACAO/IMAGEM:TAGExemplo:
ghcr.io/acme/orders-api:1.4.3Preparando o Dockerfile
Use uma imagem multi-stage e execute como usuário não-root:
FROM node:22-bookworm-slim AS dependencies
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
FROM dependencies AS build
COPY . .
RUN npm run build
RUN npm prune --omit=dev
FROM node:22-bookworm-slim AS production
ENV NODE_ENV=production
WORKDIR /app
USER node
COPY --from=build --chown=node:node /app/node_modules ./node_modules
COPY --from=build --chown=node:node /app/dist ./dist
COPY --from=build --chown=node:node /app/package.json ./package.json
EXPOSE 3000
CMD ["node", "--enable-source-maps", "dist/server.js"]Consulte Docker Multi-stage para Node.js.
Labels OCI
O GHCR reconhece labels OCI para associar imagem, fonte, descrição e licença:
LABEL org.opencontainers.image.source="https://github.com/acme/orders-api"
LABEL org.opencontainers.image.description="API de pedidos em Node.js"
LABEL org.opencontainers.image.licenses="MIT"A especificação de annotations OCI define chaves padronizadas. Prefira gerar labels na pipeline com commit, versão e data.
Login local
Para uso fora do GitHub Actions, a documentação exige token com escopo apropriado:
export CR_PAT="token"
echo "$CR_PAT" | docker login ghcr.io \
--username USERNAME \
--password-stdinUse read:packages para pull e write:packages para push. Evite tokens com repo quando não é necessário.
Build e push manual
docker build \
--tag ghcr.io/acme/orders-api:1.4.3 \
--tag ghcr.io/acme/orders-api:sha-abc1234 \
.
docker push ghcr.io/acme/orders-api:1.4.3
docker push ghcr.io/acme/orders-api:sha-abc1234Não publique somente latest. Uma versão e uma tag de commit tornam o artefato rastreável.
Workflow do GitHub Actions
name: Container
on:
push:
branches: [main]
tags: ["v*"]
permissions:
contents: read
packages: write
attestations: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
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 }}
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix=sha-
type=raw,value=latest,enable={{is_default_branch}}
- uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=maxFixe Actions por commit em ambientes rigorosos para reduzir risco de supply chain. Veja CI para Node.js com GitHub Actions.
Permissões mínimas
Declare permissions no job ou workflow. packages: write permite publicar; contents: read permite checkout. Não use write-all.
Em pull requests de forks, não publique imagens com tokens privilegiados. Separe validação de código e publicação.
GITHUB_TOKEN
Dentro do workflow do repositório, prefira GITHUB_TOKEN a um PAT permanente. O token é temporário e pode ter permissões restritas. Quando o pacote pertence a outro repositório, conceda acesso explicitamente.
Conectando pacote e repositório
Publicar pelo workflow normalmente associa o pacote ao repositório. Ao publicar pela linha de comando, use a label org.opencontainers.image.source e conecte o pacote nas configurações quando necessário.
Visibilidade
Pacotes podem ser públicos, privados ou internos conforme conta e organização. Uma imagem pública pode ser puxada anonimamente. Imagens privadas exigem autenticação e permissões.
Não transforme uma imagem em pública sem revisar:
- arquivos copiados para camadas;
- source maps;
- credenciais em ENV ou ARG;
- código proprietário;
- licenças;
- SBOM e metadados.
Tags recomendadas
1.4.3: versão imutável da aplicação;1.4: canal móvel da linha minor;sha-abc1234: commit específico;latest: conveniência, nunca referência de produção.
Proteja tags de release no Git e publique somente após testes.
Deploy por digest
Mesmo uma tag pode ser sobrescrita. O digest identifica o conteúdo:
docker pull ghcr.io/acme/orders-api@sha256:abc123...No Kubernetes:
image: ghcr.io/acme/orders-api@sha256:abc123...Isso garante que todos os nós executem a mesma imagem. Consulte Kubernetes Deployment no Node.js.
Obtendo o digest
O build-push-action expõe o digest:
- name: Show digest
run: echo "${{ steps.build.outputs.digest }}"Dê um id: build ao step e passe esse valor ao processo de atualização do manifesto.
Multi-arquitetura
- uses: docker/setup-qemu-action@v3
- uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ghcr.io/acme/orders-api:1.4.3O registry armazena um manifest list apontando para imagens de cada arquitetura. Teste dependências nativas e addons em ambas.
Cache de build
cache-from: type=gha
cache-to: type=gha,mode=maxCache acelera builds, mas não deve carregar segredos em camadas. Use BuildKit secrets para tokens usados durante o build.
NPM privado durante build
Não passe NPM_TOKEN com ARG ou ENV:
# syntax=docker/dockerfile:1.7
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \
npm ciNo workflow:
secrets: |
npmrc=${{ secrets.NPMRC }}Revise logs para evitar vazamento.
SBOM
Gere uma Software Bill of Materials e associe ao artefato. Veja SBOM no Node.js. O SBOM ajuda a identificar dependências afetadas, mas precisa corresponder exatamente à imagem publicada.
Provenance e attestation
Registre como a imagem foi construída, de qual commit e em qual workflow. GitHub Actions e BuildKit podem produzir attestations. Trate a provenance como evidência, não como substituto para revisão.
Scan de vulnerabilidades
Execute scanner antes do push ou da promoção:
trivy image \
--exit-code 1 \
--severity CRITICAL,HIGH \
ghcr.io/acme/orders-api@sha256:abc123...Defina política para vulnerabilidades sem correção e registre exceções com prazo.
Supply chain
Uma pipeline segura deve:
- fixar dependências e Actions;
- testar o código;
- construir uma vez;
- gerar SBOM;
- escanear a imagem;
- assinar ou atestar;
- publicar por digest;
- promover o mesmo digest entre ambientes.
Consulte Supply Chain no Node.js.
Kubernetes com imagem privada
Crie um Secret de leitura:
kubectl create secret docker-registry ghcr-pull \
--docker-server=ghcr.io \
--docker-username=USERNAME \
--docker-password=TOKEN \
--namespace=productionNo Pod:
imagePullSecrets:
- name: ghcr-pullUse token somente com read:packages e faça rotação. Em plataformas compatíveis, prefira identidade federada ou integração nativa.
Docker Compose
services:
api:
image: ghcr.io/acme/orders-api@sha256:abc123...
pull_policy: alwaysVeja Docker Compose para Node.js.
Retenção
Tags de commit acumulam rapidamente. Defina política para remover versões antigas não usadas, preservando releases, digests implantados e artefatos necessários à auditoria.
Não delete a única imagem capaz de executar rollback.
Imutabilidade operacional
O GHCR permite administrar versões, mas a governança deve impedir sobrescrever tags de release. A pipeline pode verificar se a tag já existe antes do push e falhar em caso de conflito.
Ambientes
Não reconstrua a imagem para produção. Construa no commit, publique o digest e promova o mesmo artefato. Apenas configuração externa deve mudar entre ambientes.
Observabilidade
Registre em cada deploy:
- nome da imagem;
- tag;
- digest;
- commit;
- workflow run;
- SBOM;
- resultado do scan;
- assinatura ou attestation;
- ambiente e horário.
Erros comuns
- Somente latest: não existe rastreabilidade.
- PAT amplo: um vazamento compromete repositórios e pacotes.
- Push em pull request: código não confiável recebe credenciais.
- Build por ambiente: staging e produção executam artefatos diferentes.
- Deploy por tag móvel: o conteúdo muda sem alteração do manifesto.
- Secret em camada: remover depois não apaga o histórico.
- Sem retenção: registry acumula imagens inúteis.
- Sem scan: vulnerabilidades chegam à produção.
Conclusão
O GitHub Container Registry no Node.js integra imagens Docker e OCI ao repositório e ao GitHub Actions. Com GITHUB_TOKEN, metadata-action e build-push-action, a equipe publica versões, commits e imagens multi-arquitetura.
Use permissões mínimas, labels OCI, tags imutáveis e deploy por digest. Gere SBOM, escaneie e promova o mesmo artefato entre ambientes. Assim, o GHCR funciona como parte verificável da supply chain, e não apenas como armazenamento de imagens.


