Skip to content

Commit 76d641b

Browse files
committed
docker and ga
1 parent d45ab8c commit 76d641b

File tree

7 files changed

+258
-0
lines changed

7 files changed

+258
-0
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
name: Build & push Docker images for Eventage Claw
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- 'src/**'
8+
- 'crates/example-eventage-claw/**'
9+
- 'Cargo.toml'
10+
- 'Cargo.lock'
11+
12+
env:
13+
REGISTRY: ghcr.io
14+
CLAW_IMAGE: ghcr.io/${{ github.repository_owner }}/eventage-claw
15+
BRIDGE_IMAGE: ghcr.io/${{ github.repository_owner }}/eventage-claw-bridge
16+
17+
jobs:
18+
build-claw:
19+
name: Build claw (Rust)
20+
runs-on: ubuntu-latest
21+
permissions:
22+
contents: read
23+
packages: write
24+
steps:
25+
- uses: actions/checkout@v4
26+
27+
- name: Log in to GHCR
28+
uses: docker/login-action@v3
29+
with:
30+
registry: ${{ env.REGISTRY }}
31+
username: ${{ github.actor }}
32+
password: ${{ secrets.GITHUB_TOKEN }}
33+
34+
- name: Set up Docker Buildx
35+
uses: docker/setup-buildx-action@v3
36+
37+
- name: Build and push claw
38+
uses: docker/build-push-action@v6
39+
with:
40+
context: .
41+
file: crates/example-eventage-claw/Dockerfile
42+
push: true
43+
tags: ${{ env.CLAW_IMAGE }}:latest,${{ env.CLAW_IMAGE }}:${{ github.sha }}
44+
cache-from: type=gha
45+
cache-to: type=gha,mode=max
46+
47+
build-bridge:
48+
name: Build whatsapp-bridge (Node)
49+
runs-on: ubuntu-latest
50+
permissions:
51+
contents: read
52+
packages: write
53+
steps:
54+
- uses: actions/checkout@v4
55+
56+
- name: Log in to GHCR
57+
uses: docker/login-action@v3
58+
with:
59+
registry: ${{ env.REGISTRY }}
60+
username: ${{ github.actor }}
61+
password: ${{ secrets.GITHUB_TOKEN }}
62+
63+
- name: Set up Docker Buildx
64+
uses: docker/setup-buildx-action@v3
65+
66+
- name: Build and push bridge
67+
uses: docker/build-push-action@v6
68+
with:
69+
context: crates/example-eventage-claw/whatsapp-bridge
70+
file: crates/example-eventage-claw/whatsapp-bridge/Dockerfile
71+
push: true
72+
tags: ${{ env.BRIDGE_IMAGE }}:latest,${{ env.BRIDGE_IMAGE }}:${{ github.sha }}
73+
cache-from: type=gha
74+
cache-to: type=gha,mode=max
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
target/
2+
**/*.rs.bk
3+
.git/
4+
data/
5+
crates/example-eventage-claw/whatsapp-bridge/node_modules/
6+
crates/example-eventage-claw/whatsapp-bridge/auth/
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copy to .env and fill in values before running docker compose.
2+
3+
# ── LLM credentials ───────────────────────────────────────────────────────────
4+
# Aliyun DashScope (qwen):
5+
OPENAI_API_KEY=sk-... # actually your DashScope key goes here
6+
LLM_URL=https://dashscope-intl.aliyuncs.com/compatible-mode/v1
7+
LLM_MODEL=qwen-plus
8+
9+
10+
# ── Data directories on the host machine ─────────────────────────────────────
11+
CLAW_DATA_DIR=/opt/claw/data # config.toml, skills/, memory/, tasks.json
12+
BRIDGE_AUTH_DIR=/opt/claw/bridge-auth # Baileys WhatsApp session
13+
14+
# ── WhatsApp bridge ───────────────────────────────────────────────────────────
15+
CLAW_GROUP=personal
16+
# TRIGGER_PREFIX=! # only forward messages starting with !
17+
# PAIRING_CODE=+1234567890 # use pairing-code auth instead of QR scan
18+
# SELF_CHAT=false
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# syntax=docker/dockerfile:1
2+
# ── Stage 1: install cargo-chef ───────────────────────────────────────────────
3+
FROM rust:1-slim AS chef
4+
RUN apt-get update \
5+
&& apt-get install -y --no-install-recommends pkg-config libssl-dev \
6+
&& rm -rf /var/lib/apt/lists/*
7+
RUN cargo install cargo-chef --locked
8+
WORKDIR /build
9+
10+
# ── Stage 2: compute dependency recipe ────────────────────────────────────────
11+
FROM chef AS planner
12+
COPY . .
13+
RUN cargo chef prepare --recipe-path recipe.json
14+
15+
# ── Stage 3: pre-compile dependencies (cached layer) ─────────────────────────
16+
FROM chef AS builder
17+
COPY --from=planner /build/recipe.json recipe.json
18+
RUN cargo chef cook --release -p example-eventage-claw --recipe-path recipe.json
19+
20+
# Build the actual binary (only re-runs when source changes)
21+
COPY . .
22+
RUN cargo build --release -p example-eventage-claw
23+
24+
# ── Stage 4: minimal runtime image ────────────────────────────────────────────
25+
FROM debian:12-slim AS runtime
26+
RUN apt-get update \
27+
&& apt-get install -y --no-install-recommends ca-certificates libssl3 \
28+
&& rm -rf /var/lib/apt/lists/*
29+
30+
COPY --from=builder /build/target/release/claw /usr/local/bin/claw
31+
32+
# Persistent data directory: config, skills, memory, tasks, event log.
33+
# Mount a volume or bind-mount a host directory here.
34+
VOLUME ["/root/.claw"]
35+
36+
EXPOSE 3000
37+
38+
ENTRYPOINT ["claw"]
39+
# Override CMD to pass extra flags, e.g.:
40+
# docker run ... claw --http-port 3000 --log /root/.claw/events.jsonl
41+
CMD ["--no-tui", "--http-port", "3000"]
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
services:
2+
3+
# ── eventage-claw (Rust AI agent, HTTP channel) ────────────────────────────
4+
claw:
5+
image: ${CLAW_IMAGE:-ghcr.io/dwzhangdavid/eventage-claw:latest}
6+
build:
7+
# Build context is the workspace root so cargo can see all crates.
8+
context: ../..
9+
dockerfile: crates/example-eventage-claw/Dockerfile
10+
restart: unless-stopped
11+
ports:
12+
- "3000:3000"
13+
volumes:
14+
# Persistent data: config.toml, skills/, memory/, tasks.json, events.jsonl
15+
# Bind-mount a local directory so you can edit config and skills directly.
16+
- ${CLAW_DATA_DIR:-../../data/claw}:/root/.claw
17+
environment:
18+
# LLM credentials — set in .env or environment
19+
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-}
20+
OPENAI_API_KEY: ${OPENAI_API_KEY:-}
21+
LLM_URL: ${LLM_URL:-https://api.anthropic.com/v1}
22+
LLM_MODEL: ${LLM_MODEL:-claude-sonnet-4-6}
23+
# To also run the live replay UI:
24+
# ports: ["3000:3000", "4567:4567"]
25+
# command: ["--no-tui", "--http-port", "3000", "--replay"]
26+
27+
# ── WhatsApp bridge (Node.js, Baileys) ────────────────────────────────────
28+
# Optional: only needed for WhatsApp connectivity.
29+
# Comment this service out if using claw's HTTP channel directly.
30+
whatsapp-bridge:
31+
image: ${BRIDGE_IMAGE:-ghcr.io/dwzhangdavid/eventage-claw-bridge:latest}
32+
build:
33+
context: whatsapp-bridge
34+
dockerfile: Dockerfile
35+
restart: unless-stopped
36+
ports:
37+
- "3001:3001"
38+
volumes:
39+
# Baileys auth state (QR / pairing-code session) — must survive restarts
40+
- ${BRIDGE_AUTH_DIR:-../../data/bridge-auth}:/app/auth
41+
# Shared with claw so downloaded media is accessible to the agent
42+
- ${CLAW_DATA_DIR:-../../data/claw}:/root/.claw
43+
environment:
44+
CLAW_HTTP_URL: http://claw:3000
45+
CLAW_GROUP: ${CLAW_GROUP:-personal}
46+
BRIDGE_PORT: 3001
47+
AUTH_DIR: /app/auth
48+
# Media written here is read by the agent via RunCommandTool skills
49+
ATTACHMENTS_DIR: /root/.claw/groups/${CLAW_GROUP:-personal}/attachments
50+
# Optional: only forward messages starting with this prefix
51+
TRIGGER_PREFIX: ${TRIGGER_PREFIX:-}
52+
# Set to your phone number (e.g. +1234567890) to use pairing-code auth
53+
PAIRING_CODE: ${PAIRING_CODE:-}
54+
SELF_CHAT: ${SELF_CHAT:-false}
55+
depends_on:
56+
- claw
57+
58+
# ── Uncomment to enable Docker-sandboxed tool execution ───────────────────
59+
# This mounts the Docker socket so claw can spin up sibling containers.
60+
# Only needed when docker_enabled = true in config.toml.
61+
#
62+
# claw-with-docker:
63+
# extends:
64+
# service: claw
65+
# volumes:
66+
# - ${CLAW_DATA_DIR:-../../data/claw}:/root/.claw
67+
# - /var/run/docker.sock:/var/run/docker.sock
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# eventage-claw nginx site config
2+
# Place at: /etc/nginx/sites-available/claw
3+
# Enable: ln -s /etc/nginx/sites-available/claw /etc/nginx/sites-enabled/claw
4+
# SSL cert: certbot --nginx -d your-domain.com
5+
6+
server {
7+
listen 80;
8+
server_name your-domain.com;
9+
return 301 https://$host$request_uri;
10+
}
11+
12+
server {
13+
listen 443 ssl;
14+
server_name your-domain.com;
15+
16+
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
17+
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
18+
include /etc/letsencrypt/options-ssl-nginx.conf;
19+
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
20+
21+
# Optional: restrict to known IPs (e.g. your WhatsApp bridge server)
22+
# allow 1.2.3.4;
23+
# deny all;
24+
25+
location / {
26+
proxy_pass http://127.0.0.1:3000;
27+
proxy_http_version 1.1;
28+
proxy_set_header Host $host;
29+
proxy_set_header X-Real-IP $remote_addr;
30+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
31+
proxy_set_header X-Forwarded-Proto $scheme;
32+
33+
# Required for SSE (streaming agent responses)
34+
proxy_buffering off;
35+
proxy_cache off;
36+
proxy_read_timeout 300s;
37+
}
38+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# syntax=docker/dockerfile:1
2+
FROM node:20-slim
3+
4+
WORKDIR /app
5+
6+
# Install dependencies first for layer caching
7+
COPY package.json package-lock.json ./
8+
RUN npm ci --omit=dev
9+
10+
COPY bridge.js .
11+
12+
EXPOSE 3001
13+
14+
CMD ["node", "bridge.js"]

0 commit comments

Comments
 (0)