Docker Registry: hospedando suas próprias imagens
1. Por que rodar seu próprio Registry?
Em pipelines DevOps que utilizam Docker e Kubernetes, o Docker Registry é o componente central para armazenamento e distribuição de imagens de contêiner. Embora serviços como Docker Hub e Amazon ECR sejam amplamente utilizados, cenários específicos exigem uma solução auto-hospedada.
Controle e privacidade dos artefatos
Empresas que desenvolvem software proprietário ou lidam com dados sensíveis não podem depender exclusivamente de registries públicos. Hospedar seu próprio registry garante que imagens nunca saiam do perímetro da rede corporativa.
Redução de latência em ambientes locais/on-premise
Em clusters Kubernetes on-premise ou em ambientes de desenvolvimento, um registry local reduz drasticamente o tempo de pull. Em vez de baixar camadas de centenas de megabytes da internet, as imagens trafegam na rede interna.
Cenários de air-gapped e compliance
Ambientes militares, financeiros ou de infraestrutura crítica frequentemente operam em redes isoladas (air-gapped). Nessas situações, o registry auto-hospedado não é uma opção — é um requisito obrigatório.
2. Instalação e configuração básica do Registry
A maneira mais rápida de iniciar é usando a imagem oficial registry:2:
docker run -d -p 5000:5000 --name registry registry:2
Para persistir dados, monte um volume bind:
docker run -d -p 5000:5000 --name registry \
-v /data/registry:/var/lib/registry \
registry:2
Agora você pode fazer push de uma imagem:
docker pull alpine:latest
docker tag alpine:latest localhost:5000/alpine:latest
docker push localhost:5000/alpine:latest
Para configurações avançadas, crie um arquivo config.yml:
version: 0.1
storage:
filesystem:
rootdirectory: /var/lib/registry
delete:
enabled: true
http:
addr: :5000
Execute com configuração personalizada:
docker run -d -p 5000:5000 --name registry \
-v /data/registry:/var/lib/registry \
-v /data/config.yml:/etc/docker/registry/config.yml \
registry:2
Para armazenamento em nuvem, substitua a seção storage:
storage:
s3:
accesskey: "AKIA..."
secretkey: "..."
region: us-east-1
bucket: meu-registry
rootdirectory: /registry
3. Autenticação e autorização
Habilitar autenticação básica com htpasswd é o primeiro passo para proteger o registry:
# Instalar htpasswd (se necessário)
apt-get install apache2-utils
# Criar arquivo de senhas
htpasswd -Bc /data/auth/htpasswd admin
# Digite a senha quando solicitado
# Executar registry com autenticação
docker run -d -p 5000:5000 --name registry \
-v /data/registry:/var/lib/registry \
-v /data/auth:/auth \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \
registry:2
Para fazer login:
docker login localhost:5000 -u admin -p "sua-senha"
Para integração com LDAP ou OAuth, utilize um proxy reverso (Nginx ou Traefik) que faça a autenticação externa antes de encaminhar para o registry. O controle de acesso por namespace pode ser implementado com políticas no proxy ou usando soluções como Harbor, que oferece RBAC nativo.
4. TLS e segurança na comunicação
Sem TLS, as credenciais e imagens trafegam em texto puro. Para testes, use certificados auto-assinados:
# Gerar certificado auto-assinado
mkdir -p /data/certs
openssl req -newkey rsa:4096 -nodes -sha256 \
-keyout /data/certs/domain.key \
-x509 -days 365 \
-out /data/certs/domain.crt \
-subj "/CN=meuregistry.local"
# Executar registry com TLS
docker run -d -p 443:5000 --name registry \
-v /data/registry:/var/lib/registry \
-v /data/certs:/certs \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
registry:2
Para produção, use Let's Encrypt com Nginx como proxy reverso. Exemplo de configuração Nginx:
server {
listen 443 ssl;
server_name registry.exemplo.com;
ssl_certificate /etc/letsencrypt/live/registry.exemplo.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/registry.exemplo.com/privkey.pem;
location / {
proxy_pass http://localhost:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Para que o Docker client confie em um CA privado, copie o certificado para /etc/docker/certs.d/meuregistry.local:5000/ca.crt em cada node.
5. Gerenciamento de imagens e limpeza
Comandos essenciais via Docker CLI:
# Listar tags de uma imagem (via API)
curl -X GET https://registry.exemplo.com/v2/alpine/tags/list
# Remover um manifesto (marca para garbage collection)
docker manifest rm registry.exemplo.com/alpine:old-tag
Para executar garbage collection e remover blobs órfãos:
docker exec registry /bin/registry garbage-collect \
/etc/docker/registry/config.yml
Políticas de retenção podem ser implementadas com scripts que consultam a API e removem tags antigas. Ferramentas como docker-registry-web ou cr-cleaner automatizam esse processo.
6. Integração com Kubernetes
Para que o Kubernetes possa fazer pull de imagens do registry privado, crie um Secret:
kubectl create secret docker-registry regcred \
--docker-server=registry.exemplo.com \
--docker-username=admin \
--docker-password=senha123 \
--docker-email=admin@exemplo.com
Utilize o Secret nos Pods:
apiVersion: v1
kind: Pod
metadata:
name: meu-app
spec:
containers:
- name: app
image: registry.exemplo.com/meu-app:latest
imagePullSecrets:
- name: regcred
Para deploy do registry no próprio cluster Kubernetes, use um StatefulSet com PVC:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: docker-registry
spec:
serviceName: registry
replicas: 1
selector:
matchLabels:
app: registry
template:
metadata:
labels:
app: registry
spec:
containers:
- name: registry
image: registry:2
env:
- name: REGISTRY_HTTP_TLS_CERTIFICATE
value: /certs/tls.crt
- name: REGISTRY_HTTP_TLS_KEY
value: /certs/tls.key
ports:
- containerPort: 5000
volumeMounts:
- name: data
mountPath: /var/lib/registry
- name: certs
mountPath: /certs
readOnly: true
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 100Gi
7. Monitoramento e boas práticas
O registry expõe métricas no formato Prometheus via endpoint /v2/_catalog e /v2/<name>/blobs/<digest>. Para habilitar métricas completas, configure:
REGISTRY_STORAGE_CACHE_BLOBDESCRIPTOR: inmemory
REGISTRY_HTTP_DEBUG_ADDR: :5001
Configure o Prometheus para coletar métricas do registry e crie dashboards no Grafana para monitorar:
- Número de pulls/pushes por segundo
- Tamanho total do armazenamento
- Latência de requisições
Para logs e auditoria, configure o registry para enviar logs estruturados em JSON:
REGISTRY_LOG_LEVEL: info
REGISTRY_LOG_FORMATTER: json
Backup e restore são simples quando se usa armazenamento filesystem: basta copiar o diretório /var/lib/registry. Para S3, utilize snapshots nativos do provedor.
Boas práticas finais:
- Sempre use TLS em produção
- Implemente autenticação desde o início
- Configure políticas de retenção para evitar crescimento descontrolado
- Monitore o uso de disco e estabeleça alertas
- Faça backup regular do armazenamento e da configuração
Referências
- Docker Registry Documentation — Documentação oficial do Docker Registry com configurações avançadas, autenticação e armazenamento.
- Deploy a Registry Server — Guia oficial para implantação do registry em produção, incluindo TLS e autenticação.
- Kubernetes: Pull an Image from a Private Registry — Documentação oficial do Kubernetes sobre como configurar imagePullSecrets para registries privados.
- Harbor: Open Source Container Registry — Solução completa de registry com RBAC, escaneamento de vulnerabilidades e replicação.
- Prometheus Monitoring for Docker Registry — Guia para configurar métricas e monitoramento do registry com Prometheus.
- Garbage Collection in Docker Registry — Documentação oficial sobre como remover blobs órfãos e liberar espaço.
- Let's Encrypt + Docker Registry with Nginx — Tutorial prático para configurar TLS com Let's Encrypt e proxy reverso Nginx.