# Use Cases

This document covers common scenarios for using Occy Strap with practical
examples.

## Airgapped Environments

Transfer container images to systems without internet access.

### Download Images for Transfer

```bash
# Download multiple images to tarballs
occystrap process registry://docker.io/library/python:3.11 tar://python.tar
occystrap process registry://docker.io/library/nginx:latest tar://nginx.tar
occystrap process registry://docker.io/library/postgres:15 tar://postgres.tar
```

### Load Images on Airgapped System

```bash
# On the airgapped system with Docker
docker load -i python.tar
docker load -i nginx.tar
docker load -i postgres.tar
```

## Reproducible Builds

Create images with consistent hashes regardless of build time.

### Normalize Timestamps

```bash
# Download with timestamp normalization (Unix epoch)
occystrap process registry://docker.io/library/busybox:latest \
    tar://busybox.tar -f normalize-timestamps

# Verify hash is consistent
sha256sum busybox.tar
# Running again produces the same hash
```

### Use Specific Timestamp

```bash
# Normalize to a specific date (Jan 1, 2024)
occystrap process registry://docker.io/library/python:3.11 \
    tar://python.tar -f "normalize-timestamps:ts=1704067200"
```

## Container Forensics

Inspect and analyze container image contents.

### Search for Configuration Files

```bash
# Find all .conf files
occystrap search registry://docker.io/library/nginx:latest "*.conf"

# Find all Python files with regex
occystrap search --regex docker://myapp:v1 ".*\.py$"

# Machine-readable output for scripting
occystrap search --script-friendly tar://image.tar "*.sh" > shell_files.txt
```

### Extract and Inspect Layers

```bash
# Extract with expanded layers for inspection
occystrap process registry://docker.io/library/python:3.11 \
    "dir://python-inspect?expand=true"

# Browse the extracted filesystem
ls -la python-inspect/
find python-inspect -name "*.conf"
```

### Search While Processing

```bash
# Search for config files while creating tarball
occystrap process registry://docker.io/library/nginx:latest \
    tar://nginx.tar -f "search:pattern=etc/**/*.conf"
```

## Private Registry Operations

Work with authenticated registries.

### Download from Private Registry

```bash
# Using command-line options
occystrap --username myuser --password mytoken \
    process registry://registry.gitlab.com/mygroup/myimage:latest \
    tar://myimage.tar

# Using environment variables (more secure)
export OCCYSTRAP_USERNAME=myuser
export OCCYSTRAP_PASSWORD=mytoken
occystrap process registry://registry.gitlab.com/mygroup/myimage:latest \
    tar://myimage.tar
```

### Mirror Images Between Registries

```bash
# Copy from Docker Hub to private registry
occystrap --username destuser --password desttoken \
    process registry://docker.io/library/nginx:latest \
    registry://myregistry.example.com/mirror/nginx:latest

# Copy from local Docker to registry
occystrap --username myuser --password mytoken \
    process docker://myapp:v1 \
    registry://ghcr.io/myorg/myapp:v1

# Copy from local Docker to registry (faster for multi-layer images)
occystrap --username myuser --password mytoken \
    process dockerpush://myapp:v1 \
    registry://ghcr.io/myorg/myapp:v1
```

## Multi-Architecture Images

Work with images for different CPU architectures.

### Download ARM64 Image

```bash
# Using global options
occystrap --os linux --architecture arm64 --variant v8 \
    process registry://docker.io/library/busybox:latest \
    tar://busybox-arm64.tar

# Using URI query parameters
occystrap process \
    "registry://docker.io/library/busybox:latest?os=linux&arch=arm64&variant=v8" \
    tar://busybox-arm64.tar
```

### Download Multiple Architectures

```bash
# AMD64
occystrap process registry://docker.io/library/python:3.11 \
    tar://python-amd64.tar

# ARM64
occystrap --architecture arm64 --variant v8 \
    process registry://docker.io/library/python:3.11 \
    tar://python-arm64.tar
```

## Storage Optimization

Reduce disk usage when working with multiple images.

### Shared Layer Storage

