From 8208731064162ec06394fe979e5bf34be95b2b14 Mon Sep 17 00:00:00 2001 From: pyr0ball Date: Sun, 22 Mar 2026 18:47:46 -0700 Subject: [PATCH] feat(docker): add web service for Vue SPA (nginx, multi-stage build) Ports: dev=8506, demo=8507, cloud=8508 manage.sh build now includes web service --- compose.cloud.yml | 8 ++++++++ compose.demo.yml | 8 ++++++++ compose.yml | 8 ++++++++ docker/web/Dockerfile | 13 +++++++++++++ docker/web/nginx.conf | 18 ++++++++++++++++++ manage.sh | 9 ++++++++- 6 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 docker/web/Dockerfile create mode 100644 docker/web/nginx.conf diff --git a/compose.cloud.yml b/compose.cloud.yml index 180b168..16c442e 100644 --- a/compose.cloud.yml +++ b/compose.cloud.yml @@ -39,6 +39,14 @@ services: - "host.docker.internal:host-gateway" restart: unless-stopped + web: + build: + context: . + dockerfile: docker/web/Dockerfile + ports: + - "8508:80" + restart: unless-stopped + searxng: image: searxng/searxng:latest volumes: diff --git a/compose.demo.yml b/compose.demo.yml index 3678321..db1b9f6 100644 --- a/compose.demo.yml +++ b/compose.demo.yml @@ -38,6 +38,14 @@ services: - "host.docker.internal:host-gateway" restart: unless-stopped + web: + build: + context: . + dockerfile: docker/web/Dockerfile + ports: + - "8507:80" + restart: unless-stopped + searxng: image: searxng/searxng:latest volumes: diff --git a/compose.yml b/compose.yml index 186dd97..9127e84 100644 --- a/compose.yml +++ b/compose.yml @@ -40,6 +40,14 @@ services: - "host.docker.internal:host-gateway" restart: unless-stopped + web: + build: + context: . + dockerfile: docker/web/Dockerfile + ports: + - "${VUE_PORT:-8506}:80" + restart: unless-stopped + searxng: image: searxng/searxng:latest ports: diff --git a/docker/web/Dockerfile b/docker/web/Dockerfile new file mode 100644 index 0000000..de50164 --- /dev/null +++ b/docker/web/Dockerfile @@ -0,0 +1,13 @@ +# Stage 1: build +FROM node:20-alpine AS build +WORKDIR /app +COPY web/package*.json ./ +RUN npm ci --prefer-offline +COPY web/ ./ +RUN npm run build + +# Stage 2: serve +FROM nginx:alpine +COPY docker/web/nginx.conf /etc/nginx/conf.d/default.conf +COPY --from=build /app/dist /usr/share/nginx/html +EXPOSE 80 diff --git a/docker/web/nginx.conf b/docker/web/nginx.conf new file mode 100644 index 0000000..dcbcbb6 --- /dev/null +++ b/docker/web/nginx.conf @@ -0,0 +1,18 @@ +server { + listen 80; + server_name _; + + root /usr/share/nginx/html; + index index.html; + + # SPA fallback + location / { + try_files $uri $uri/ /index.html; + } + + # Cache static assets + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + } +} diff --git a/manage.sh b/manage.sh index 69176c3..e0919d7 100755 --- a/manage.sh +++ b/manage.sh @@ -32,6 +32,7 @@ usage() { echo -e " ${GREEN}logs [service]${NC} Tail logs (default: app)" echo -e " ${GREEN}update${NC} Pull latest images + rebuild app" echo -e " ${GREEN}preflight${NC} Check ports + resources; write .env" + echo -e " ${GREEN}models${NC} Check ollama models in config; pull any missing" echo -e " ${GREEN}test${NC} Run test suite" echo -e " ${GREEN}e2e [mode]${NC} Run E2E tests (mode: demo|cloud|local, default: demo)" echo -e " Set E2E_HEADLESS=false to run headed via Xvfb" @@ -91,6 +92,12 @@ case "$CMD" in make preflight PROFILE="$PROFILE" ;; + models) + info "Checking ollama models..." + conda run -n job-seeker python scripts/preflight.py --models-only + success "Model check complete." + ;; + start) info "Starting Peregrine (PROFILE=${PROFILE})..." make start PROFILE="$PROFILE" @@ -133,7 +140,7 @@ case "$CMD" in && echo "docker compose" \ || (command -v podman >/dev/null 2>&1 && echo "podman compose" || echo "podman-compose"))" $COMPOSE pull searxng ollama 2>/dev/null || true - $COMPOSE build app + $COMPOSE build app web success "Update complete. Run './manage.sh restart' to apply." ;;