Containers - image and compose stack

The repository ships a Dockerfile producing one image with all three binaries (hopskip-server, hopskip-wasm-worker, and the hop CLI) and a compose.yaml that runs a single-node stack.

Building the image

docker build -t hopskip:dev .

Behind a TLS-inspecting corporate proxy, pass its CA so the build’s network step (cargo fetching crates) trusts it:

docker build --secret id=extra_ca,src=/path/to/ca-bundle.crt -t hopskip:dev .

The CA is a build secret, so it never becomes a layer in the final image.

The image runs as a non-root user (uid 10001) and keeps all state under /var/lib/hopskip, declared as a volume. The event log is the durable record, so it must outlive the container.

Which binary runs is the container’s command:

docker run --rm hopskip:dev --version                  # hopskip-server (entrypoint)
docker run --rm hopskip:dev check-config               # validate configuration
docker run --rm --entrypoint hop hopskip:dev --help   # the CLI
docker run --rm --entrypoint hopskip-wasm-worker hopskip:dev

The image’s HEALTHCHECK probes the server’s /readyz. Disable it for containers running the worker or the CLI, which do not serve that endpoint. compose.yaml does this already.

The compose stack

# 1. A signing secret, shared by the server, the worker, and token minting.
export HOPSKIP_STATIC_AUTH_SECRET=$(openssl rand -hex 32)

# 2. Every surface authenticates, workers included, so mint the tokens.
docker run --rm -e HOPSKIP_STATIC_AUTH_SECRET --entrypoint hop hopskip:dev \
  token --subject worker --namespace default
docker run --rm -e HOPSKIP_STATIC_AUTH_SECRET --entrypoint hop hopskip:dev \
  token --subject client --namespace default

# 3. Put all three in .env (see .env.example), then:
docker compose up -d

The server publishes gRPC on 127.0.0.1:50051, the console API on :8090, and health/metrics on :9464. The worker waits for the server to report healthy before starting, and both share a registry volume so deployments written by hop build / hop deploy are visible to the worker that serves them and the server that routes to them.

Run a workflow through the stack:

docker compose --profile tools run --rm cli run hopskip:hello.greet@1 --input Ada

Check that it is live:

curl -s localhost:9464/metrics | grep hopskip_worker_connections   # expect 1
curl -s -o /dev/null -w '%{http_code}\n' localhost:8090/api/stats  # 401 without a token

What this stack is not

This is a development and evaluation stack. It does not configure TLS, OIDC, replicas, or an external object store, and its bundled secret is a checked-in constant. For anything beyond local evaluation, see Operations for TLS and authentication and the configuration reference for every setting.