The web image silently stopped building, so production kept serving the previous openpencil build while the deploy job still reported success (deploy-images.sh treats this image as optional): - Copy every workspace manifest (COPY --parents packages/*/package.json tools/**/package.json) instead of a hand-kept list. Upstream added packages/design-jsx, packages/emit and tools/**, so the old list made `bun install --frozen-lockfile` fail with "Workspace not found". - Build the SPA with Node, not bun: Vite 8 fails loading vite.config.ts under bun-in-Docker (vite-module-runner import-meta-resolve). bun still runs the lockfile install and build:packages; recreate the bunx symlink for the package build scripts. Verified: docker build -f Dockerfile.web-vue succeeds and the image serves the merged build.
87 lines
3.9 KiB
Docker
87 lines
3.9 KiB
Docker
# syntax=docker/dockerfile:1
|
|
#
|
|
# Dockerfile.web-vue — container for the VUE editor (upstream master, v0.15.x) + MCP.
|
|
#
|
|
# Replaces the retired Dockerfile.web-rust (Rust web host, main branch). This
|
|
# image serves the static SPA build (the same `dist/` artifact that Cloudflare
|
|
# Pages deploys for app.openpencil.dev) on :3100 AND the @open-pencil/mcp
|
|
# Streamable-HTTP server on :7600, both from one container via the entrypoint.
|
|
# w4c-chatapi talks MCP to http://openpencil:7600/mcp (OpenPencilMcp__HttpEndpoint).
|
|
#
|
|
# Build:
|
|
# docker build -f Dockerfile.web-vue -t w4c-openpencil:latest .
|
|
#
|
|
# Run:
|
|
# docker run -p 3100:3100 -p 7600:7600 \
|
|
# -e OPENPENCIL_MCP_AUTH_TOKEN=... \
|
|
# -e OPENPENCIL_MCP_CORS_ORIGIN=https://openpencil.wiz4chat.com \
|
|
# -v openpencil_data:/data \
|
|
# w4c-openpencil:latest
|
|
|
|
# ── Stage 1: builder — bun for install/package build, Node for Vite ──────────
|
|
#
|
|
# The SPA is built with Node, not bun. Vite 8 bundles vite.config.ts through its
|
|
# module runner, and that step fails under bun-in-Docker regardless of the bun
|
|
# version (`Cannot find package 'vite-module-runner:import-meta-resolve'` on
|
|
# 1.4.2, a bare `ResolveMessage {}` on 1.3.14), while the same tree builds under
|
|
# Node 22 here and under bun on the host. bun still owns the lockfile install
|
|
# and `build:packages` (which runs TypeScript through bun).
|
|
FROM oven/bun:1 AS bun
|
|
|
|
FROM node:22-bookworm AS builder
|
|
COPY --from=bun /usr/local/bin/bun /usr/local/bin/bun
|
|
# Package build scripts call `bunx tsdown`; the official image provides bunx only
|
|
# as a symlink to bun, so recreate it (argv[0] === "bunx" makes bun run `bun x`).
|
|
RUN ln -s /usr/local/bin/bun /usr/local/bin/bunx
|
|
|
|
WORKDIR /app
|
|
|
|
# Lockfile + manifests first for layer caching. `COPY --parents` mirrors the whole
|
|
# workspace tree without listing each workspace by hand — the explicit list went
|
|
# stale as upstream added workspaces (packages/design-jsx, packages/emit, tools/**),
|
|
# and a missing manifest makes `bun install --frozen-lockfile` fail with
|
|
# "Workspace not found". That failure is silent in production: deploy-images.sh
|
|
# treats this image as optional, so the deploy job still succeeds while the
|
|
# openpencil container keeps serving the previous build.
|
|
COPY package.json bun.lock bunfig.toml ./
|
|
COPY --parents packages/*/package.json tools/**/package.json ./
|
|
|
|
RUN bun install --frozen-lockfile
|
|
|
|
# Full source (excludes heavy local build outputs via .dockerignore).
|
|
COPY . .
|
|
|
|
# Build the workspace packages (bun) and the SPA (Node — see the stage note
|
|
# above). Deliberately NOT `bun run build`: that also runs the repo's oxlint
|
|
# quality gate (`lint:structure` + type-aware oxlint over ~2k files). Linting is
|
|
# a CI/`bun run check` concern, not an image build step — it added ~7 s and
|
|
# spammed the deploy log with the fork's pre-existing `max-lines` warnings.
|
|
RUN bun run build:packages && node node_modules/vite/bin/vite.js build
|
|
|
|
# Prune to production dependencies so the runtime layer is lean. bun keeps
|
|
# workspace symlinks; the MCP server's deps (hono, @modelcontextprotocol/sdk,
|
|
# ws, zod + @open-pencil/core) are all in the prod graph.
|
|
RUN bun install --production --frozen-lockfile
|
|
|
|
# ── Stage 2: runtime — static SPA (:3100) + MCP (:7600) ─────────────────────
|
|
FROM oven/bun:1-slim AS runtime
|
|
|
|
WORKDIR /app
|
|
|
|
COPY --from=builder /app/dist ./dist
|
|
COPY --from=builder /app/package.json ./package.json
|
|
COPY --from=builder /app/bun.lock ./bun.lock
|
|
COPY --from=builder /app/bunfig.toml ./bunfig.toml
|
|
COPY --from=builder /app/node_modules ./node_modules
|
|
COPY --from=builder /app/packages ./packages
|
|
COPY --from=builder /app/docker/static-server.mjs ./static-server.mjs
|
|
COPY --from=builder /app/docker/entrypoint.sh /entrypoint.sh
|
|
|
|
# Writable document root for MCP file-scoped tools (open_file / new_document /
|
|
# save_file). Keep on a volume so documents survive container restarts.
|
|
ENV OPENPENCIL_MCP_ROOT=/data
|
|
|
|
EXPOSE 3100 7600
|
|
|
|
ENTRYPOINT ["/entrypoint.sh"]
|