krz/brand-bench

A dynamic brand documentation generator with Ollama integration.

clone: git clone https://gitbay.org/krz/brand-bench.git

f5c756707ff30fbcb1bddb2dedd453fe6e276cd1

unsigned

author: Christian Cleberg <hello@cleberg.net> · 2026-04-19T03:40:21Z

add docker deployment option
 Dockerfile        | 18 ++++++++++++++++++
 README.md         | 26 ++++++++++++++++++++++++++
 compose.yml       | 35 +++++++++++++++++++++++++++++++++++
 docker/nginx.conf | 27 +++++++++++++++++++++++++++
 4 files changed, 106 insertions(+)

diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..5a27dca
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,18 @@
+# ── Stage 1: build ───────────────────────────────────────────────────────────
+FROM node:22-alpine AS build
+
+WORKDIR /app
+
+COPY package*.json ./
+RUN npm ci
+
+COPY . .
+RUN npm run build
+
+# ── Stage 2: serve ───────────────────────────────────────────────────────────
+FROM nginx:alpine
+
+COPY --from=build /app/dist /usr/share/nginx/html
+COPY docker/nginx.conf /etc/nginx/conf.d/default.conf
+
+EXPOSE 80
diff --git a/README.md b/README.md
index 82ba080..6312725 100644
--- a/README.md
+++ b/README.md
@@ -74,6 +74,32 @@ Larger models produce better-structured output. If generation fails with a JSON
 error, try a bigger model. Generation typically takes 15–60 seconds depending on
 hardware.
 
+## Self-hosting with Docker
+
+A `Dockerfile` and `compose.yml` are included for deploying the app alongside
+Ollama on a server.
+
+```bash
+docker compose up -d --build
+```
+
+The app is served on port 8000. Ollama's API is proxied through nginx at `/api/`
+so the browser never makes a cross-origin request — no CORS configuration
+needed.
+
+**After first boot, pull at least one model:**
+
+```bash
+docker compose exec ollama ollama pull llama3.2
+```
+
+Then open the app, go to Settings (⚙), enable AI, and set the Ollama base URL
+to `http://your-server:8000` (no path suffix).
+
+**GPU support:** If your server has an NVIDIA GPU, uncomment the `deploy` block
+in `compose.yml` (requires the
+[NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html)).
+
 ## Project structure
 
 ```
diff --git a/compose.yml b/compose.yml
new file mode 100644
index 0000000..361301c
--- /dev/null
+++ b/compose.yml
@@ -0,0 +1,35 @@
+services:
+
+  app:
+    build: .
+    ports:
+      - "8000:80"
+    depends_on:
+      - ollama
+    restart: unless-stopped
+
+  ollama:
+    image: ollama/ollama
+    volumes:
+      - ollama_data:/root/.ollama
+    restart: unless-stopped
+    # Expose port 11434 if you want to reach Ollama directly from your host
+    # (e.g. to run `ollama pull` without exec-ing into the container).
+    ports:
+      - "11434:11434"
+
+    # ── GPU support ──────────────────────────────────────────────────────────
+    # Uncomment the block below if your server has an NVIDIA GPU.
+    # Requires the NVIDIA Container Toolkit:
+    #   https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html
+    #
+    # deploy:
+    #   resources:
+    #     reservations:
+    #       devices:
+    #         - driver: nvidia
+    #           count: all
+    #           capabilities: [gpu]
+
+volumes:
+  ollama_data:
diff --git a/docker/nginx.conf b/docker/nginx.conf
new file mode 100644
index 0000000..49cd069
--- /dev/null
+++ b/docker/nginx.conf
@@ -0,0 +1,27 @@
+server {
+    listen 80;
+    root /usr/share/nginx/html;
+    index index.html;
+
+    # SPA fallback — let React Router handle unknown paths
+    location / {
+        try_files $uri $uri/ /index.html;
+    }
+
+    # Proxy Ollama's API through the same origin so the browser never has to
+    # make a cross-origin request and CORS is a non-issue.
+    # In the app's Settings panel, set the Ollama base URL to just:
+    #   http://<your-server>   (no port, no path suffix)
+    location /api/ {
+        proxy_pass         http://ollama:11434/api/;
+        proxy_http_version 1.1;
+        proxy_set_header   Host              $host;
+        proxy_set_header   X-Real-IP         $remote_addr;
+        proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
+
+        # Ollama responses (especially streamed ones) can be large and slow;
+        # disable buffering so cancellation works promptly.
+        proxy_buffering    off;
+        proxy_read_timeout 120s;
+    }
+}