> Part of the walkerOS documentation. Project overview and full index: <https://www.walkeros.io/llms.txt>

# Docker

The `walkeros/flow` image runs a flow bundle you build with the CLI. This quickstart builds a small collector, runs it in a container, and sends it an event.

You need [Docker](https://docs.docker.com/get-docker/), Node.js, and network access to npm (the CLI downloads the packages your flow names).

## 1. Create a flow[​](#1-create-a-flow "Direct link to 1. Create a flow")

Save this as `flow.json`. The Express source receives events on `/collect`, and the demo destination logs each event's `name` and `data`:

```
{
  "version": 4,
  "flows": {
    "default": {
      "config": { "platform": "server" },
      "sources": {
        "http": { "package": "@walkeros/server-source-express" }
      },
      "destinations": {
        "demo": {
          "package": "@walkeros/destination-demo",
          "config": { "settings": { "values": ["name", "data"] } }
        }
      }
    }
  }
}
```

## 2. Bundle it[​](#2-bundle-it "Direct link to 2. Bundle it")

```
npm install -g @walkeros/cli
walkeros bundle flow.json -o dist/
```

This writes `dist/flow.mjs`, `dist/package.json`, and `dist/node_modules/`. The packages stay in `node_modules/`, so the container needs the whole directory, not `flow.mjs` alone.

## 3. Run the container[​](#3-run-the-container "Direct link to 3. Run the container")

Mount the bundle directory at `/app/flow`, where the image expects `flow.mjs`:

```
docker run --rm -p 8080:8080 \
  -v $(pwd)/dist:/app/flow:ro \
  walkeros/flow:latest
```

The image's entrypoint checks that the bundle file exists before it starts. If it exits with `bundle not found`, check the mount path.

## 4. Send an event[​](#4-send-an-event "Direct link to 4. Send an event")

In another terminal:

```
curl -X POST http://localhost:8080/collect \
  -H "Content-Type: application/json" \
  -d '{"name":"page view","data":{"title":"Home"}}'
```

The response is `{"success":true,"timestamp":...}`, and the container log shows the event:

```
[demo] {
  "name": "page view",
  "data": {
    "title": "Home"
  }
}
```

`GET http://localhost:8080/health` returns `{"status":"ok"}` while the container runs.

## Build a custom image[​](#build-a-custom-image "Direct link to Build a custom image")

Bake the bundle into your own image instead of mounting it:

```
FROM walkeros/flow:latest
COPY dist/ /app/flow/
```

```
docker build -t my-walker .
docker run -p 8080:8080 my-walker
```

## Docker compose[​](#docker-compose "Direct link to Docker compose")

```
services:
  walkeros:
    image: walkeros/flow:latest
    volumes:
      - ./dist:/app/flow:ro
    ports:
      - '8080:8080'
    restart: unless-stopped
```

## Single-file archive[​](#single-file-archive "Direct link to Single-file archive")

To ship one file instead of a directory, bundle to an archive and point `BUNDLE` at it. The runtime extracts it into `/app/flow/` at startup, so leave that directory writable:

```
walkeros bundle flow.json -o flow.tar.gz

docker run --rm -p 8080:8080 \
  -v $(pwd)/flow.tar.gz:/app/bundle/flow.tar.gz:ro \
  -e BUNDLE=/app/bundle/flow.tar.gz \
  walkeros/flow:latest
```

## Environment variables[​](#environment-variables "Direct link to Environment variables")

| Variable | Description                                                    | Default              |
| -------- | -------------------------------------------------------------- | -------------------- |
| `BUNDLE` | Path inside the container to `flow.mjs` or a `.tar.gz` archive | `/app/flow/flow.mjs` |
| `PORT`   | Server port                                                    | `8080`               |

## Next steps[​](#next-steps "Direct link to Next steps")

* [Docker deployment guide](/preview/pr-720/docs/apps/docker.md)
* [Runner](/preview/pr-720/docs/apps/runner.md): remote config, heartbeats, and hot-swap
* [Available sources](/preview/pr-720/docs/sources.md)
* [Available destinations](/preview/pr-720/docs/destinations.md)
