Skip to content

Docker

Images

Image Build For
CPU (api target) docker build --target api -t brainbrew-api . OpenAI or any OpenAI-compatible endpoint; the CLI
GPU (default) docker build -t brainbrew . LoRA training (NVIDIA driver R580+, CUDA 13.0)

vLLM is not installed in either image. For a local model server, compose.yaml runs the official vLLM image next to the app (below).

Each release also publishes the CPU image, signed with Sigstore (keyless) and with build provenance, for linux/amd64 and linux/arm64:

docker pull ghcr.io/yog-sotho/brainbrew          # or :<version>
docker run -p 127.0.0.1:8501:8501 --env-file .env -v brainbrew-runs:/app/runs ghcr.io/yog-sotho/brainbrew

The GPU image is not published (its CUDA torch stack is too large for the hosted build runners); build it with the command above.

Images run as a non-root user (uid 10001), log JSON lines, and never contain .env or .streamlit/secrets.toml (.dockerignore is an allow-list).

docker run -p 127.0.0.1:8501:8501 --env-file .env -v brainbrew-runs:/app/runs brainbrew-api

Mount a volume at /app/runs to keep runs across restarts.

Brainbrew with a local vLLM server

compose.yaml runs the CPU app next to the official vLLM server image:

cp .env.sample .env       # HF_TOKEN only for gated models or publishing
docker compose up -d      # model: VLLM_MODEL (default Qwen/Qwen3-4B-Instruct-2507)

The app can only reach the vLLM container (BRAINBREW_ALLOW_CUSTOM_ENDPOINTS=0), and vLLM's port is not published on the host. The first start downloads the model, so the health check allows ten minutes.

Headless runs

docker run --rm -v "$PWD:/data" -v brainbrew-runs:/app/runs -e OPENAI_API_KEY brainbrew-api \
    python cli.py run /data/notes.pdf -o /data/dataset.jsonl