-
-
Notifications
You must be signed in to change notification settings - Fork 187
Expand file tree
/
Copy pathDockerfile
More file actions
93 lines (85 loc) · 4.75 KB
/
Copy pathDockerfile
File metadata and controls
93 lines (85 loc) · 4.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# syntax=docker/dockerfile:1
# =============================================================================
# wigolo container image — two build targets:
# default (slim): OS libraries for the browser engine baked at build time;
# the browser binary and on-device models download on FIRST USE
# into the /data volume. Smallest image; ideal for MCP stdio use.
# full: browser binary preinstalled at build time. Larger image;
# ideal for JS-render-heavy or ephemeral `--rm` runs with no
# persistent volume.
# Build the default target: docker build --target default -t wigolo .
# Build the full target: docker build --target full -t wigolo:full .
# =============================================================================
# ---- builder: compile TypeScript to dist/ ----
FROM node:22-bookworm-slim AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
# ---- deps: install production node_modules once, shared by both targets ----
FROM node:22-bookworm-slim AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
# ---- base: shared runtime layout with the browser engine's OS libraries baked ----
# `playwright install-deps chromium` installs the OS shared libraries the browser
# engine needs (deps ONLY, NOT the browser binary) as ROOT at build time. Without
# them, a first-use lazy install as the non-root `node` user cannot add system
# libs (no passwordless sudo) and the browser-engine launch smoke-test fails,
# degrading that tier permanently. With them baked, the lazy path works: the first
# JS-render fetch downloads only the browser binary into the /data volume and
# launches cleanly.
#
# No sudo in the image: the first-use deps-strategy probe treats its absence as
# the 'skip' strategy (the baked libraries make the deps step unnecessary anyway).
# No python either — it is only needed by the opt-in search-engine sidecar, and
# doctor's runtime check is scoped to that backend.
# Start from a CLEAN slim base (not `FROM deps`) so node_modules lands in the
# image exactly once, via a single --chown COPY. `FROM deps` + a second COPY +
# `chown -R /app` would triplicate the ~750MB node_modules layer.
FROM node:22-bookworm-slim AS base
ENV NODE_ENV=production \
WIGOLO_DATA_DIR=/data \
PLAYWRIGHT_BROWSERS_PATH=/data/browsers
WORKDIR /app
# --chown at copy time avoids a costly `chown -R` layer that would duplicate the
# whole node_modules tree.
COPY --chown=node:node --from=deps /app/node_modules ./node_modules
COPY --chown=node:node --from=builder /app/dist ./dist
COPY --chown=node:node package.json ./
COPY --chown=node:node skills/ ./skills/
# Bake the browser engine's OS libraries via the LOCAL playwright CLI (already in
# node_modules) so the version matches the runtime and no throwaway playwright is
# downloaded. install-deps runs apt-get itself (we are root at build time).
RUN ./node_modules/.bin/playwright install-deps chromium \
&& rm -rf /var/lib/apt/lists/*
# Writable location for the local cache, on-device models, browser binary, and
# encrypted keys. The volume persists all of these across container runs.
RUN mkdir -p /data/browsers && chown node:node /data /data/browsers
VOLUME ["/data"]
# stdio MCP server by default. No image-level HEALTHCHECK: the default command
# speaks the stdio MCP protocol and exposes no HTTP endpoint, so a baked
# healthcheck would mark every container permanently unhealthy. For `serve` mode
# use packaging/compose.serve.yml, which adds a daemon HTTP healthcheck.
ENTRYPOINT ["node", "dist/index.js"]
CMD ["mcp"]
# ---- default: slim image, browser binary + models download on first use ----
FROM base AS default
LABEL org.opencontainers.image.title="wigolo" \
org.opencontainers.image.description="Local-first web intelligence MCP server. The browser engine binary and on-device models download on first use into the /data volume." \
org.opencontainers.image.source="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/KnockOutEZ/wigolo"
USER node
# ---- full: browser binary preinstalled at build for --rm / no-volume use ----
FROM base AS full
LABEL org.opencontainers.image.title="wigolo" \
org.opencontainers.image.description="Local-first web intelligence MCP server with the browser engine preinstalled. On-device models download on first use." \
org.opencontainers.image.source="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/KnockOutEZ/wigolo"
# Preinstall the browser binary into an image-baked path (not the volume) so
# JS-render works with no first-use download and no volume. Installed as root,
# then made readable by the node user.
ENV PLAYWRIGHT_BROWSERS_PATH=/opt/browsers
RUN mkdir -p /opt/browsers \
&& ./node_modules/.bin/playwright install chromium \
&& chown -R node:node /opt/browsers
USER node