Docker
Deploy the Kitaru server using Docker or Docker Compose
The Kitaru server container image is available at
zenmldocker/kitaru and works
with Docker, Docker Compose, or any container orchestration platform.
Quick start
Start a server with sensible defaults:
docker run -d --name kitaru-server -p 8080:8080 zenmldocker/kitaru:latestUse a version-pinned tag (e.g. zenmldocker/kitaru:0.2.0) that matches your
client SDK version to avoid API incompatibilities.
The server initializes an internal SQLite database on first startup. Wait for the health endpoint before connecting:
until curl -fsS http://localhost:8080/health >/dev/null; do sleep 2; doneThen connect your local CLI:
kitaru login http://localhost:8080This opens browser-based device authorization. After completing the flow, verify with:
kitaru statusHeadless activation
The first time the server starts, you need to activate it by visiting the
dashboard at http://localhost:8080 and creating an initial admin user account.
To skip this manual onboarding step (useful for automated or headless deployments), pass these environment variables:
docker run -d --name kitaru-server -p 8080:8080 \
-e ZENML_SERVER_AUTO_ACTIVATE=1 \
-e ZENML_DEFAULT_USER_NAME=admin \
-e ZENML_DEFAULT_USER_PASSWORD=password \
zenmldocker/kitaru:latestIf ZENML_DEFAULT_USER_PASSWORD is omitted, the admin account is created
with an empty password — only appropriate for local development.
The server activation variables use ZENML_* names because the Kitaru server
uses ZenML's server runtime internally. These are server-side configuration
knobs, not user-facing SDK settings.
Building from source
If you are testing changes from a local checkout:
just DOCKER_REPO=kitaru-local DOCKER_TAG=dev server-imagedocker build -f docker/Dockerfile --target server -t kitaru-local:dev .Then run it:
docker run -d --name kitaru-server -p 8080:8080 kitaru-local:devContainer management
docker logs kitaru-server # View server logs
docker logs kitaru-server -f # Follow logs
docker stop kitaru-server # Stop
docker start kitaru-server # Restart
docker rm kitaru-server # Remove
docker rm -f kitaru-server # Force remove (stop + remove)Persist your data
Default (ephemeral)
Without any volume mounts, the server stores everything inside the container:
- Metadata: SQLite database
- Artifacts: Local filesystem
This data is lost when the container is removed (docker rm). It survives
docker stop / docker start.
Persisting the SQLite database
Mount a host directory or Docker volume at the default data path:
docker run -d --name kitaru-server -p 8080:8080 \
-v kitaru-data:/zenml/.zenconfig/local_stores/default_zen_store \
zenmldocker/kitaru:latestmkdir kitaru-data
docker run -d --name kitaru-server -p 8080:8080 \
--mount type=bind,source=$PWD/kitaru-data,target=/zenml/.zenconfig/local_stores/default_zen_store \
zenmldocker/kitaru:latestThe path /zenml/.zenconfig/local_stores/default_zen_store is an internal
default inherited from the base image. It may change in a future release. For
production deployments, use an external MySQL database
instead of relying on this path.
The container runs as UID 1000 (zenml). If using a bind mount, ensure the
host directory is writable by UID 1000: chown -R 1000:1000 kitaru-data
Using MySQL (recommended for production)
SQLite works well for development and single-user setups, but for production you should use MySQL:
- Supports concurrent access from multiple server replicas
- Better performance under load
- Standard backup and HA tooling
Start a MySQL container:
docker run -d --name kitaru-mysql \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=password \
-e MYSQL_DATABASE=kitaru \
-v kitaru-mysql:/var/lib/mysql \
mysql:8.0Then start the Kitaru server pointing at it:
docker run -d --name kitaru-server -p 8080:8080 \
--add-host host.docker.internal:host-gateway \
--env ZENML_STORE_URL=mysql://root:password@host.docker.internal:3306/kitaru \
zenmldocker/kitaru:latestThe server automatically runs database migrations on first startup.
The database URL uses ZENML_STORE_URL because the Kitaru server uses
ZenML's server runtime internally. Future versions may provide a
KITARU_DATABASE_URL equivalent.
Linux users: The --add-host host.docker.internal:host-gateway flag is
required on Linux to make host.docker.internal resolve inside the
container. On macOS and Windows, Docker provides this automatically.
Docker Compose (server + MySQL)
A docker-compose.yml for a production-like setup:
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: kitaru
volumes:
- kitaru-mysql:/var/lib/mysql
ports:
- "3306:3306"
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
kitaru:
image: zenmldocker/kitaru:latest
ports:
- "8080:8080"
environment:
ZENML_STORE_URL: mysql://root:password@mysql:3306/kitaru
ZENML_SERVER_AUTO_ACTIVATE: "1"
ZENML_DEFAULT_USER_NAME: admin
ZENML_DEFAULT_USER_PASSWORD: "${KITARU_ADMIN_PASSWORD:-}"
depends_on:
mysql:
condition: service_healthy
restart: on-failure
volumes:
kitaru-mysql:Create a .env file alongside the compose file:
KITARU_ADMIN_PASSWORD=your-secure-passwordThe KITARU_ADMIN_PASSWORD environment variable is optional here for
convenience. If not set, the admin account is created with an empty
password — not recommended for production.
Start:
docker compose up -dWait for health and connect:
until curl -fsS http://localhost:8080/health >/dev/null; do sleep 2; done
kitaru login http://localhost:8080Tear down:
docker compose down # Stop containers (keep data)
docker compose down -v # Stop and delete volumesConnect to the server
Interactive login (browser-based)
kitaru login http://localhost:8080The CLI opens a browser for device authorization. If the browser does not open automatically, copy/paste the printed URL.
API key login (headless / CI)
kitaru login https://kitaru.example.com --api-key kat_abc123...Environment variable bootstrap (Docker / CI)
For containers or CI jobs that need to talk to the server without running
kitaru login:
export KITARU_SERVER_URL=https://kitaru.example.com
export KITARU_AUTH_TOKEN=kat_abc123...
export KITARU_PROJECT=my-projectSee Configuration for the full env-var reference and precedence rules.
Verify connection
kitaru status # Compact view
kitaru info # Detailed view (shows server version, database type, deployment type)Disconnect
kitaru logoutTroubleshooting
Server won't start
Check container logs:
docker logs kitaru-server -fCommon causes:
- Database connection refused (wrong host/port/credentials in
ZENML_STORE_URL) - Port 8080 already in use (
docker: bind: address already in use) - Insufficient permissions on mounted volumes (UID 1000 cannot write)
Login stalls or shows errors
- Ensure the
/healthendpoint returns 200 before attempting login. - If the browser shows
{"detail":"An unexpected error occurred."}, the dashboard assets may be missing from the image. Rebuild from source or use a newer image tag. - If the CLI keeps printing
authorization_pending, the server may not be fully initialized. Wait and retry. - Check
docker logs kitaru-serverfor error details.
host.docker.internal not resolving (Linux)
Add --add-host host.docker.internal:host-gateway to your docker run
command, or use extra_hosts in Docker Compose.