Agent-almanac setup-container-registry
git clone https://github.com/pjt222/agent-almanac
T=$(mktemp -d) && git clone --depth=1 https://github.com/pjt222/agent-almanac "$T" && mkdir -p ~/.claude/skills && cp -r "$T/i18n/es/skills/setup-container-registry" ~/.claude/skills/pjt222-agent-almanac-setup-container-registry-bcee43 && rm -rf "$T"
i18n/es/skills/setup-container-registry/SKILL.mdConfigurar Registro de Contenedores
Configura registros de contenedores listos para producción con escaneo de seguridad, control de acceso e integración automatizada con CI/CD.
Cuándo Usar
- Al configurar un registro de contenedores privado para una organización
- Al migrar de Docker Hub a registros autoalojados o alternativos
- Al implementar escaneo de vulnerabilidades de imágenes en pipelines CI/CD
- Al gestionar imágenes multi-arquitectura (amd64, arm64) con manifiestos
- Al aplicar la firma de imágenes y la verificación de procedencia
- Al configurar limpieza automática de imágenes y políticas de retención
Entradas
- Requerido: Docker o Podman instalado localmente
- Requerido: Credenciales del registro (tokens de acceso personal, cuentas de servicio)
- Opcional: Infraestructura autoalojada para el despliegue de Harbor
- Opcional: Clúster Kubernetes para integración con el registro
- Opcional: Cosign/Notary para la firma de imágenes
- Opcional: Trivy o Clair para escaneo de vulnerabilidades
Procedimiento
Consulta Ejemplos Extendidos para archivos de configuración completos y plantillas.
Paso 1: Configurar GitHub Container Registry (ghcr.io)
Configura GitHub Container Registry con tokens de acceso personal e integración CI/CD.
# Create GitHub Personal Access Token # Go to: Settings → Developer settings → Personal access tokens → Tokens (classic) # Required scopes: write:packages, read:packages, delete:packages # Login to ghcr.io echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin # Verify login docker info | grep -A 5 "Registry:" # Tag image for ghcr.io docker tag myapp:latest ghcr.io/USERNAME/myapp:latest docker tag myapp:latest ghcr.io/USERNAME/myapp:v1.0.0 # Push image docker push ghcr.io/USERNAME/myapp:latest docker push ghcr.io/USERNAME/myapp:v1.0.0 # Configure in GitHub Actions cat > .github/workflows/docker-build.yml <<'EOF' name: Build and Push Docker Image on: push: branches: [main] tags: ['v*'] env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} jobs: build-and-push: runs-on: ubuntu-latest permissions: contents: read packages: write steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Log in to GitHub Container Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Extract metadata id: meta uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | type=ref,event=branch type=ref,event=pr type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=sha,prefix={{branch}}- - name: Build and push uses: docker/build-push-action@v5 with: context: . platforms: linux/amd64,linux/arm64 push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max EOF # Make package public (default is private) # Go to: github.com/USERNAME?tab=packages → Select package → Package settings → Change visibility # Pull image (public packages don't require authentication) docker pull ghcr.io/USERNAME/myapp:latest
Esperado: El token de GitHub tiene permisos de paquete. El inicio de sesión en Docker se realiza correctamente. Las imágenes se envían a ghcr.io con el etiquetado adecuado. El flujo de trabajo de GitHub Actions construye imágenes multi-arquitectura con etiquetado automatizado. La visibilidad del paquete está configurada correctamente.
En caso de fallo: Para errores de autenticación, verifica que el token tenga el ámbito
write:packages y no haya caducado. Para fallos de envío, comprueba que el nombre del repositorio coincida con el nombre de la imagen (distingue mayúsculas de minúsculas). Para fallos del flujo de trabajo, verifica que permissions: packages: write esté configurado. Para paquetes públicos no accesibles, espera hasta 10 minutos para que el cambio de visibilidad se propague.
Paso 2: Configurar Docker Hub con Compilaciones Automatizadas
Configura el repositorio de Docker Hub con tokens de acceso y escaneo de vulnerabilidades.
# Create Docker Hub access token # Go to: hub.docker.com → Account Settings → Security → New Access Token # Login to Docker Hub echo $DOCKERHUB_TOKEN | docker login -u USERNAME --password-stdin # Create repository # Go to: hub.docker.com → Repositories → Create Repository # Select: public or private, enable vulnerability scanning (Pro/Team plan) # Tag for Docker Hub docker tag myapp:latest USERNAME/myapp:latest docker tag myapp:latest USERNAME/myapp:v1.0.0 # Push to Docker Hub docker push USERNAME/myapp:latest docker push USERNAME/myapp:v1.0.0 # Configure automated builds (legacy feature, deprecated) # Modern approach: Use GitHub Actions with Docker Hub cat > .github/workflows/dockerhub.yml <<'EOF' name: Docker Hub Push on: push: branches: [main] tags: ['v*'] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push uses: docker/build-push-action@v5 with: context: . platforms: linux/amd64,linux/arm64,linux/arm/v7 push: true tags: | ${{ secrets.DOCKERHUB_USERNAME }}/myapp:latest ${{ secrets.DOCKERHUB_USERNAME }}/myapp:${{ github.ref_name }} build-args: | BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') VCS_REF=${{ github.sha }} - name: Update Docker Hub description uses: peter-evans/dockerhub-description@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} repository: ${{ secrets.DOCKERHUB_USERNAME }}/myapp readme-filepath: ./README.md EOF # View vulnerability scan results # Go to: hub.docker.com → Repository → Tags → View scan results # Configure webhook for automated triggers # Go to: Repository → Webhooks → Add webhook WEBHOOK_URL="https://example.com/webhook" curl -X POST https://hub.docker.com/api/content/v1/repositories/USERNAME/myapp/webhooks \ -H "Authorization: Bearer $DOCKERHUB_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"name\":\"CI Trigger\",\"webhook_url\":\"$WEBHOOK_URL\"}"
Esperado: Token de acceso de Docker Hub creado con permisos de lectura/escritura. Las imágenes se envían correctamente con soporte multi-arquitectura. Los escaneos de vulnerabilidades se ejecutan automáticamente (si están habilitados). El README se sincroniza desde GitHub. Los webhooks se activan al enviar imágenes.
En caso de fallo: Para errores de límite de velocidad, actualiza al plan Pro o implementa una caché de extracción. Para fallos de escaneo, verifica que el plan incluya escaneo (no disponible en el nivel gratuito). Para fallos de compilación multi-arquitectura, asegúrate de que QEMU esté instalado con
docker run --privileged --rm tonistiigi/binfmt --install all. Para fallos de webhook, verifica que el punto de conexión sea accesible públicamente y devuelva 200 OK.
Paso 3: Desplegar Harbor Registro Autoalojado
Instala Harbor con Helm para un registro empresarial con RBAC y replicación.
# Add Harbor Helm repository helm repo add harbor https://helm.gopharbor.io helm repo update # Create namespace kubectl create namespace harbor # Create values file cat > harbor-values.yaml <<EOF expose: type: ingress tls: enabled: true certSource: secret secret: secretName: harbor-tls ingress: hosts: core: harbor.example.com className: nginx annotations: cert-manager.io/cluster-issuer: letsencrypt-prod externalURL: https://harbor.example.com persistence: enabled: true persistentVolumeClaim: registry: size: 200Gi storageClass: gp3 database: size: 10Gi storageClass: gp3 harborAdminPassword: "ChangeMe123!" database: type: internal # Use external: postgres for production redis: type: internal # Use external: redis for production trivy: enabled: true skipUpdate: false notary: enabled: true # Image signing chartmuseum: enabled: true # Helm chart storage EOF # Install Harbor helm install harbor harbor/harbor \ --namespace harbor \ --values harbor-values.yaml \ --timeout 10m # Wait for pods to be ready kubectl get pods -n harbor -w # Get admin password kubectl get secret -n harbor harbor-core -o jsonpath='{.data.HARBOR_ADMIN_PASSWORD}' | base64 -d # Access Harbor UI echo "Harbor UI: https://harbor.example.com" echo "Username: admin" # Login via Docker CLI docker login harbor.example.com # Username: admin # Password: (from above) # Create project via API curl -u "admin:$HARBOR_PASSWORD" -X POST \ https://harbor.example.com/api/v2.0/projects \ -H "Content-Type: application/json" \ -d '{ "project_name": "myapp", "public": false, "metadata": { "auto_scan": "true", "severity": "high", "enable_content_trust": "true" } }' # Tag and push to Harbor docker tag myapp:latest harbor.example.com/myapp/app:latest docker push harbor.example.com/myapp/app:latest # Configure robot account for CI/CD # UI: Administration → Robot Accounts → New Robot Account # Permissions: Pull, Push to specific projects # Use robot account in CI/CD docker login harbor.example.com -u 'robot$myapp-ci' -p "$ROBOT_TOKEN"
Esperado: Harbor se despliega en Kubernetes con PostgreSQL y Redis. Ingress configurado con TLS. Interfaz de administración accesible. Proyectos creados con escaneo de vulnerabilidades habilitado. Las cuentas robot proporcionan autenticación para CI/CD. Trivy escanea imágenes al enviarlas.
En caso de fallo: Para errores de conexión a la base de datos, comprueba los registros del pod de PostgreSQL con
kubectl logs -n harbor harbor-database-0. Para problemas de Ingress, verifica que el DNS apunte al LoadBalancer y que cert-manager haya emitido el certificado. Para fallos de Trivy, comprueba si la base de datos de vulnerabilidades se descargó correctamente. Para problemas de almacenamiento, verifica que los PVCs estén vinculados con kubectl get pvc -n harbor.
Paso 4: Implementar Estrategia de Etiquetado de Imágenes y Políticas de Retención
Configura el versionado semántico, etiquetas inmutables y limpieza automática.
# Tagging best practices # 1. Semantic versioning docker tag myapp:latest harbor.example.com/myapp/app:v1.2.3 docker tag myapp:latest harbor.example.com/myapp/app:v1.2 docker tag myapp:latest harbor.example.com/myapp/app:v1 docker tag myapp:latest harbor.example.com/myapp/app:latest # ... (see EXAMPLES.md for complete configuration)
Esperado: Imágenes etiquetadas con versiones semánticas, SHAs de confirmación y etiquetas de entorno. Las políticas de retención limpian automáticamente imágenes antiguas basándose en antigüedad, actividad de extracción o límites de cantidad. Las etiquetas de producción (patrón v*) se retienen más tiempo que las ramas de desarrollo. Las imágenes sin etiquetar se eliminan para ahorrar almacenamiento.
En caso de fallo: Para que la retención no se active, verifica la sintaxis del programa cron y la configuración de zona horaria de Harbor. Para la eliminación accidental de imágenes de producción, implementa etiquetas inmutables con las reglas de inmutabilidad de etiquetas de Harbor. Si el almacenamiento sigue creciendo, verifica que la retención de artefactos incluye gráficos Helm y otros artefactos OCI. Para conflictos de política, asegúrate de que las reglas de retención usen el algoritmo
or y no se contradigan entre sí.
Paso 5: Configurar Secretos de Extracción de Imágenes en Kubernetes
Configura la autenticación del registro para clústeres Kubernetes.
# Create Docker registry secret kubectl create secret docker-registry ghcr-secret \ --docker-server=ghcr.io \ --docker-username=USERNAME \ --docker-password=$GITHUB_TOKEN \ --docker-email=user@example.com \ # ... (see EXAMPLES.md for complete configuration)
Esperado: Secretos de extracción de imágenes creados en los namespaces de destino. Los Pods extraen correctamente imágenes de registros privados. Las cuentas de servicio incluyen imagePullSecrets. Sin errores ImagePullBackOff.
En caso de fallo: Para errores de autenticación, verifica las credenciales manualmente con
docker login. Para secreto no encontrado, comprueba que el namespace coincida con el namespace del Pod. Si sigue fallando, decodifica el secreto y verifica la estructura JSON con kubectl get secret ghcr-secret -o jsonpath='{.data.\.dockerconfigjson}' | base64 -d | jq. Para vencimiento del token, rota las credenciales y actualiza los secretos.
Paso 6: Habilitar el Escaneo de Vulnerabilidades y la Firma de Imágenes
Integra el escaneo con Trivy y Cosign para la procedencia de imágenes.
# Install Trivy CLI wget https://github.com/aquasecurity/trivy/releases/latest/download/trivy_0.47.0_Linux-64bit.tar.gz tar zxvf trivy_0.47.0_Linux-64bit.tar.gz sudo mv trivy /usr/local/bin/ # Scan local image # ... (see EXAMPLES.md for complete configuration)
Esperado: Los escaneos de Trivy detectan vulnerabilidades con clasificaciones de gravedad. Los resultados SARIF se cargan en la pestaña de Seguridad de GitHub. Las vulnerabilidades críticas fallan las compilaciones CI/CD. Cosign firma imágenes con par de claves o sin clave (Fulcio). La verificación se realiza correctamente para imágenes firmadas. Kyverno bloquea imágenes sin firmar en Kubernetes.
En caso de fallo: Para fallos de descarga de la base de datos de Trivy, ejecuta
trivy image --download-db-only. Para falsos positivos, crea un archivo .trivyignore con IDs de CVE y justificaciones. Para fallos de firma de Cosign, verifica que el resumen de la imagen no haya cambiado (las firmas se aplican a resúmenes específicos, no a etiquetas). Para fallos de política de Kyverno, comprueba que el patrón de referencia de imagen coincida con los nombres de imagen reales. Para la firma sin clave, verifica que el token OIDC tenga permisos suficientes.
Validación
- Registro accesible mediante inicio de sesión de Docker CLI
- Las imágenes se envían y extraen correctamente con la autenticación adecuada
- Las imágenes multi-arquitectura se construyen y el manifiesto se crea
- El escaneo de vulnerabilidades se ejecuta automáticamente al enviar imágenes
- Las políticas de retención limpian imágenes antiguas según programación
- Los clústeres Kubernetes pueden extraer imágenes mediante imagePullSecrets
- Las firmas de imágenes se verifican antes del despliegue
- Las notificaciones webhook se activan en actualizaciones de imágenes
- La interfaz del registro muestra resultados de escaneo y metadatos de artefactos
Errores Comunes
-
Imágenes públicas por defecto: Los paquetes de GitHub son privados por defecto, Docker Hub público. Verifica la configuración de visibilidad según los requisitos de seguridad.
-
Vencimiento de tokens: Los tokens de acceso personal vencen, rompiendo el CI/CD. Usa tokens sin vencimiento para la automatización o implementa rotación.
-
Acumulación de imágenes sin etiquetar: El proceso de compilación crea imágenes sin etiquetar que consumen almacenamiento. Habilita la limpieza automática de artefactos sin etiquetar.
-
Soporte multi-arquitectura faltante: Las compilaciones son solo para amd64, fallando en instancias ARM. Usa
con la opcióndocker buildx
para compilaciones multiplataforma.--platform -
Sin protección contra límite de velocidad: Las cuentas gratuitas de Docker Hub tienen un límite de 100 extracciones/6h. Implementa una caché de extracción o actualiza el plan.
-
Etiquetas mutables: La etiqueta
sobreescrita rompe la reproducibilidad. Usa etiquetas inmutables (SHA de confirmación, versión semántica) para producción.latest -
Comunicación de registro insegura: Registro autoalojado sin TLS. Usa siempre HTTPS con certificados válidos.
-
Sin control de acceso: Una única credencial compartida entre equipos. Implementa RBAC con cuentas robot específicas por proyecto.
Habilidades Relacionadas
- Construcción de imágenes de contenedor para el registrocreate-r-dockerfile
- Compilaciones de imágenes eficientes para envío al registrooptimize-docker-build-cache
- Envío automatizado al registro en CI/CDbuild-ci-cd-pipeline
- Extracción de imágenes del registrodeploy-to-kubernetes
- Promoción de imágenes entre registrosimplement-gitops-workflow