> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/nullclaw/nullclaw/llms.txt
> Use this file to discover all available pages before exploring further.

# Docker Deployment

> Deploy NullClaw using Docker and docker-compose

NullClaw provides production-ready Docker images optimized for minimal size and security.

## Quick Start

<Steps>
  <Step title="Pull the image">
    ```bash theme={null}
    docker pull ghcr.io/nullclaw/nullclaw:latest
    ```
  </Step>

  <Step title="Run the gateway">
    ```bash theme={null}
    docker run -p 3000:3000 \
      -e NULLCLAW_API_KEY=your-api-key \
      -v nullclaw-data:/nullclaw-data \
      nullclaw:latest
    ```
  </Step>

  <Step title="Verify it's running">
    ```bash theme={null}
    curl http://localhost:3000/health
    ```
  </Step>
</Steps>

## Building from Source

The Dockerfile uses a multi-stage build optimized for binary size:

```dockerfile theme={null}
# Stage 1: Build with Zig
FROM alpine:3.23 AS builder
RUN apk add --no-cache zig musl-dev
WORKDIR /app
COPY build.zig build.zig.zon ./
COPY src/ src/
RUN zig build -Dtarget="x86_64-linux-musl" -Doptimize=ReleaseSmall

# Stage 2: Runtime
FROM alpine:3.23
RUN apk add --no-cache ca-certificates curl tzdata
COPY --from=builder /app/zig-out/bin/nullclaw /usr/local/bin/nullclaw

EXPOSE 3000
ENTRYPOINT ["nullclaw"]
CMD ["gateway", "--port", "3000", "--host", "::"]
```

Build locally:

```bash theme={null}
docker build -t nullclaw:latest .
```

### Multi-architecture Builds

The Dockerfile supports both AMD64 and ARM64:

```bash theme={null}
docker buildx build --platform linux/amd64,linux/arm64 -t nullclaw:latest .
```

The `TARGETARCH` argument automatically selects the correct Zig target:

* `amd64` → `x86_64-linux-musl`
* `arm64` → `aarch64-linux-musl`

## Environment Variables

<ParamField path="NULLCLAW_API_KEY" type="string" required>
  Your AI provider API key
</ParamField>

<ParamField path="NULLCLAW_WORKSPACE" type="string" default="/nullclaw-data/workspace">
  Workspace directory for agent operations
</ParamField>

<ParamField path="HOME" type="string" default="/nullclaw-data">
  Home directory for config and data
</ParamField>

<ParamField path="NULLCLAW_GATEWAY_PORT" type="string" default="3000">
  Gateway HTTP port
</ParamField>

## Docker Compose

For production deployments, use docker-compose:

```yaml theme={null}
services:
  agent:
    build: .
    image: nullclaw:latest
    profiles: ["agent"]
    stdin_open: true
    tty: true
    env_file:
      - path: .env
        required: false
    volumes:
      - nullclaw-data:/root/.nullclaw
    restart: unless-stopped

  gateway:
    build: .
    image: nullclaw:latest
    profiles: ["gateway"]
    ports:
      - "8080:8080"
    env_file:
      - path: .env
        required: false
    volumes:
      - nullclaw-data:/root/.nullclaw
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:8080/health"]
      interval: 30s
      timeout: 5s
      retries: 3

volumes:
  nullclaw-data:
```

### Running Services

<Tabs>
  <Tab title="Gateway only">
    ```bash theme={null}
    docker-compose --profile gateway up -d
    ```
  </Tab>

  <Tab title="Agent only">
    ```bash theme={null}
    docker-compose --profile agent up -d
    ```
  </Tab>

  <Tab title="Both">
    ```bash theme={null}
    docker-compose --profile gateway --profile agent up -d
    ```
  </Tab>
</Tabs>

## Security Modes

NullClaw provides two Docker build targets:

### Safe Default (Non-root)

```bash theme={null}
docker build --target release -t nullclaw:safe .
```

Runs as user `65534:65534` (nobody). This is the default.

<Warning>
  Non-root mode cannot install packages or modify system files. Use this for production.
</Warning>

### Autonomous Mode (Root)

```bash theme={null}
docker build --target release-root -t nullclaw:root .
```

Runs as root with full system access. Requires explicit opt-in.

<Warning>
  **Only use root mode if your agent needs system-level operations.** This allows the AI to install packages, modify system files, and spawn processes with elevated privileges.
</Warning>

## Configuration

The Docker image includes a default config at `/nullclaw-data/.nullclaw/config.json`:

```json theme={null}
{
  "api_key": "",
  "default_provider": "openrouter",
  "default_model": "anthropic/claude-sonnet-4",
  "default_temperature": 0.7,
  "gateway": {
    "port": 3000,
    "host": "::",
    "allow_public_bind": true
  }
}
```

Override with your own config:

```bash theme={null}
docker run -v $(pwd)/config.json:/nullclaw-data/.nullclaw/config.json \
  nullclaw:latest
```

## Persistent Storage

Use named volumes to persist data across container restarts:

```bash theme={null}
docker volume create nullclaw-data

docker run -v nullclaw-data:/nullclaw-data \
  nullclaw:latest
```

The volume contains:

* `~/.nullclaw/config.json` - Configuration
* `~/.nullclaw/memory.db` - SQLite memory backend
* `~/workspace/` - Agent workspace files

## Health Checks

The gateway exposes a `/health` endpoint:

```bash theme={null}
curl http://localhost:3000/health
```

Response:

```json theme={null}
{"status": "ok"}
```

Docker Compose includes automatic health checks:

```yaml theme={null}
healthcheck:
  test: ["CMD", "wget", "-qO-", "http://localhost:8080/health"]
  interval: 30s
  timeout: 5s
  retries: 3
```

## Logging

View container logs:

```bash theme={null}
docker logs -f <container-id>
```

With docker-compose:

```bash theme={null}
docker-compose logs -f gateway
```

## Resource Limits

NullClaw is designed for minimal resource usage:

* Binary size: \< 1 MB (ReleaseSmall)
* Memory footprint: \< 5 MB peak RSS
* Zero dependencies beyond libc

Set container limits:

```bash theme={null}
docker run --memory=128m --cpus=0.5 nullclaw:latest
```

Or in docker-compose:

```yaml theme={null}
services:
  gateway:
    image: nullclaw:latest
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 128M
        reservations:
          cpus: '0.25'
          memory: 64M
```
