This page is the fastest way to run Spooky in containers and verify health, metrics, and first proxied traffic.

Prerequisites

Choose Your Docker Path

  • Want the fastest container evaluation path: use the provided Compose stack plus a small demo backend
  • Want to run only the Spooky container: use the single-container commands later in this page
  • Want full host and production guidance: use Production Deployment

Quick Start with Docker Compose

The fastest working container path is:

  1. use the provided Compose stack
  2. point the default upstream at a demo backend
  3. verify first traffic, health, and metrics

1. Clone the repository:

git clone https://github.com/Supernova-Labs-Org/spooky.git
cd spooky

2. Use the repo development certificates for local testing.

The packaged Compose file already mounts certs/proxy-cert.pem and certs/proxy-key-pkcs8.pem from the repository.

For real deployments, replace them with your own certificate material and follow TLS Setup.

3. Start a small demo backend:

docker run -d --name spooky-demo-backend --rm -p 8080:80 nginx:alpine

4. Edit the config to point at that backend:

Open packaging/docker/config.docker.yaml and replace the upstream address:

upstream:
  default:
    backends:
      - id: "default-backend"
        address: "http://host.docker.internal:8080"

If you are on Linux, replace host.docker.internal with a reachable host-gateway address or run the backend in the same Compose project and use its service name.

Also replace the control API token:

observability:
  control_api:
    auth_token: "replace-with-strong-token"   # <-- change this

5. Start the stack:

docker compose -f packaging/docker/docker-compose.yml up -d --build

6. Verify health, metrics, and first traffic:

# Health check
curl -k --http1.1 https://127.0.0.1:9902/health

# Metrics
curl http://127.0.0.1:9901/metrics

# First proxied request
curl --http3-only -k https://127.0.0.1:9889/

Stop the stack:

docker compose -f packaging/docker/docker-compose.yml down
docker rm -f spooky-demo-backend 2>/dev/null || true

Running a Single Container

If you prefer to manage the container directly:

docker build -t spooky:latest -f packaging/docker/Dockerfile .

docker run -d \
  --name spooky \
  -p 9889:9889/udp \
  -p 9889:9889/tcp \
  -p 9901:9901 \
  -p 9902:9902 \
  -v "$(pwd)/packaging/docker/config.docker.yaml:/etc/spooky/config.yaml:ro" \
  -v "$(pwd)/certs:/etc/spooky/certs:ro" \
  --restart unless-stopped \
  spooky:latest

Ports

Port Protocol Purpose
9889 UDP + TCP QUIC / HTTP3 proxy listener
9901 TCP Prometheus metrics endpoint
9902 TCP Control API (health, ready, admin)

Using a Custom Config

Mount your own config file instead of the default:

docker run -d \
  --name spooky \
  -p 9889:9889/udp -p 9889:9889/tcp \
  -p 9901:9901 -p 9902:9902 \
  -v "/path/to/your/config.yaml:/etc/spooky/config.yaml:ro" \
  -v "/path/to/your/certs:/etc/spooky/certs:ro" \
  --restart unless-stopped \
  spooky:latest

See packaging/docker/config.docker.yaml for the packaged container reference config.

Building the Image

A helper script is provided to build and tag the image:

# Default tag: spooky:packaging
./packaging/docker/scripts/build-image.sh

# Custom tag
./packaging/docker/scripts/build-image.sh spooky:1.0.0

Smoke Test

Run the bundled smoke test to verify the image builds, starts, and responds correctly:

./packaging/docker/scripts/smoke-test.sh

This validates: - Image builds and the container starts cleanly - Control API health endpoint responds at https://127.0.0.1:9902/health - Metrics endpoint responds at http://127.0.0.1:9901/metrics - Container logs show a clean runtime startup

Logs

# Follow live logs
docker logs -f spooky

# With Compose
docker compose -f packaging/docker/docker-compose.yml logs -f spooky

By default, the container logs to stdout/stderr. To persist logs to a file, set in your config:

log:
  file:
    enabled: true
    path: /var/log/spooky/spooky.log

And mount a volume for /var/log/spooky/.

Upgrading

# Rebuild the image from latest source
docker compose -f packaging/docker/docker-compose.yml up -d --build

# Or for a single container
docker build -t spooky:latest -f packaging/docker/Dockerfile .
docker rm -f spooky
docker run -d ...   # same run command as before