```bash
# Download multiple images with layer deduplication
occystrap process registry://docker.io/library/python:3.11 \
    "dir://shared-images?unique_names=true"

occystrap process registry://docker.io/library/python:3.10 \
    "dir://shared-images?unique_names=true"

occystrap process registry://docker.io/library/python:3.9 \
    "dir://shared-images?unique_names=true"

# Shared base layers are stored only once
ls -la shared-images/
cat shared-images/catalog.json
```

### Clean Up Images

```bash
# Exclude unnecessary files to reduce size
occystrap process registry://docker.io/library/python:3.11 \
    tar://python-clean.tar \
    -f "exclude:pattern=**/__pycache__/**,**/*.pyc,**/.git/**"
```

### Efficient Registry Pushes with Deduplication

When pushing images that share base layers, Occy Strap skips uploading
blobs that already exist in the target registry. Combining this with
`normalize-timestamps` maximizes the chance of layer deduplication:

```bash
# Push multiple Python versions -- shared base layers upload once
for version in 3.9 3.10 3.11; do
    occystrap process \
        "registry://docker.io/library/python:$version" \
        "registry://myregistry.example.com/python:$version" \
        -f normalize-timestamps
done
```

Compression is deterministic (gzip suppresses header timestamps, zstd
is inherently deterministic), so identical layers always produce the
same compressed digest. The second and third pushes will skip uploading
any layers shared with earlier pushes.

## OCI Runtime Integration

Create runtime bundles for runc.

### Generate OCI Bundle

```bash
# Create OCI bundle from registry image
occystrap process registry://docker.io/library/hello-world:latest \
    oci://hello-bundle

# Run with runc
cd hello-bundle
sudo runc run hello-world
```

### From Local Docker Image

```bash
# Export and convert to OCI bundle
occystrap process docker://myapp:v1 oci://myapp-bundle

# Run the bundle
cd myapp-bundle
sudo runc run myapp
```

## Podman Integration

Work with Podman instead of Docker.

### Enable Podman Socket

```bash
# Start rootless Podman socket
systemctl --user start podman.socket

# Or rootful
sudo systemctl start podman.socket
```

### Fetch from Podman

```bash
# Rootless Podman
occystrap process \
    "docker://myimage:v1?socket=/run/user/$(id -u)/podman/podman.sock" \
    tar://myimage.tar

# Rootful Podman
occystrap process \
    "docker://myimage:v1?socket=/run/podman/podman.sock" \
    tar://myimage.tar
```

### Load into Podman

```bash
# Load tarball into Podman
occystrap process tar://myimage.tar \
    "docker://myimage:v1?socket=/run/user/$(id -u)/podman/podman.sock"
```

## CI/CD Pipelines

Integrate Occy Strap into build pipelines.

### Cache Images for CI

```bash
#!/bin/bash
# ci-image-cache.sh - Download images for CI environment

CACHE_DIR="/var/cache/ci-images"
mkdir -p "$CACHE_DIR"

# Download with normalized timestamps for consistent caching
for image in python:3.11 node:18 postgres:15; do
    name=$(echo "$image" | tr ':' '-')
    if [ ! -f "$CACHE_DIR/$name.tar" ]; then
        occystrap process "registry://docker.io/library/$image" \
            "tar://$CACHE_DIR/$name.tar" -f normalize-timestamps
    fi
done
```

### Fast Local-to-Registry Push with Layer Cache

```bash
#!/bin/bash
# ci-push.sh - Push locally-built images to registry with layer cache
# Uses dockerpush:// for fast transfer from local Docker and
# --layer-cache to skip re-processing shared base layers.

CACHE="/tmp/occystrap-cache.json"

for image in app-web app-api app-worker; do
    occystrap --layer-cache "$CACHE" \
        process "dockerpush://$image:latest" \
        "registry://myregistry.example.com/$image:latest" \
        -f normalize-timestamps
done
# Second and third images skip uploading shared base layers
```

### Verify Image Contents

```bash
#!/bin/bash
# verify-image.sh - Check image doesn't contain sensitive files

IMAGE="$1"
SENSITIVE_PATTERNS="*.pem *.key id_rsa* .env* secrets*"

for pattern in $SENSITIVE_PATTERNS; do
    matches=$(occystrap search --script-friendly \
        "registry://$IMAGE" "$pattern" 2>/dev/null)
    if [ -n "$matches" ]; then
        echo "WARNING: Found sensitive files matching '$pattern':"
        echo "$matches"
        exit 1
    fi
done

echo "Image passed security check"
```

