Docker
Run DorkOS in a Docker container with persistent data, custom configuration, and Docker Compose
Docker
Run DorkOS as a container. The official image bundles Node.js, the DorkOS CLI, and the built client, so Docker is the only thing you need on the host.
Quick Start
docker run -d --name dorkos \
-p 4242:4242 \
-e ANTHROPIC_API_KEY=your-key-here \
-v dorkos-data:/home/node/.dork \
ghcr.io/dork-labs/dorkos:latestThis runs DorkOS in the background (-d), maps port 4242 on your machine to the container, passes your API key, and creates a named volume so your data survives container restarts.
Open http://localhost:4242.
Image Versioning
Every release publishes the image with multiple tags:
| Tag | Example | Description |
|---|---|---|
latest | ghcr.io/dork-labs/dorkos:latest | Most recent non-prerelease version |
| Exact version | ghcr.io/dork-labs/dorkos:0.52.0 | Pinned to a specific release |
| Minor track | ghcr.io/dork-labs/dorkos:0.52 | Tracks the latest patch within a minor version |
| Commit SHA | ghcr.io/dork-labs/dorkos:sha-abc1234 | Pinned to a specific build commit |
For production deployments, pin to an exact version:
docker pull ghcr.io/dork-labs/dorkos:0.52.0The latest tag always points to the most recent non-prerelease version. Pre-release tags (e.g., 0.53.0-beta.1) are available by exact version but do not update latest.
Docker Hub mirror
The same image is mirrored to Docker Hub as dorkai/dorkos, with the same tags. GitHub Container Registry (the ghcr.io address above) stays the main home for the image. Docker Hub is a convenience copy, useful if your setup already pulls from there:
docker pull dorkai/dorkos:latestMulti-Platform Support
The image is built for both linux/amd64 and linux/arm64. Docker automatically pulls the correct architecture for your machine:
- Intel/AMD servers and desktops:
linux/amd64 - Apple Silicon (M1/M2/M3) via Docker Desktop:
linux/arm64 - ARM servers (AWS Graviton, Ampere):
linux/arm64
You don't need to configure anything: docker pull selects the right platform automatically.
Supply Chain Verification
Every published image includes a build provenance attestation (a signed record of exactly which source commit built it) proving it came from the dork-labs/dorkos repository, not a fork. Verify any image with the GitHub CLI:
gh attestation verify oci://ghcr.io/dork-labs/dorkos:0.52.0 --owner dork-labsA passing check confirms GitHub Actions built the image, not someone's laptop.
Configuration
Pass environment variables with -e or an env file. DorkOS reads the same variables whether it's running in Docker or installed directly.
Prop
Type
Custom port
Set DORKOS_PORT instead of using the --port flag. The container's built-in health check reads DORKOS_PORT to know which port to test, so setting the env var keeps DorkOS and its health check pointed at the same place. Match it with the container side of -p host:container:
docker run -d --name dorkos \
-p 8080:8080 \
-e ANTHROPIC_API_KEY=your-key-here \
-e DORKOS_PORT=8080 \
-v dorkos-data:/home/node/.dork \
ghcr.io/dork-labs/dorkos:latestThe --port flag still works, but it only tells DorkOS which port to listen on. The health check
keeps checking port 4242, so docker ps would report the container unhealthy even though it's
running fine. Use DORKOS_PORT instead so both stay in sync.
Environment file
Keep secrets out of your shell history:
ANTHROPIC_API_KEY=your-key-heredocker run -d --name dorkos \
-p 4242:4242 \
--env-file .env.dorkos \
-v dorkos-data:/home/node/.dork \
ghcr.io/dork-labs/dorkos:latestPersistent Data
DorkOS stores configuration, session transcripts, agent registrations, and the SQLite database in /home/node/.dork inside the container. Without a volume mount, all of this is lost when the container is removed. Mount a named volume or host directory to persist data across container restarts and upgrades.
Upgrading from 0.48 or earlier? The container now runs as a non-root user, and its data
directory moved from /root/.dork to /home/node/.dork. See Upgrading from an older
image below before you pull the new version.
docker run -d --name dorkos \
-p 4242:4242 \
-e ANTHROPIC_API_KEY=your-key-here \
-v dorkos-data:/home/node/.dork \
ghcr.io/dork-labs/dorkos:latestDocker manages the volume lifecycle. Inspect it with docker volume inspect dorkos-data.
mkdir -p ~/.dork
docker run -d --name dorkos \
-p 4242:4242 \
-e ANTHROPIC_API_KEY=your-key-here \
-v ~/.dork:/home/node/.dork \
ghcr.io/dork-labs/dorkos:latestUseful for backup or inspection, since the data directory is directly accessible on the host.
Upgrading from an older image
Versions 0.48.0 and earlier ran the container as root, and stored data at /root/.dork. The image now runs as a regular, unprivileged user (node, uid 1000) instead of root, so a compromised agent or a bug can't touch the rest of the container as easily. That move means two things for anyone upgrading:
- The data path changed. Change every
-v ...:/root/.dorkin yourdocker runcommand or Compose file to-v ...:/home/node/.dork. - Existing files need new ownership. Files created by the old root image are owned by root, and the new non-root user can't write to them until you fix that. Run this once, before starting the new image, against the same volume or host directory you already use:
docker run --rm -v dorkos-data:/data alpine chown -R 1000:1000 /dataReplace dorkos-data with your volume name, or with the host path (e.g. ~/.dork:/data) if you mounted a directory instead of a named volume. After that, start the new image with the updated /home/node/.dork mount path as shown above.
Mounting a project directory
By default, agents running inside the container can only see the container's own filesystem. They have no access to your code on the host machine. To let agents read and write files in one of your projects, mount the project directory into the container and tell DorkOS to use it as the default working directory:
docker run -d --name dorkos \
-p 4242:4242 \
-e ANTHROPIC_API_KEY=your-key-here \
-e DORKOS_DEFAULT_CWD=/workspace \
-e DORKOS_BOUNDARY=/workspace \
-v dorkos-data:/home/node/.dork \
-v ~/projects/my-app:/workspace \
ghcr.io/dork-labs/dorkos:latestSet DORKOS_BOUNDARY to the mounted directory to restrict agent file access. Without it, agents
can access the entire container filesystem.
Since the container runs as an unprivileged user, files agents create in your mounted project are owned by uid 1000 instead of root, so they're usually already owned by your own user account on Linux hosts.
Backing up your data
Copy everything in the data volume into a single archive file you can store somewhere safe. Stop the container first so the SQLite database isn't being written to mid-copy:
docker stop dorkos
docker run --rm -v dorkos-data:/data -v "$(pwd)":/backup alpine \
tar czf /backup/dorkos-backup.tgz -C /data .
docker start dorkosThis drops dorkos-backup.tgz in your current folder. To restore, extract that archive into a fresh volume the same way:
docker run --rm -v dorkos-data:/data -v "$(pwd)":/backup alpine \
tar xzf /backup/dorkos-backup.tgz -C /dataDocker Compose
The docker run commands above work fine for trying DorkOS out, but they're unwieldy to maintain. You end up with long shell commands that are easy to mistype and hard to version control. Docker Compose captures the full configuration in one file, so it's reproducible, easy to update, and simple to tear down with docker compose down.
The quickest way to start: download the ready-made file and run it.
curl -O https://dorkos.ai/compose.yml
export ANTHROPIC_API_KEY=your-key-here
docker compose up -ddocker compose finds compose.yml in the current directory automatically, no -f flag needed.
Want to see or customize it first? Here's what that file contains (minus a short comment header):
services:
dorkos:
image: ghcr.io/dork-labs/dorkos:latest
container_name: dorkos
restart: unless-stopped
ports:
- '4242:4242'
environment:
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
volumes:
- dorkos-data:/home/node/.dork
volumes:
dorkos-data:No healthcheck: entry needed: the image already checks its own health every 30 seconds. Run
docker ps and look at the STATUS column to see whether the container reports healthy or
unhealthy.
With a reverse proxy
Turn on login before you point a domain at DorkOS. The Docker image ships with login off, and it binds to every network address so port forwarding works. With login off, anyone who reaches the port gets full control: your sessions, your files, and your agents, spending your Claude quota. Create the owner account and require login first:
docker exec -it dorkos dorkos auth enableThis walks you through an email and password, then requires login from then on. You can also pass
--email and --password to skip the prompts. Full details are in Securing Your
Instance.
The standalone Compose setup above serves DorkOS over plain HTTP on port 4242. That's fine for local use. But if you're exposing DorkOS over the internet (a VPS, a home server with a domain, or any machine other people will connect to), you need HTTPS. Without TLS, browsers block mixed content, credentials travel in the clear, and SSE streams (the live updates DorkOS uses to stream agent output) can be intercepted.
A reverse proxy sits in front of DorkOS, handles HTTPS, and forwards requests to the container. Caddy is the simplest option: it obtains and renews Let's Encrypt certificates automatically, so there's no manual cert management. It also handles the buffering settings SSE needs.
Add Caddy to the Compose file for automatic HTTPS:
services:
dorkos:
image: ghcr.io/dork-labs/dorkos:latest
container_name: dorkos
restart: unless-stopped
expose:
- '4242'
environment:
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
volumes:
- dorkos-data:/home/node/.dork
caddy:
image: caddy:2-alpine
restart: unless-stopped
ports:
- '80:80'
- '443:443'
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy-data:/data
- caddy-config:/config
volumes:
dorkos-data:
caddy-data:
caddy-config:dorkos.example.com {
reverse_proxy dorkos:4242 {
flush_interval -1
}
}flush_interval -1 disables response buffering, which is required for SSE streaming. See the
reverse proxy guide for nginx configuration.
Health Check
The image checks its own health automatically: every 30 seconds it asks itself whether the server is responding, and reports the result to Docker. Run docker ps and check the STATUS column for healthy or unhealthy, no setup required.
You can also check it yourself at any time:
curl http://localhost:4242/api/health
# { "status": "ok", "version": "0.52.0", "uptime": 12345 }The health endpoint is unauthenticated and suitable for load balancer or container orchestrator use.
Using MCP tools
DorkOS exposes its tools to other AI clients at /mcp. Read-only tools work without any setup. Anything that changes state (running an agent, editing files) needs the instance's MCP token, or the call comes back with a 401 error that names where to find it.
Fetch the token from inside the container:
docker exec dorkos cat /home/node/.dork/mcp-local-tokenSend it as a Bearer token (a key you attach to each request) on your calls to /mcp. Once you turn on login, per-user API keys replace this token. See the MCP server guide for the full setup.
Building from Source
The official image from the container registry is the easiest path. Build from source if you need to run unreleased changes, test a fork, or include local modifications. One Dockerfile at the repository root covers both cases below.
Build the CLI tarball
git clone https://github.com/dork-labs/dorkos.git
cd dorkos
pnpm install
pnpm docker:buildThis builds the CLI package and creates the dorkos:latest image locally.
Run the local image
docker run -d --name dorkos \
-p 4242:4242 \
-e ANTHROPIC_API_KEY=your-key-here \
-v dorkos-data:/home/node/.dork \
dorkos:latestFrom published npm (no clone needed)
If you want a custom Docker image but don't need local code changes, you can build one that installs a published version directly from npm, no tarball or local build required:
docker build \
--build-arg INSTALL_MODE=npm \
--build-arg DORKOS_VERSION=latest \
-t dorkos:npm .Updating
Pull the latest image
docker pull ghcr.io/dork-labs/dorkos:latestRecreate the container
docker stop dorkos && docker rm dorkos
docker run -d --name dorkos \
-p 4242:4242 \
-e ANTHROPIC_API_KEY=your-key-here \
-v dorkos-data:/home/node/.dork \
ghcr.io/dork-labs/dorkos:latestOr with Compose:
docker compose pull
docker compose up -dData in the dorkos-data volume persists across updates.
Troubleshooting
Port forwarding not working
Cause: The server is binding to localhost inside the container.
Fix: The official image sets DORKOS_HOST=0.0.0.0 automatically. If you're using a custom image, ensure this variable is set.
Pull fails with "unauthorized" or "denied"
Cause: A registry hiccup, a rate limit, or a stale login on your machine.
Fix: Try the Docker Hub mirror, which carries the same image:
docker pull dorkai/dorkos:latestIf you were signed into the GitHub registry with an old token, sign out and pull again:
docker logout ghcr.io
docker pull ghcr.io/dork-labs/dorkos:latestContainer exits immediately
Check the logs:
docker logs dorkosCommon causes: missing ANTHROPIC_API_KEY, port already in use on the host, or insufficient memory.
Data lost after restart
Cause: No volume mounted for /home/node/.dork.
Fix: Add -v dorkos-data:/home/node/.dork to persist configuration and session data.
Upgrading from a root-based image and the new container can't write its data
Cause: Images from version 0.48.0 and earlier ran as root and stored data at /root/.dork. The
new image runs as an unprivileged user instead, and that user can't write to files the old root
image created.
Fix: Fix ownership once, then switch to the new mount path:
docker run --rm -v dorkos-data:/data alpine chown -R 1000:1000 /dataThen start the new container with -v dorkos-data:/home/node/.dork (not /root/.dork). See
Upgrading from an older image above for the full walkthrough.