crane is Google's Go library and CLI tool for interacting with container registries at the OCI protocol level — listing tags, copying images, pushing and pulling manifests, and validating layer integrity without needing a Docker daemon. It's used in CI/CD pipelines for image promotion, in GitOps automation for registry synchronization, and in platform tooling for image auditing. When the container registry crane targets goes down, image promotion jobs fail silently, GitOps sync loops stop updating deployments, and security scanning pipelines miss new images entirely. Vigilmon gives you external visibility into the registry endpoints crane depends on, TLS certificate health for the registries, and heartbeat monitoring for the automation pipelines that use crane.
What You'll Build
- HTTP monitors on the container registry API endpoints crane connects to
- SSL certificate monitors for each registry's HTTPS endpoint
- TCP monitors on registry ports for network-layer health
- Heartbeat monitors for crane-based CI/CD automation jobs
- Alerting runbook mapping crane failure modes to registry health issues
Prerequisites
- crane CLI installed (
go install github.com/google/go-containerregistry/cmd/crane@latest) - One or more container registries (Harbor, Docker Hub, ECR, GCR, GHCR, or self-hosted)
- A free account at vigilmon.online
Step 1: Understand the crane + Registry Health Surface
crane communicates with registries using the OCI Distribution Specification (Docker Registry HTTP API v2). Every crane command ultimately makes requests to these API endpoints:
# Test registry connectivity with crane
crane catalog registry.example.com
# Expected: list of repositories
# Check a specific image manifest
crane manifest registry.example.com/myapp:latest
# Expected: JSON manifest
# Validate an image exists and its layers are accessible
crane digest registry.example.com/myapp:latest
# Expected: sha256:... digest
# Ping the registry (checks v2 API availability without auth)
crane ls registry.example.com/nonexistent 2>&1 | head -5
# A connection refused error means the registry is down
# An auth error or 404 means the registry is up
# Check crane's view of the registry API
curl -I https://registry.example.com/v2/
# Expected: 200 or 401 (registry up); connection refused or 5xx (registry down)
The key signals to monitor:
- Registry v2 API availability (the core endpoint crane uses)
- TLS certificate validity on the registry
- Registry storage backend health
- Automation pipeline heartbeats for crane-based jobs
Step 2: Monitor the Registry v2 API
The /v2/ endpoint is the universal health signal for any OCI-compliant registry. crane, Docker, Kubernetes, and every other container toolchain uses this endpoint first:
# Test the v2 API
curl -I https://registry.example.com/v2/
# Expected: 200 OK or 401 Unauthorized (both mean the registry is running)
# Harbor health endpoint (includes component checks)
curl https://harbor.example.com/api/v2.0/health
# Expected: {"status":"healthy","components":[...]}
# Docker Hub (public registry)
curl https://registry-1.docker.io/v2/
# Expected: 401 (requires auth — confirms Docker Hub is reachable)
# AWS ECR (public registry)
curl https://public.ecr.aws/v2/
# Expected: 200 or 401
# GitHub Container Registry
curl https://ghcr.io/v2/
# Expected: 401
Create a Vigilmon monitor for your primary registry:
- Log in to Vigilmon → Add Monitor → HTTP.
- URL:
https://registry.example.com/v2/. - Check interval: 60 seconds.
- Response timeout: 10 seconds.
- Expected status codes:
200, 401(both indicate the registry is operational). - Label:
Container registry v2 API. - Click Save.
For Harbor, add a dedicated health monitor on the full component health endpoint:
- Add Monitor → HTTP.
- URL:
https://harbor.example.com/api/v2.0/health. - Expected status:
200. - Keyword:
healthy. - Label:
Harbor health. - Click Save.
Step 3: Monitor the Registry TCP Port
Add a TCP monitor to detect network-layer failures that the HTTP monitor might miss — for example, when the registry process is down but a load balancer returns a maintenance page:
# Test TCP connectivity to the registry
nc -zv registry.example.com 443
# Expected: succeeded
# For registries on non-standard ports
nc -zv registry.example.com 5000
- Add Monitor → TCP.
- Host:
registry.example.com. - Port:
443. - Check interval: 60 seconds.
- Label:
Container registry TCP (443). - Click Save.
For self-hosted registries on port 5000:
- Add Monitor → TCP.
- Host:
registry.example.com. - Port:
5000. - Label:
Container registry TCP (5000). - Click Save.
A TCP success with an HTTP failure isolates the problem to the application layer — the network connection is alive but the registry process is broken.
Step 4: Monitor TLS Certificates
crane connects to HTTPS registries and validates TLS certificates by default. An expired certificate on your registry causes every crane command to fail with a TLS verification error — breaking image promotion, sync, and auditing pipelines simultaneously:
# Check the registry certificate directly
echo | openssl s_client -connect registry.example.com:443 2>/dev/null | \
openssl x509 -noout -dates
# notAfter=Dec 31 00:00:00 2026 GMT
# Use crane to verify the TLS connection
crane ls registry.example.com/myapp 2>&1 | head -3
# If TLS is broken: "x509: certificate has expired or is not yet valid"
# Check certificate for insecure registries crane uses with --insecure flag
# (these should still be monitored for expiry even if crane bypasses TLS verification)
- Add Monitor → SSL Certificate.
- Domain:
registry.example.com. - Alert when expiry is within: 30 days.
- Alert again: 14 days, 7 days, 3 days, 1 day.
- Click Save.
Monitor every registry endpoint your crane-based pipelines use:
# List all registries referenced in your crane scripts
grep -rE 'crane (copy|push|pull|ls|catalog|manifest|digest)' .github/ scripts/ \
| grep -oP '[a-z0-9.-]+\.(io|com|example\.com|ecr\.amazonaws\.com)[:/][^\s"]+' \
| sed 's|/.*||' | sort -u
# Output: list of registry hostnames to monitor
Add an SSL certificate monitor for each registry hostname you identify.
Step 5: Heartbeat Monitoring for crane CI/CD Automation
crane is most commonly used in automation: image promotion pipelines, nightly registry sync jobs, and tag cleanup crons. These pipelines have no HTTP endpoint to probe — only a successful run at the expected frequency. Vigilmon's heartbeat monitor detects when they stop running:
Image Promotion Pipeline
A pipeline that promotes images from a staging registry to production after CI passes:
#!/bin/bash
# promote-image.sh
# Promote the image from staging to production
crane copy \
staging.registry.example.com/myapp:${GIT_SHA} \
production.registry.example.com/myapp:${GIT_SHA}
crane tag \
production.registry.example.com/myapp:${GIT_SHA} \
latest
# Signal success to Vigilmon
curl -s https://vigilmon.online/heartbeat/abc123
Set up the heartbeat monitor:
- In Vigilmon → Add Monitor → Cron Heartbeat.
- Expected interval:
1440minutes (for a pipeline that runs on every main branch merge, expected at least daily). - Copy the heartbeat URL:
https://vigilmon.online/heartbeat/abc123. - Add the
curlcall to your promotion script after successful crane commands. - Click Save.
Nightly Registry Sync Job
A cron job that mirrors images from an upstream registry to your internal registry:
#!/bin/bash
# registry-sync.sh
IMAGES=(
"nginx:1.25"
"postgres:16"
"redis:7"
)
for IMAGE in "${IMAGES[@]}"; do
crane copy "docker.io/library/${IMAGE}" "registry.example.com/${IMAGE}"
done
# Ping heartbeat only after all images synced successfully
curl -s https://vigilmon.online/heartbeat/def456
- Add Monitor → Cron Heartbeat.
- Expected interval:
1440minutes (daily sync). - Add the
curlcall at the end of your sync script. - Label:
Nightly registry mirror. - Click Save.
GitHub Actions with crane
For pipelines running in GitHub Actions:
# .github/workflows/promote.yml
name: Promote image
on:
push:
branches: [main]
jobs:
promote:
runs-on: ubuntu-latest
steps:
- name: Install crane
run: |
CRANE_VERSION=$(curl -s https://api.github.com/repos/google/go-containerregistry/releases/latest | jq -r .tag_name)
curl -L "https://github.com/google/go-containerregistry/releases/download/${CRANE_VERSION}/go-containerregistry_Linux_x86_64.tar.gz" | tar xz crane
sudo mv crane /usr/local/bin/
- name: Promote image
run: |
crane auth login staging.registry.example.com -u ${{ secrets.REGISTRY_USER }} -p ${{ secrets.REGISTRY_PASS }}
crane copy staging.registry.example.com/myapp:${{ github.sha }} production.registry.example.com/myapp:${{ github.sha }}
- name: Ping Vigilmon heartbeat
if: success()
run: curl -s https://vigilmon.online/heartbeat/abc123
Step 6: Validate Image Availability with crane
Use crane in a synthetic monitoring script that tests whether specific critical images remain pullable. Run this as a scheduled job and wrap it with a Vigilmon heartbeat:
#!/bin/bash
# validate-images.sh — run every 30 minutes via cron
CRITICAL_IMAGES=(
"registry.example.com/api-server:production"
"registry.example.com/worker:production"
"registry.example.com/scheduler:production"
)
FAILED=0
for IMAGE in "${CRITICAL_IMAGES[@]}"; do
if ! crane digest "${IMAGE}" > /dev/null 2>&1; then
echo "FAIL: ${IMAGE} is not pullable"
FAILED=1
else
echo "OK: ${IMAGE}"
fi
done
if [ "${FAILED}" -eq 0 ]; then
# All images validated — ping Vigilmon
curl -s https://vigilmon.online/heartbeat/ghi789
else
echo "Image validation failed — not pinging heartbeat"
exit 1
fi
Set up the cron:
# /etc/cron.d/crane-image-validation
*/30 * * * * deploy /opt/scripts/validate-images.sh >> /var/log/crane-validation.log 2>&1
- Add Monitor → Cron Heartbeat.
- Expected interval:
35minutes (30-minute schedule + 5-minute grace period). - Label:
Critical image availability check. - Click Save.
If the registry goes down or a critical image is deleted, the validation script fails and the heartbeat goes silent — Vigilmon fires after 35 minutes.
Step 7: Configure Alerting
In Vigilmon under Settings → Notifications, configure alert channels and response runbooks:
| Monitor | Trigger | Immediate action |
|---|---|---|
| Registry v2 API | Non-200/401 or timeout | Check registry pod health; verify storage backend (S3/disk) is accessible; crane commands will fail cluster-wide |
| Harbor health | Non-200 or unhealthy keyword | Check Harbor components: kubectl get pods -n harbor; identify the unhealthy component in the JSON response |
| Registry TCP | Connection refused | Check load balancer / ingress; check registry service port; network firewall rules |
| TLS certificate | < 30 days | Rotate certificate; test with crane ls registry.example.com/test after rotation |
| Image promotion heartbeat | Missed ping | Check CI/CD pipeline logs; verify staging registry has the source image; check for crane auth errors |
| Nightly sync heartbeat | Missed ping | Check cron job logs: journalctl -u registry-sync; verify upstream registry connectivity |
| Image validation heartbeat | Missed ping | Run crane digest manually for each critical image; check for deleted or overwritten production tags |
Common crane + Registry Failure Modes and What Vigilmon Catches
| Scenario | Vigilmon signal | |---|---| | Registry database crash | v2 API fires with 500; all crane commands fail | | Registry storage backend (S3/GCS/disk) full | v2 API returns errors on write; push commands fail; read commands may still work | | TLS certificate expired on registry | SSL monitor fires at 30-day threshold; crane returns TLS errors on expiry | | Image promotion pipeline stalls | Heartbeat monitor fires after expected interval; production images stop updating | | Nightly sync cron misconfigured | Sync heartbeat fires; internal registry drifts from upstream; old image versions cached | | Harbor core pod OOM-killed | Harbor health monitor fires with unhealthy core component | | Registry behind expired load balancer cert | SSL monitor fires; TCP monitor stays green (isolating the TLS layer) | | Critical production image accidentally deleted | Image validation heartbeat fires after next scheduled check | | Registry rate limit hit (Docker Hub free tier) | v2 API returns 429; crane copy jobs in CI fail with pull limit errors | | Auth token expiry in long-running crane job | Individual crane commands fail with 401; heartbeat goes silent |
crane brings the power of the OCI distribution protocol to shell scripts, CI/CD pipelines, and platform automation — but it's only as reliable as the registries it talks to. Vigilmon gives you external visibility into those registries' availability, TLS health, and the automation pipelines that depend on them. When a registry storage backend fills up and image pushes start failing, or a nightly sync stops running because of a cron misconfiguration, Vigilmon alerts you before engineers start seeing mysterious pull failures in production deployments.
Start monitoring your container registries in under 5 minutes — register free at vigilmon.online.