# How to Use Docker with OpenWork for Development: Complete Setup Guide

> Easily set up the complete OpenWork development environment with Docker. Launch MySQL, Den control plane, and the web UI using a single command from the repository.

- Repository: [Different AI/openwork](https://github.com/different-ai/openwork)
- Tags: how-to-guide
- Published: 2026-08-14

---

**You can launch the complete OpenWork development stack—including MySQL, the Den control plane, and the OpenWork Cloud web UI—with a single command: [`./packaging/docker/den-dev-up.sh`](https://github.com/different-ai/openwork/blob/main/./packaging/docker/den-dev-up.sh) from the repository root.**

The `different-ai/openwork` repository provides a fully containerized development environment that isolates the backend, database, and web frontend. Using Docker with OpenWork for development lets you run end-to-end workflows locally without installing Node.js, MySQL, or other dependencies directly on your host machine.

## What the OpenWork Docker Development Stack Includes

The development stack defined in [`packaging/docker/docker-compose.den-dev.yml`](https://github.com/different-ai/openwork/blob/main/packaging/docker/docker-compose.den-dev.yml) runs three core services:

- **MySQL** on port `3306` for persistent data storage.
- **Den API** container (the backend admin server) exposing the control plane, typically on port `8788`.
- **Den Web** container serving the **OpenWork Cloud web UI**, typically on port `3005`.

The helper script [`packaging/docker/den-dev-up.sh`](https://github.com/different-ai/openwork/blob/main/packaging/docker/den-dev-up.sh) automates the entire bootstrap process. According to the `different-ai/openwork` source code, it generates random host ports so multiple stacks can coexist, creates a secure Better Auth secret, generates a dev-only DB encryption key, starts MySQL, runs Den migrations, and then launches the Den API and Den web containers. After startup, it prints ready-to-use localhost, LAN, and Tailscale URLs and writes a runtime `.env` file containing all ports and secrets.

## Starting the OpenWork Docker Development Environment

You can start the stack using either the shell helper or a `pnpm` shortcut.

### Run the Helper Script

Navigate to the repository root and execute the convenience script:

```bash
./packaging/docker/den-dev-up.sh

```

When the stack is ready, the script outputs the local URLs and a path to a runtime environment file such as `/path/to/tmp/.den-dev-env-<id>`.

### Use the pnpm Shortcut

Alternatively, run the same script through the package manager:

```bash
pnpm dev:den-docker

```

This shortcut is registered in [`package.json`](https://github.com/different-ai/openwork/blob/main/package.json) and behaves identically to calling the script directly.

## Accessing the Containerized Services

Verify that the services are healthy using `curl`:

```bash
curl http://localhost:8788/health       # Den API

curl http://localhost:3005/api/health   # Den web

```

Open a browser to the printed web URL—commonly `http://localhost:3005`—and log in with the default demo credentials:

- **Email:** `alex@acme.test`
- **Password:** `OpenWorkDemo123!`

## Seeding Demo Data

To populate the database with an idempotent demo organization, first source the generated runtime environment file:

```bash
source tmp/.den-dev-env-<id>

```

Then run the seed command:

```bash
pnpm dev:den:seed-demo

```

## Viewing Logs and Tearing Down the Stack

View real-time logs by referencing the randomized Compose project name printed during startup:

```bash
docker compose -p <project> -f packaging/docker/docker-compose.den-dev.yml logs -f

```

Stop the containers while preserving the MySQL volume for the next session:

```bash
docker compose -p <project> -f packaging/docker/docker-compose.den-dev.yml down

```

To remove everything—including the database volume—run:

```bash
docker compose -p <project> -f packaging/docker/docker-compose.den-dev.yml down -v

```

## Customizing Ports and Environment Variables

The [`packaging/docker/docker-compose.den-dev.yml`](https://github.com/different-ai/openwork/blob/main/packaging/docker/docker-compose.den-dev.yml) file declares a large set of optional environment variables for fine-grained control without editing the Compose file directly.

To bind the Den API to a specific host port:

```bash
DEN_API_PORT=9090 ./packaging/docker/den-dev-up.sh

```

To switch the provisioner mode to `daytona` (requires a Daytona API key):

```bash
DEN_PROVISIONER_MODE=daytona DAYTONA_API_KEY=... ./packaging/docker/den-dev-up.sh

```

## Key Docker Files in the OpenWork Repository

Understanding the layout of `packaging/docker/` helps when you need to modify images or service definitions:

- **`packaging/docker/Dockerfile`** — Builds the base image that installs `openwork-server` and the matching `opencode` binary.
- **`packaging/docker/Dockerfile.den`** — Defines the production-grade image for the Den API service.
- **`packaging/docker/Dockerfile.den-web`** — Defines the production-grade image for the Den web UI service.
- **[`packaging/docker/docker-compose.den-dev.yml`](https://github.com/different-ai/openwork/blob/main/packaging/docker/docker-compose.den-dev.yml)** — Wires MySQL, Den API, and Den web together and exposes all configurable environment variables.
- **[`packaging/docker/den-dev-up.sh`](https://github.com/different-ai/openwork/blob/main/packaging/docker/den-dev-up.sh)** — Automates port selection, secret generation, and launch logging.
- **[`packaging/docker/README.md`](https://github.com/different-ai/openwork/blob/main/packaging/docker/README.md)** — Documents OTEL validation, image publishing, and micro-sandbox usage.

## Summary

- Execute [`./packaging/docker/den-dev-up.sh`](https://github.com/different-ai/openwork/blob/main/./packaging/docker/den-dev-up.sh) or `pnpm dev:den-docker` to launch the complete Docker stack.
- The environment includes containerized MySQL, the Den API control plane, and the OpenWork Cloud web UI.
- Access the UI at `http://localhost:3005` and sign in with `alex@acme.test` / `OpenWorkDemo123!`.
- Source the runtime `.env` file before running `pnpm dev:den:seed-demo` to populate demo data.
- Tear down with `docker compose ... down`, and append `-v` to permanently delete the MySQL data volume.
- Override variables such as `DEN_API_PORT` or `DEN_PROVISIONER_MODE` at the command line to customize behavior.

## Frequently Asked Questions

### What services does the OpenWork Docker development stack run?

The stack runs MySQL for persistence, the Den API container for the backend admin server, and the Den web container for the OpenWork Cloud UI. As implemented in `different-ai/openwork`, these services are orchestrated via [`packaging/docker/docker-compose.den-dev.yml`](https://github.com/different-ai/openwork/blob/main/packaging/docker/docker-compose.den-dev.yml) and bootstrapped by [`packaging/docker/den-dev-up.sh`](https://github.com/different-ai/openwork/blob/main/packaging/docker/den-dev-up.sh).

### How do I start the OpenWork development environment with Docker?

Run [`./packaging/docker/den-dev-up.sh`](https://github.com/different-ai/openwork/blob/main/./packaging/docker/den-dev-up.sh) from the repository root, or use `pnpm dev:den-docker`. Both approaches generate secrets, assign random host ports, start MySQL, run migrations, and launch the Den API and web containers.

### Where are the Docker configuration files located?

All Docker-related assets live under `packaging/docker/` in the `different-ai/openwork` repository. This directory contains `Dockerfile`, `Dockerfile.den`, `Dockerfile.den-web`, [`docker-compose.den-dev.yml`](https://github.com/different-ai/openwork/blob/main/docker-compose.den-dev.yml), [`den-dev-up.sh`](https://github.com/different-ai/openwork/blob/main/den-dev-up.sh), and [`README.md`](https://github.com/different-ai/openwork/blob/main/README.md).

### How do I completely remove the OpenWork Docker stack and its data?

Run `docker compose -p <project> -f packaging/docker/docker-compose.den-dev.yml down -v`, replacing `<project>` with the randomized project name printed during startup. The `-v` flag destroys the MySQL volume, so all persistent data is erased.