Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.git
.github
node_modules
dist
coverage
*.db
*.db-shm
*.db-wal
.env
.DS_Store
npm-debug.log
pnpm-debug.log
Dockerfile
docker-compose.yml
9 changes: 9 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,12 @@ jobs:

- name: Replay smoke test
run: pnpm run replay

- name: Build Docker test stage
run: docker build --target test -t narrative-alpha-agent:test .

- name: Build Docker runtime image
run: docker build -t narrative-alpha-agent:ci .

- name: Docker replay smoke test
run: docker run --rm narrative-alpha-agent:ci
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ The format is based on Keep a Changelog, and this project uses Conventional Comm
- Synthetic demo dataset and CLI commands
- Vitest coverage for clustering, scoring, replay, and lifecycle transitions
- Open-source documentation, CI, and project governance files
- Dockerfile, Docker Compose, and containerized replay smoke test
34 changes: 34 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# syntax=docker/dockerfile:1.7

FROM node:20-bookworm-slim AS base
WORKDIR /app
ENV PNPM_HOME=/pnpm
ENV PATH=$PNPM_HOME:$PATH
RUN corepack enable

FROM base AS deps
RUN apt-get update \
&& apt-get install -y --no-install-recommends python3 make g++ \
&& rm -rf /var/lib/apt/lists/*
COPY package.json pnpm-lock.yaml ./
RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store pnpm install --frozen-lockfile

FROM deps AS test
COPY . .
RUN pnpm run check
RUN pnpm run replay

FROM base AS runner
ENV NODE_ENV=production
COPY --from=deps /app/node_modules ./node_modules
COPY package.json pnpm-lock.yaml ./
COPY src ./src
COPY README.md LICENSE ./
RUN groupadd --system naa \
&& useradd --system --gid naa --home-dir /app naa \
&& mkdir -p /data \
&& chown -R naa:naa /app /data
USER naa
VOLUME ["/data"]
ENV NAA_DATABASE_PATH=/data/naa.sqlite
CMD ["pnpm", "run", "replay"]
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,13 @@ pnpm run ingest
pnpm run dev
```

Docker:

```bash
docker build -t narrative-alpha-agent:local .
docker run --rm narrative-alpha-agent:local
```

Quality gates:

```bash
Expand All @@ -146,6 +153,7 @@ pnpm run test
- [Providers and Secrets](docs/PROVIDERS.md)
- [Observability](docs/OBSERVABILITY.md)
- [Notifications](docs/NOTIFICATIONS.md)
- [Docker](docs/DOCKER.md)
- [Contributing](CONTRIBUTING.md)
- [Security](SECURITY.md)
- [Changelog](CHANGELOG.md)
Expand Down
21 changes: 21 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
services:
narrative-alpha-agent:
build:
context: .
target: runner
image: narrative-alpha-agent:local
environment:
NAA_ENV: development
NAA_DATABASE_PATH: /data/naa.sqlite
NAA_LLM_PROVIDER: local
LANGSMITH_TRACING: ${LANGSMITH_TRACING:-false}
LANGSMITH_API_KEY: ${LANGSMITH_API_KEY:-}
LANGSMITH_PROJECT: ${LANGSMITH_PROJECT:-narrative-alpha-agent}
DISCORD_WEBHOOK_URL: ${DISCORD_WEBHOOK_URL:-}
DISCORD_USERNAME: ${DISCORD_USERNAME:-Narrative Alpha Agent}
volumes:
- naa-data:/data
command: ["pnpm", "run", "replay"]

volumes:
naa-data:
66 changes: 66 additions & 0 deletions docs/DOCKER.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Docker

Narrative Alpha Agent includes Docker support for reproducible local runs, CI smoke tests, and deployment experiments.

Docker is useful for this project because `better-sqlite3` uses native bindings. The image builds those bindings in a controlled Linux environment instead of relying on each contributor's local machine.

## Build

```bash
docker build -t narrative-alpha-agent:local .
```

The Dockerfile is multi-stage:

- `deps`: installs dependencies and builds native packages
- `test`: runs `pnpm run check` and `pnpm run replay`
- `runner`: non-root runtime image with source, dependencies, and `/data` volume

## Run Replay

```bash
docker run --rm narrative-alpha-agent:local
```

By default the container runs:

```bash
pnpm run replay
```

## Run Ingest With Persistent SQLite

```bash
docker run --rm \
-v naa-data:/data \
-e NAA_DATABASE_PATH=/data/naa.sqlite \
narrative-alpha-agent:local \
pnpm run ingest
```

## Docker Compose

```bash
docker compose up --build
```

Compose mounts a named volume at `/data` and runs replay with local deterministic providers by default.

## Secrets

Do not bake secrets into the image. Pass runtime secrets through environment variables:

```bash
docker run --rm \
-e LANGSMITH_TRACING=true \
-e LANGSMITH_API_KEY=lsv2_... \
-e LANGSMITH_PROJECT=narrative-alpha-agent \
-e DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/... \
narrative-alpha-agent:local
```

For provider credentials, use the same variables documented in `.env.example` and `docs/PROVIDERS.md`.

## CI

GitHub Actions builds the Docker image and runs a replay smoke test inside the container. This keeps the container path from drifting away from the normal local development path.
4 changes: 4 additions & 0 deletions docs/OPERATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ pnpm run replay
pnpm run ingest
pnpm run dev
pnpm run check
docker build -t narrative-alpha-agent:local .
docker run --rm narrative-alpha-agent:local
```

## Data and Storage
Expand All @@ -16,6 +18,8 @@ pnpm run check

`pnpm run replay` uses an in-memory database by default and does not write persistent state.

Docker runtime uses `/data/naa.sqlite` by default for persistent SQLite state when running ingest. See [Docker](DOCKER.md).

## Configuration

Defaults live in `src/config/defaults.ts`.
Expand Down