feat: add Docker deployment with Containerfile, entrypoints, and nginx

Multi-stage Containerfile for all Node.js services (single image,
different CMD per docker-compose service). ESM entrypoints for gateway,
config, text-completion, prompt, embeddings, agent, and librarian.

Workbench gets a separate Containerfile (nginx:alpine) with SPA routing
and API/WebSocket proxy to gateway.

Docker Compose updated with 6 app services (gateway, config-service,
text-completion, prompt, embeddings, workbench) using shared
trustgraph-ts:local image.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
elpresidank 2026-04-06 00:21:00 -05:00
parent f09ef4de45
commit d1f24cf759
13 changed files with 241 additions and 78 deletions

7
ts/.dockerignore Normal file
View file

@ -0,0 +1,7 @@
node_modules
.git
deploy
**/dist
**/.turbo
*.log
.env*

44
ts/Containerfile Normal file
View file

@ -0,0 +1,44 @@
# TrustGraph TypeScript — multi-stage build for all Node.js services.
# A single image is built once; each service overrides CMD to pick its entrypoint.
# ---------------------------------------------------------------------------
# Stage 1: Build
# ---------------------------------------------------------------------------
FROM node:22-slim AS builder
RUN corepack enable && corepack prepare pnpm@9.15.0 --activate
WORKDIR /app
# Copy workspace config first for layer caching
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml turbo.json tsconfig.base.json ./
COPY packages/base/package.json packages/base/tsconfig.json packages/base/
COPY packages/client/package.json packages/client/tsconfig.json packages/client/
COPY packages/flow/package.json packages/flow/tsconfig.json packages/flow/
COPY packages/cli/package.json packages/cli/tsconfig.json packages/cli/
COPY packages/mcp/package.json packages/mcp/tsconfig.json packages/mcp/
RUN pnpm install --frozen-lockfile
# Copy source and build
COPY packages/ packages/
COPY tsconfig.json ./
RUN pnpm build
# ---------------------------------------------------------------------------
# Stage 2: Runtime
# ---------------------------------------------------------------------------
FROM node:22-slim AS runtime
WORKDIR /app
# Copy built output and production deps
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/packages ./packages
COPY --from=builder /app/package.json ./
COPY --from=builder /app/pnpm-workspace.yaml ./
COPY entrypoints/ ./entrypoints/
# Default env
ENV NODE_ENV=production
ENV NATS_URL=nats://nats:4222
EXPOSE 8088
CMD ["node", "entrypoints/gateway.mjs"]

View file

@ -197,82 +197,89 @@ services:
restart: unless-stopped
# ---------------------------------------------------------------------------
# TrustGraph Services (placeholders — will be filled in later)
# TrustGraph Application Services
# ---------------------------------------------------------------------------
#
# gateway:
# build:
# context: ../
# dockerfile: packages/base/Dockerfile
# target: gateway
# ports:
# - "${GATEWAY_PORT:-8088}:8000"
# environment:
# - NATS_URL=nats://nats:4222
# - FALKORDB_URL=redis://falkordb:6379
# - QDRANT_URL=http://qdrant:6333
# - OPENAI_TOKEN=${OPENAI_TOKEN}
# - CLAUDE_KEY=${CLAUDE_KEY}
# - GATEWAY_SECRET=${GATEWAY_SECRET}
# - OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
# - OTEL_SERVICE_NAME=gateway
# depends_on:
# nats:
# condition: service_healthy
# falkordb:
# condition: service_healthy
# qdrant:
# condition: service_healthy
# networks:
# - trustgraph
#
# text-completion:
# build:
# context: ../
# dockerfile: packages/base/Dockerfile
# target: text-completion
# environment:
# - NATS_URL=nats://nats:4222
# - OPENAI_TOKEN=${OPENAI_TOKEN}
# - CLAUDE_KEY=${CLAUDE_KEY}
# - OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
# - OTEL_SERVICE_NAME=text-completion
# depends_on:
# nats:
# condition: service_healthy
# networks:
# - trustgraph
#
# graph-rag:
# build:
# context: ../
# dockerfile: packages/base/Dockerfile
# target: graph-rag
# environment:
# - NATS_URL=nats://nats:4222
# - FALKORDB_URL=redis://falkordb:6379
# - QDRANT_URL=http://qdrant:6333
# - OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
# - OTEL_SERVICE_NAME=graph-rag
# depends_on:
# nats:
# condition: service_healthy
# falkordb:
# condition: service_healthy
# qdrant:
# condition: service_healthy
# networks:
# - trustgraph
#
# workbench:
# build:
# context: ../
# dockerfile: packages/workbench/Dockerfile
# ports:
# - "3001:3000"
# environment:
# - GATEWAY_URL=http://gateway:8000
# depends_on:
# - gateway
# networks:
# - trustgraph
gateway:
image: trustgraph-ts:local
build:
context: ../
dockerfile: Containerfile
command: ["node", "entrypoints/gateway.mjs"]
ports:
- "${GATEWAY_PORT:-8088}:8088"
environment:
- NATS_URL=nats://nats:4222
- GATEWAY_PORT=8088
- GATEWAY_SECRET=${GATEWAY_SECRET:-}
depends_on:
nats:
condition: service_healthy
networks:
- trustgraph
restart: unless-stopped
config-service:
image: trustgraph-ts:local
command: ["node", "entrypoints/config.mjs"]
environment:
- NATS_URL=nats://nats:4222
depends_on:
nats:
condition: service_healthy
networks:
- trustgraph
restart: unless-stopped
text-completion:
image: trustgraph-ts:local
command: ["node", "entrypoints/text-completion-openai.mjs"]
environment:
- NATS_URL=nats://nats:4222
- OPENAI_TOKEN=${OPENAI_TOKEN:-}
- OPENAI_BASE_URL=${OPENAI_BASE_URL:-}
depends_on:
nats:
condition: service_healthy
networks:
- trustgraph
restart: unless-stopped
prompt:
image: trustgraph-ts:local
command: ["node", "entrypoints/prompt.mjs"]
environment:
- NATS_URL=nats://nats:4222
depends_on:
nats:
condition: service_healthy
networks:
- trustgraph
restart: unless-stopped
embeddings:
image: trustgraph-ts:local
command: ["node", "entrypoints/embeddings.mjs"]
environment:
- NATS_URL=nats://nats:4222
- OLLAMA_URL=http://ollama:11434
depends_on:
nats:
condition: service_healthy
ollama:
condition: service_started
networks:
- trustgraph
restart: unless-stopped
workbench:
build:
context: ../
dockerfile: packages/workbench/Containerfile
ports:
- "${WORKBENCH_PORT:-3001}:80"
depends_on:
- gateway
networks:
- trustgraph
restart: unless-stopped