### Validate Image Integrity in CI

```bash
#!/bin/bash
# validate-image.sh - Validate image after processing

# Process image with filters
occystrap process docker://myapp:v1 tar://output.tar \
    -f normalize-timestamps \
    -f "exclude:pattern=**/__pycache__/**"

# Fast metadata check (no layer download)
occystrap check --fast tar://output.tar

# Full integrity check (verifies diff_ids, tar validity)
occystrap -O json check tar://output.tar | jq .errors
# Exit code is non-zero if errors found
```

### Inspect Image Metadata

```bash
# Quick overview of a registry image
occystrap info registry://docker.io/library/python:3.11

# JSON output for scripting
occystrap -O json info docker://myapp:v1 | jq '.layer_count, .architecture'
```

## Batch Image Builds with Filtering Proxy

When building many container images (e.g., OpenStack Kolla), the proxy
command lets build and push overlap, and deduplicates shared base layers
across images.

### Start Proxy Before Build

```bash
# Start the proxy in the background
occystrap proxy --listen 127.0.0.1:5050 \
    --downstream ghcr.io/myorg \
    --layer-cache /tmp/layer-cache.json \
    -f normalize-timestamps &

# Configure the build tool to push to the proxy
kolla-build --registry 127.0.0.1:5050 --push ...

# Or push individual images as they're built
docker tag nova-api:latest localhost:5050/kolla/nova-api:latest
docker push localhost:5050/kolla/nova-api:latest

docker tag keystone:latest localhost:5050/kolla/keystone:latest
docker push localhost:5050/kolla/keystone:latest
```

### Why Use the Proxy Instead of `dockerpush://`

The `dockerpush://` input processes one image per invocation. For a
build producing many images (Kolla builds ~100), each invocation
starts a fresh embedded registry and cannot share state across images.

The proxy:

- Runs once, receives all images as they are built
- Maintains a single `LayerCache` across all images, so the first
  image pays the full cost and subsequent images skip shared base
  layers entirely
- Overlaps build and push (images push as soon as they are built,
  rather than waiting for the entire build to complete)

**TLS behavior difference:** The `dockerpush://` input starts an
embedded HTTPS server with a self-signed certificate. Docker skips
certificate verification for `127.0.0.0/8`, so it works without any
daemon.json changes. The proxy, on the other hand, listens on plain
HTTP. Docker normally allows insecure access to localhost, but when
`containerd-snapshotter: true` is enabled in daemon.json this
exception is not honored and `insecure-registries` in daemon.json
is not propagated to containerd's push path. You must configure
containerd's host-based registry config directly. See the
[proxy command reference](command-reference.md#proxy) for details.

### Push Multiple Images with Layer Dedup

```bash
#!/bin/bash
# Start proxy with layer cache
occystrap proxy -l 127.0.0.1:5050 \
    -d myregistry.example.com \
    --layer-cache /tmp/cache.json \
    -f normalize-timestamps &
PROXY_PID=$!

# Push images -- shared base layers are uploaded only once
for img in app-web app-api app-worker; do
    docker tag "$img:latest" "localhost:5050/$img:latest"
    docker push "localhost:5050/$img:latest"
done

# Stop proxy
kill $PROXY_PID
```

## Debugging

Troubleshoot issues with verbose output. By default, occystrap only
logs milestones (start/end, summary statistics). Use `--verbose` to
see per-layer detail from occystrap, or `--debug` to also include
library output (requests, urllib3, etc.).

### Enable Debug Logging

```bash
# Debug logging for occystrap modules only
occystrap --verbose process registry://docker.io/library/busybox:latest \
    tar://busybox.tar

# Debug logging for all modules (includes library output)
occystrap --debug process registry://docker.io/library/busybox:latest \
    tar://busybox.tar
```

When running in a terminal, registry downloads and uploads display
interactive progress bars. In non-TTY environments (CI, pipes),
periodic log messages are emitted instead.

### Inspect Layer Contents

```bash
# Extract layers without merging
occystrap process registry://docker.io/library/python:3.11 dir://python-layers

# Each layer is a separate tarball
ls python-layers/*.tar

# Inspect a specific layer
tar -tvf python-layers/<layer-hash>.tar | head -50
```
