Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Docker

SQE ships as a single Docker image containing the engine binaries (sqe-server, sqe-worker) and the client (sqe-cli).

Image Layout

graph TB
    subgraph "sqe:latest (chainguard/glibc-dynamic)"
        BIN1["/usr/local/bin/sqe-server"]
        BIN2["/usr/local/bin/sqe-worker"]
        BIN3["/usr/local/bin/sqe-cli"]
        HC["/usr/local/bin/wget (healthcheck only)"]
        USER["User: nonroot (UID 65532)"]
        EP["ENTRYPOINT: sqe-server"]
    end
  • Build: one multi-stage Dockerfile. Stage 1 is rust:<toolchain>-bookworm and a plain cargo build --release --locked. No cargo-chef, no sccache. Same file for local compose, data-platform quickstart/sqe, and aikido/kaniko.
  • Base (runtime): cgr.dev/chainguard/glibc-dynamic (digest-pinned). glibc, libgcc, and CA certificates only. No shell, no package manager, no OpenSSL.
  • Why not Debian slim / distroless: the binaries link only libc / libm / libgcc (TLS is rustls). Bookworm-slim carried hundreds of unused OS CVEs. Distroless cut most of that but still fails the Aikido image gate on unfixed debian libc criticals. Chainguard is clean under grype --fail-on high.
  • User: Non-root UID/GID 65532. Helm securityContext matches this UID.
  • Healthcheck: static busybox wget (exec form). Kubernetes uses HTTP probes on /healthz and does not need wget.
  • Entrypoint: sqe-server. Mode is selected via --mode or SQE_MODE.
  • CI (Aikido): aikido-build runs kaniko with --target=runtime. On merge, aikido-image-vuln runs grype registry:$AIKIDO_IMAGE --fail-on high.
  • Bench image: docker build --target bench-runtime -t sqe-bench:latest . (same Dockerfile).

There is no shell in the image. docker exec -it <container> sqe-cli still works (the CLI binary is present). docker exec ... bash does not.

Build

docker build -t sqe:latest .

# With metadata labels
docker build -t sqe:0.1.0 \
  --build-arg VERSION=0.1.0 \
  --build-arg BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ) \
  --build-arg GIT_REVISION=$(git rev-parse HEAD) \
  .

Run Coordinator

docker run -d \
  --name sqe-coordinator \
  -p 50051:50051 \
  -p 8080:8080 \
  -p 9090:9090 \
  -p 9091:9091 \
  -v $(pwd)/sqe.toml:/etc/sqe/sqe.toml:ro \
  -e SQE_AUTH__CLIENT_SECRET=my-secret \
  -e SQE_STORAGE__S3_ACCESS_KEY=minioadmin \
  -e SQE_STORAGE__S3_SECRET_KEY=minioadmin \
  sqe:latest --config /etc/sqe/sqe.toml

The default mode is coordinator, so no --mode flag needed.

Run Worker

docker run -d \
  --name sqe-worker-1 \
  -p 50052:50052 \
  -v $(pwd)/sqe.toml:/etc/sqe/sqe.toml:ro \
  sqe:latest --mode worker --config /etc/sqe/sqe.toml

Use the CLI

# Interactive SQL against running coordinator
docker exec -it sqe-coordinator sqe-cli

# One-shot query
docker exec sqe-coordinator sqe-cli -e "SELECT COUNT(*) FROM raw.orders;"

# With explicit connection
docker run --rm -it --network host \
  --entrypoint /usr/local/bin/sqe-cli \
  sqe:latest --host localhost --port 50051 --user alice

Note: when using docker exec, sqe-cli connects to localhost:50051 by default, which is the coordinator running in the same container. Override the entrypoint when docker run should start the CLI instead of the server.

Docker Compose

services:
  coordinator:
    image: sqe:latest
    command: ["--config", "/etc/sqe/sqe.toml"]
    ports:
      - "50051:50051"
      - "8080:8080"
      - "9090:9090"
      - "9091:9091"
    volumes:
      - ./sqe.toml:/etc/sqe/sqe.toml:ro
    environment:
      SQE_AUTH__CLIENT_SECRET: ${SQE_AUTH_SECRET}
      SQE_STORAGE__S3_ACCESS_KEY: ${S3_ACCESS_KEY}
      SQE_STORAGE__S3_SECRET_KEY: ${S3_SECRET_KEY}
    healthcheck:
      # exec form: no shell in the image
      test: ["CMD", "/usr/local/bin/wget", "-q", "-O", "/dev/null", "http://127.0.0.1:9091/healthz"]
      interval: 10s
      timeout: 5s
      retries: 3

  worker:
    image: sqe:latest
    command: ["--mode", "worker", "--config", "/etc/sqe/sqe.toml"]
    deploy:
      replicas: 2
    volumes:
      - ./sqe.toml:/etc/sqe/sqe.toml:ro
    depends_on:
      coordinator:
        condition: service_healthy

Why One Image?

ConcernAnswer
Version skewCoordinator, workers, and CLI are always the same build
CI/CDOne image to build, scan, and promote
K8s simplicitySame image: field, different --mode arg
Debuggingkubectl exec / docker exec can run sqe-cli (no shell)
Size overheadMinimal: both roles share 95% of their code
CVEsOS surface is distroless + a static healthcheck wget, not a full Debian userland