GitHub Container Registry (GHCR)

GitHub Container Registry (ghcr.io) é o registry de containers integrado ao GitHub, sem limite de pulls, autenticação com o mesmo token do GitHub Actions e visibilidade configurável por package. É a alternativa gratuita e mais conveniente ao Docker Hub para projetos hospedados no GitHub.

Autenticar e fazer push manual no GHCR

Para publicar imagens a partir da máquina local:

bash
# 1. Criar Personal Access Token com permissão write:packages
#    github.com → Settings → Developer settings → Tokens → Classic
#    Scopes: write:packages, read:packages, delete:packages

# 2. Login no GHCR
echo "SEU_GITHUB_TOKEN" | docker login ghcr.io -u SEU_USUARIO --password-stdin

# 3. Build e tag da imagem
docker build -t ghcr.io/SEU_USUARIO/minha-api:latest .
docker build -t ghcr.io/SEU_USUARIO/minha-api:1.2.3 .

# 4. Push
docker push ghcr.io/SEU_USUARIO/minha-api:latest
docker push ghcr.io/SEU_USUARIO/minha-api:1.2.3

# 5. Ver pacotes publicados:
# github.com/SEU_USUARIO → Packages

# 6. Pull da imagem (requer login se privado)
docker pull ghcr.io/SEU_USUARIO/minha-api:latest

Configurar visibilidade e acesso

Controle quem pode acessar suas imagens:

bash
# GHCR suporta três níveis de visibilidade:
# Public: qualquer um pode fazer pull (sem autenticação)
# Private: apenas usuários autorizados (requer login)
# Internal: apenas membros da organização

# Alterar via interface:
# github.com/SEU_USUARIO → Packages → minha-api → Package settings
# Change package visibility

# Vincular package ao repositório:
# Package settings → Connect Repository → selecionar repo
# Isso habilita herança de permissões do repositório

# Gerenciar via API:
curl -X PATCH \
  -H "Authorization: Bearer SEU_TOKEN" \
  -H "Accept: application/vnd.github.v3+json" \
  https://api.github.com/user/packages/container/minha-api/versions/ID \
  -d '{"metadata": {"container": {"tags": ["latest", "stable"]}}}'

Usar imagem do GHCR em docker-compose na VPS

Configure a VPS para puxar imagens privadas do GHCR:

yaml
# Na VPS — login permanente no GHCR
# Criar token com apenas read:packages
echo "GITHUB_TOKEN_READONLY" | docker login ghcr.io -u USUARIO --password-stdin

# Verificar que o login foi salvo:
cat ~/.docker/config.json | grep ghcr

# docker-compose.yml na VPS:
services:
  app:
    image: ghcr.io/usuario/minha-api:main
    restart: always
    pull_policy: always           # sempre verificar nova versão no pull

# Atualizar imagem e reiniciar:
docker compose pull app
docker compose up -d --no-deps app

# Para automação sem armazenar token na VPS:
# No script de deploy chamado pelo GitHub Actions:
# ssh deploy@VPS "echo '$GITHUB_TOKEN' | docker login ghcr.io -u $GITHUB_USER --password-stdin && docker compose pull && docker compose up -d"

Limpeza automática de imagens antigas

Mantenha o storage organizado deletando versões antigas:

yaml
# .github/workflows/cleanup-packages.yml
name: Limpar imagens antigas do GHCR

on:
  schedule:
    - cron: '0 3 * * 0'    # todo domingo às 3h
  workflow_dispatch:

jobs:
  cleanup:
    runs-on: ubuntu-latest
    permissions:
      packages: write

    steps:
      - name: Deletar versões sem tag (untagged)
        uses: actions/delete-package-versions@v5
        with:
          package-name: 'minha-api'
          package-type: 'container'
          delete-only-untagged-versions: 'true'
          min-versions-to-keep: 0

      - name: Manter apenas últimas 10 versões
        uses: actions/delete-package-versions@v5
        with:
          package-name: 'minha-api'
          package-type: 'container'
          min-versions-to-keep: 10
          ignore-versions: '^(latest|main|stable|v\d+\.\d+\.\d+)
#x27;

Labels e metadata nas imagens

Adicione metadata OCI às imagens para rastreabilidade:

dockerfile
# Dockerfile — labels OCI (padrão da indústria)
FROM node:22-alpine

LABEL org.opencontainers.image.title="Minha API"
LABEL org.opencontainers.image.description="API REST da Minha Aplicação"
LABEL org.opencontainers.image.url="https://github.com/usuario/minha-api"
LABEL org.opencontainers.image.source="https://github.com/usuario/minha-api"
LABEL org.opencontainers.image.licenses="MIT"

# No GitHub Actions — metadata-action adiciona automaticamente:
# org.opencontainers.image.created
# org.opencontainers.image.revision (git sha)
# org.opencontainers.image.version

# Verificar labels de uma imagem:
docker inspect ghcr.io/usuario/minha-api:latest | \
  python3 -m json.tool | grep -A 20 '"Labels"'

Não quer configurar manualmente?

Implante o VPS em menos de 5 minutos com a Runstack. Infraestrutura da OPEN Datacenter, com servidores em São Paulo.

Perguntas frequentes

Repositórios públicos: storage e pulls ilimitados e gratuitos. Repositórios privados: incluídos na cota de storage do plano GitHub (1 GB no Free, 2 GB no Pro, 50 GB no Team). Pulls de imagens privadas contam para a bandwidth incluída no plano. Para uso comercial intenso: avalie GitHub Team ou Enterprise.

docker pull docker.io/usuario/app:tag; docker tag docker.io/usuario/app:tag ghcr.io/usuario/app:tag; docker push ghcr.io/usuario/app:tag. Para migração em massa: use crane ou skopeo que copiam imagens entre registries sem pull/push completo, preservando layers.

Sim. Para organizações: ghcr.io/ORG_NAME/IMAGE_NAME. O GITHUB_TOKEN do Actions deve ter permissão packages:write na organização. Membros da organização podem acessar imagens internas (visibility: internal) sem PAT adicional.

Cada push gera uma tag por sha (sha-abc1234) além das tags semânticas. Para rollback: docker compose down app; docker compose up -d com image: ghcr.io/usuario/app:sha-COMMIT_ANTERIOR no docker-compose.yml, ou docker pull ghcr.io/usuario/app:sha-COMMIT_ANTERIOR && docker compose up -d.

Não, diferente do cache do GitHub Actions (7 dias), imagens no GHCR são armazenadas indefinidamente até você deletar. O único custo é o storage (contado na cota do plano). Recomenda-se limpeza periódica de versões antigas não referenciadas.