From adba123ad484c1bd7f28cfaedf5b7a316f195f89 Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Sat, 17 Jan 2026 13:51:46 -0800 Subject: [PATCH] Document both registry modes: pull-through cache + private images MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- docs/k8s-migration.md | 101 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 87 insertions(+), 14 deletions(-) diff --git a/docs/k8s-migration.md b/docs/k8s-migration.md index 1d1dea5..24527d5 100644 --- a/docs/k8s-migration.md +++ b/docs/k8s-migration.md @@ -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 @@ -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'