Registries e Docker Hub
Um registry é o serviço que guarda e distribui imagens de container. Quando
você faz docker pull nginx, o Docker baixa do Docker Hub; quando faz
docker push, envia para o registry indicado no nome da imagem. Este capítulo
cobre como os nomes de imagem funcionam, autenticação, e como rodar seu próprio
registry.
Anatomia de um nome de imagem
registry.example.com:5000/team-a/my-api:1.4.0
└──────────┬─────────────┘ └──┬─┘ └─┬──┘ └─┬─┘
registry namespace repo tag
- registry — host (e porta). Se omitido, o Docker assume
docker.io(Docker Hub). - namespace/repo — organização/usuário e nome do repositório. No Docker Hub,
imagens sem namespace (ex.:
nginx) são as Docker Official Images, que na verdade moram emdocker.io/library/nginx. - tag — rótulo mutável de uma versão. Se omitida, o Docker usa
latest(que não tem nada de especial — é só a tag padrão).
Exemplos equivalentes:
docker pull nginx
docker pull nginx:latest
docker pull docker.io/library/nginx:latest
Registries mais comuns
| Registry | Host | Observações |
|---|---|---|
| Docker Hub | docker.io |
padrão; tem rate limit para anônimos e conta free |
| GitHub Container Registry | ghcr.io |
integrado a repositórios/Actions do GitHub |
| GitLab Container Registry | registry.gitlab.com |
um registry por projeto GitLab |
| Amazon ECR | <conta>.dkr.ecr.<região>.amazonaws.com |
login via aws ecr get-login-password |
| Google Artifact Registry | <região>-docker.pkg.dev |
login via gcloud auth configure-docker |
| Azure ACR | <nome>.azurecr.io |
az acr login |
| Quay | quay.io |
scanner de vulnerabilidade embutido |
Rate limit do Docker Hub
Para usuários anônimos o Docker Hub limita o número de pulls por janela de
tempo (por IP). Em CI isso estoura fácil. Soluções: autenticar
(docker login), usar um mirror / cache pull-through, ou mover as
imagens base para outro registry.
Autenticação
docker login # Docker Hub
docker login ghcr.io # another registry
docker login registry.example.com:5000
As credenciais ficam em ~/.docker/config.json. Por padrão, em texto
(base64, não criptografado). Para produção/CI, use um credential helper
(docker-credential-pass, docker-credential-ecr-login, etc.) que guarda o
segredo no keychain do SO ou obtém tokens de curta duração.
Em CI, prefira token de acesso (revogável, com escopo) em vez da senha da conta:
echo "$REGISTRY_TOKEN" | docker login ghcr.io -u "$USERNAME" --password-stdin
Sair:
docker logout ghcr.io
docker pull, docker push
docker pull redis:7.4
docker image tag my-api:1.4.0 registry.example.com:5000/team-a/my-api:1.4.0
docker push registry.example.com:5000/team-a/my-api:1.4.0
Você só consegue dar push para um repositório onde tem permissão de escrita —
por isso o nome precisa apontar para o seu namespace/registry, não para
library/....
Rodando seu próprio registry
A imagem oficial registry:2 implementa a Registry HTTP API V2. Para um
laboratório ou um cache interno:
docker container run -d --name registry \
-p 5000:5000 \
-v registry-data:/var/lib/registry \
registry:2
docker tag alpine:3.20 localhost:5000/alpine:3.20
docker push localhost:5000/alpine:3.20
curl -s http://localhost:5000/v2/_catalog
# {"repositories":["alpine"]}
TLS e autenticação
O Docker recusa push/pull por HTTP em qualquer host que não seja
localhost. Para um registry real você precisa de TLS:
docker container run -d --name registry -p 443:5000 \
-v "$(pwd)"/certs:/certs \
-v registry-data:/var/lib/registry \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
registry:2
E autenticação básica com htpasswd (bcrypt):
docker run --rm --entrypoint htpasswd httpd:2 -Bbn admin secret > auth/htpasswd
docker container run -d --name registry -p 443:5000 \
-v "$(pwd)"/auth:/auth -v "$(pwd)"/certs:/certs -v registry-data:/var/lib/registry \
-e REGISTRY_AUTH=htpasswd \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
registry:2
Registry só para desenvolvimento (HTTP)
Se realmente precisar de HTTP sem TLS num host interno, declare-o como
inseguro em /etc/docker/daemon.json de cada cliente:
{ "insecure-registries": ["internal-registry.lab:5000"] }
sudo systemctl restart docker
Evite isso fora de um laboratório.
Cache pull-through do Docker Hub
O registry:2 pode funcionar como espelho/cache de leitura do Docker Hub,
aliviando o rate limit:
docker container run -d --name mirror -p 5000:5000 \
-v mirror-data:/var/lib/registry \
-e REGISTRY_PROXY_REMOTEURL=https://registry-1.docker.io \
registry:2
Nos clientes, /etc/docker/daemon.json:
{ "registry-mirrors": ["http://internal-mirror.lab:5000"] }
Alternativas de registry auto-hospedado
- Harbor — registry completo: RBAC, scan (Trivy) embutido, assinatura, replicação, quotas, retenção. É o padrão de fato para registry interno de empresa.
- Zot — registry OCI leve, só spec nativo, com scan e UI opcionais.
- GitLab / Gitea / Forgejo — trazem um registry embutido junto do Git.
Limpando espaço no registry
Deletar uma tag pela API marca o manifesto como removível, mas os blobs só somem no garbage collection:
docker exec registry bin/registry garbage-collect /etc/docker/registry/config.yml
Habilite REGISTRY_STORAGE_DELETE_ENABLED=true para permitir deleção.