Document both registry modes: pull-through cache + private images

- Added Zot config.json template showing sync extension for pull-through
- Documented namespace convention:
  - registry.../docker.io/* → cached from Docker Hub
  - registry.../ghcr.io/* → cached from GHCR
  - registry.../blumeops/* → private images
- Added testing steps for both pull-through and private push
- Updated zk template with namespace table and build/push commands
- Updated verification checklist

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Erich Blume 2026-01-17 13:51:46 -08:00
commit adba123ad4

View file

@ -171,8 +171,8 @@ zot_config_dir: "/Users/erichblume/.config/zot"
zot_port: 5000
zot_log_dir: "/Users/erichblume/Library/Logs"
# Pull-through cache configuration
zot_registries:
# Pull-through cache registries (on-demand sync)
zot_sync_registries:
- name: docker.io
url: https://registry-1.docker.io
- name: ghcr.io
@ -181,6 +181,53 @@ zot_registries:
url: https://quay.io
```
**Zot config.json template** (key sections):
```json
{
"storage": {
"rootDirectory": "/Users/erichblume/zot"
},
"http": {
"address": "0.0.0.0",
"port": "5000"
},
"extensions": {
"sync": {
"enable": true,
"registries": [
{
"urls": ["https://registry-1.docker.io"],
"content": [{"prefix": "**"}],
"onDemand": true,
"tlsVerify": true
},
{
"urls": ["https://ghcr.io"],
"content": [{"prefix": "**"}],
"onDemand": true,
"tlsVerify": true
}
]
}
}
}
```
**Two modes of operation:**
1. **Pull-through cache** (automatic): When you pull `registry.tail8d86e.ts.net/docker.io/library/nginx:latest`, Zot fetches from Docker Hub and caches locally. Subsequent pulls are local.
2. **Private images** (manual push): Push your own images to any path NOT matching a sync prefix:
```bash
# From gilbert (after building)
podman push myapp:v1 registry.tail8d86e.ts.net/blumeops/myapp:v1
```
**Namespace convention:**
- `registry.tail8d86e.ts.net/docker.io/*` → cached from Docker Hub
- `registry.tail8d86e.ts.net/ghcr.io/*` → cached from GHCR
- `registry.tail8d86e.ts.net/blumeops/*` → private images (built by you/Woodpecker)
**LaunchAgent template (zot.plist.j2):**
```xml
<?xml version="1.0" encoding="UTF-8"?>
@ -219,6 +266,18 @@ ssh indri 'curl -s http://localhost:5000/v2/_catalog'
# Check logs for errors
ssh indri 'tail -20 ~/Library/Logs/mcquack.zot.err.log'
# Test pull-through cache (from indri)
ssh indri 'podman pull localhost:5000/docker.io/library/alpine:latest'
ssh indri 'curl -s http://localhost:5000/v2/_catalog'
# Expected: {"repositories":["docker.io/library/alpine"]}
# Test private image push (from gilbert, after Step 0.4 tailscale serve)
podman pull alpine:latest
podman tag alpine:latest registry.tail8d86e.ts.net/blumeops/test:v1
podman push registry.tail8d86e.ts.net/blumeops/test:v1
curl -s https://registry.tail8d86e.ts.net/v2/_catalog
# Expected: {"repositories":["blumeops/test","docker.io/library/alpine"]}
```
---
@ -596,7 +655,9 @@ tags:
# Zot Registry Management Log
Zot is an OCI-native container registry running on Indri, providing local caching and pull-through proxy for Docker Hub, GHCR, and Quay.
Zot is an OCI-native container registry running on Indri, providing:
1. Pull-through cache for Docker Hub, GHCR, Quay (avoids rate limits)
2. Private image storage for custom-built containers
## Service Details
@ -606,19 +667,28 @@ Zot is an OCI-native container registry running on Indri, providing local cachin
- Config: ~/.config/zot/config.json
- Managed via: mcquack LaunchAgent
## Pull-Through Cache
## Namespace Convention
Configured to proxy:
- docker.io (Docker Hub)
- ghcr.io (GitHub Container Registry)
- quay.io (Red Hat Quay)
| Path | Source |
|------|--------|
| `registry.../docker.io/*` | Cached from Docker Hub |
| `registry.../ghcr.io/*` | Cached from GHCR |
| `registry.../quay.io/*` | Cached from Quay |
| `registry.../blumeops/*` | Private images (yours) |
## Useful Commands
\`\`\`bash
# List cached images
# List all images
curl -s http://localhost:5000/v2/_catalog | jq
# Pull via cache (from indri or k8s)
podman pull localhost:5000/docker.io/library/nginx:latest
# Build and push private image (from gilbert)
podman build -t registry.tail8d86e.ts.net/blumeops/myapp:v1 .
podman push registry.tail8d86e.ts.net/blumeops/myapp:v1
# Check service status
launchctl list | grep zot
@ -663,14 +733,17 @@ Run after completing all steps:
mise run indri-services-check
# All services should show OK, including new ones
# 2. Registry functionality
# 2. Registry functionality - pull-through cache
ssh indri 'podman pull localhost:5000/docker.io/library/alpine:latest'
curl -s https://registry.tail8d86e.ts.net/v2/_catalog
# Expected: {"repositories":[]}
# Expected: {"repositories":["docker.io/library/alpine"]}
# 3. Pull through registry (test caching)
ssh indri 'podman pull localhost:5000/library/alpine:latest'
# 3. Registry functionality - private image push (from gilbert)
podman pull alpine:latest
podman tag alpine:latest registry.tail8d86e.ts.net/blumeops/test:v1
podman push registry.tail8d86e.ts.net/blumeops/test:v1
curl -s https://registry.tail8d86e.ts.net/v2/_catalog
# Expected: {"repositories":["library/alpine"]}
# Expected: {"repositories":["blumeops/test","docker.io/library/alpine"]}
# 4. Kubernetes cluster
ssh indri 'minikube status'