Building¶
Go (Controller + Workers)¶
# Build both binaries
docker run --rm -v "$(pwd)/controller":/src -w /src golang:1.25-alpine sh -c \
"CGO_ENABLED=0 go build -o bin/controller ./cmd/controller/ && \
CGO_ENABLED=0 go build -o bin/worker ./cmd/worker/"
Output: controller/bin/controller and controller/bin/worker (static binaries).
Python (ML Service)¶
Full Stack (docker-compose)¶
# Build + start everything
./scripts/start.sh
# Or manually:
docker compose -f scripts/docker-compose.yaml up --build -d
Docker Images¶
| Image | Base | Size |
|---|---|---|
| Controller | alpine:3.20 |
~15MB |
| Worker | alpine:3.20 |
~15MB |
| ML Service | python:3.11-slim |
~400MB |
Controller/Worker Dockerfile¶
FROM golang:1.25-alpine AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /bin/controller ./cmd/controller/
RUN CGO_ENABLED=0 go build -o /bin/worker ./cmd/worker/
FROM alpine:3.20
COPY --from=builder /bin/controller /bin/worker /usr/local/bin/
ENTRYPOINT ["controller"]
ML Dockerfile¶
FROM python:3.11-slim
WORKDIR /app
COPY pyproject.toml .
RUN pip install --no-cache-dir -e .
COPY . .
CMD ["python", "-m", "server.main"]
Multi-Architecture¶
For production images (amd64 + arm64):
docker buildx build --platform linux/amd64,linux/arm64 \
-t registry/staffops-anomaly-controller:v0.11.0 \
./controller
Local development
Local builds are single-arch (your machine's architecture). Multi-arch is only needed for cluster deployment.