7
ts/entrypoints/agent.mjs Normal file
View file

@ -0,0 +1,7 @@
// Will work once the agent service is merged.
import("../packages/flow/dist/agent/react/service.js")
.then((m) => m.run())
.catch((err) => {
console.error(err);
process.exit(1);
});

View file

@ -0,0 +1,6 @@
import("../packages/flow/dist/config/service.js")
.then((m) => m.run())
.catch((err) => {
console.error(err);
process.exit(1);
});

View file

@ -0,0 +1,6 @@
import("../packages/flow/dist/embeddings/ollama.js")
.then((m) => m.run())
.catch((err) => {
console.error(err);
process.exit(1);
});

View file

@ -0,0 +1,6 @@
import("../packages/flow/dist/gateway/server.js")
.then((m) => m.run())
.catch((err) => {
console.error(err);
process.exit(1);
});

View file

@ -0,0 +1,7 @@
// Will work once the librarian service is merged.
import("../packages/flow/dist/librarian/service.js")
.then((m) => m.run())
.catch((err) => {
console.error(err);
process.exit(1);
});

View file

@ -0,0 +1,6 @@
import("../packages/flow/dist/prompt/template.js")
.then((m) => m.run())
.catch((err) => {
console.error(err);
process.exit(1);
});

View file

@ -0,0 +1,6 @@
import("../packages/flow/dist/model/text-completion/claude.js")
.then((m) => m.run())
.catch((err) => {
console.error(err);
process.exit(1);
});

View file

@ -0,0 +1,6 @@
import("../packages/flow/dist/model/text-completion/openai.js")
.then((m) => m.run())
.catch((err) => {
console.error(err);
process.exit(1);
});

View file

@ -0,0 +1,27 @@
# TrustGraph Workbench — Vite SPA served by nginx.
# ---------------------------------------------------------------------------
# Stage 1: Build
# ---------------------------------------------------------------------------
FROM node:22-slim AS builder
RUN corepack enable && corepack prepare pnpm@9.15.0 --activate
WORKDIR /app
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml turbo.json tsconfig.base.json ./
COPY packages/base/package.json packages/base/tsconfig.json packages/base/
COPY packages/client/package.json packages/client/tsconfig.json packages/client/
COPY packages/workbench/package.json packages/workbench/tsconfig.json packages/workbench/vite.config.ts packages/workbench/
RUN pnpm install --frozen-lockfile
COPY packages/ packages/
COPY tsconfig.json ./
RUN pnpm build --filter=@trustgraph/workbench
# ---------------------------------------------------------------------------
# Stage 2: Serve
# ---------------------------------------------------------------------------
FROM nginx:alpine
COPY --from=builder /app/packages/workbench/dist /usr/share/nginx/html
COPY packages/workbench/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80

View file

@ -0,0 +1,28 @@
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
# SPA routing
location / {
try_files $uri $uri/ /index.html;
}
# API proxy to gateway
location /api/v1/ {
proxy_pass http://gateway:8088;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# WebSocket proxy
location /api/v1/socket {
proxy_pass http://gateway:8088;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 86400;
}
}