This commit is contained in:
+57
-10
@@ -1,4 +1,7 @@
|
||||
FROM node:22-alpine AS builder
|
||||
# ベースイメージは digest で固定する。タグは同じ名前のまま中身が差し替わるため、
|
||||
# タグだけでは「いつビルドしても同じもの」を保証できない。バージョンを上げるときは
|
||||
# タグと digest を同時に更新すること。
|
||||
FROM node:22-alpine@sha256:c610fcdfb1d5b4740dd70c284ed3cb16bb857e0f7166196e36a5501df7a3aa32 AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
@@ -15,12 +18,14 @@ RUN npm --prefix ui ci --ignore-scripts
|
||||
# noVNC スタンドアロン (vnc.html を含む Web 配布物) を取得。
|
||||
# npm の @novnc/novnc は lib のみで vnc.html を含まないため、
|
||||
# Browser タブの iframe 用に GitHub から tarball を取得する。
|
||||
ARG NOVNC_VERSION=1.6.0
|
||||
# ARG ではなく ENV にする。ARG は `docker build --build-arg` で外から上書きでき、
|
||||
# 下の SHA-256 の固定を無効化できてしまう。
|
||||
ENV NOVNC_VERSION=1.6.0
|
||||
# Pinned SHA256 of the v${NOVNC_VERSION} source tarball. Verify the integrity of
|
||||
# the download before extracting so a compromised/MITM'd tarball can't inject
|
||||
# code into the image. To bump NOVNC_VERSION, recompute via:
|
||||
# curl -fSL "https://github.com/novnc/noVNC/archive/refs/tags/v<ver>.tar.gz" | sha256sum
|
||||
ARG NOVNC_SHA256=5066103959ef4e9b10f37e5a148627360dd8414e4cf8a7db92bdbd022e728aaa
|
||||
ENV NOVNC_SHA256=5066103959ef4e9b10f37e5a148627360dd8414e4cf8a7db92bdbd022e728aaa
|
||||
RUN apk add --no-cache --virtual .novnc-fetch curl tar \
|
||||
&& mkdir -p /app/vendor/noVNC \
|
||||
&& curl -fSL "https://github.com/novnc/noVNC/archive/refs/tags/v${NOVNC_VERSION}.tar.gz" -o /tmp/novnc.tar.gz \
|
||||
@@ -44,7 +49,7 @@ RUN npm run build:ui
|
||||
# Playwright's bundled Chromium does not run on Alpine/musl, and Xvfb/x11vnc/
|
||||
# websockify + Chromium are well-supported on Debian. The builder stage stays
|
||||
# Alpine because it only emits portable artifacts (dist/, ui/dist, vendor/).
|
||||
FROM node:22-bookworm-slim AS runtime
|
||||
FROM node:22-bookworm-slim@sha256:d649c27dae7ba0137b3cef5dd75baa422c08dc3d9e3fc0c23dfb172dc3cc6436 AS runtime
|
||||
|
||||
# System deps:
|
||||
# - git/ca-certificates/tzdata/bash: app + git ops + the bash sandbox shell
|
||||
@@ -52,10 +57,10 @@ FROM node:22-bookworm-slim AS runtime
|
||||
# - xvfb/x11vnc/websockify: the noVNC display stack (display_mode: novnc) that
|
||||
# powers the Browser tab live view, InteractiveBrowse, and the CAPTCHA pool
|
||||
# - fonts-*: legible text (incl. CJK) in the headed browser / screenshots
|
||||
# - libreoffice-impress: headless .pptx/.ppt -> PDF conversion for the file-
|
||||
# preview feature (office-preview.ts). The PDF is then rasterised to PNG via
|
||||
# the pre-baked PyMuPDF (fitz). --no-install-recommends keeps the image lean
|
||||
# (skips the GUI/java extras); CJK glyphs come from the fonts-noto-cjk above.
|
||||
# - libreoffice-impress: headless .pptx/.ppt -> PDF conversion for previews
|
||||
# - libreoffice-calc/python3-uno: trusted XLSX recalculation and formula checks
|
||||
# through runtime/excel-recalculate.py. --no-install-recommends keeps the
|
||||
# image lean; CJK glyphs come from the fonts-noto-cjk package above.
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
git \
|
||||
ca-certificates \
|
||||
@@ -70,6 +75,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
fonts-liberation \
|
||||
fonts-noto-cjk \
|
||||
libreoffice-impress \
|
||||
libreoffice-calc \
|
||||
python3-uno \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Pre-bake python packages into the system site-packages (read-only bind-mounted
|
||||
@@ -85,6 +92,12 @@ WORKDIR /app
|
||||
ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
|
||||
|
||||
COPY package.json package-lock.json* ./
|
||||
# The install-script allowlist and the rebuild driver must ship BEFORE the
|
||||
# install RUN below, because the runtime install is `--ignore-scripts` and the
|
||||
# native addon is rebuilt explicitly from this allowlist. Without these two the
|
||||
# install below cannot produce a working better-sqlite3.
|
||||
COPY security/install-scripts-allowlist.json ./security/install-scripts-allowlist.json
|
||||
COPY scripts/security/rebuild-native.mjs ./scripts/security/rebuild-native.mjs
|
||||
# build-essential compiles better-sqlite3's native addon (removed afterward to
|
||||
# stay lean). `playwright install --with-deps chromium` downloads the Chromium
|
||||
# binary INTO PLAYWRIGHT_BROWSERS_PATH and installs its shared-library apt deps
|
||||
@@ -102,9 +115,18 @@ COPY package.json package-lock.json* ./
|
||||
# and `npx playwright` fails with exit 127 (issue #007). Calling the package's
|
||||
# own cli.js sidesteps bin resolution entirely and is version-matched to the
|
||||
# installed prod `playwright`.
|
||||
#
|
||||
# `--ignore-scripts` here, not just in the builder stage. This is the SHIPPED
|
||||
# image, and build-essential is present on the very same layer, so a hijacked
|
||||
# dependency's install script would run with a compiler in reach — the most
|
||||
# permissive place in the whole pipeline. The builder stage has been guarded
|
||||
# since the start; runtime was the hole (found reviewing PR #1074).
|
||||
# The allowlisted native addon is rebuilt right after, from the same allowlist
|
||||
# CI uses, and the rebuild driver verifies it by actually opening a database.
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends build-essential \
|
||||
&& npm ci --omit=dev \
|
||||
&& npm ci --omit=dev --ignore-scripts \
|
||||
&& node scripts/security/rebuild-native.mjs \
|
||||
&& node node_modules/playwright/cli.js install --with-deps chromium \
|
||||
&& chmod -R go+rX /ms-playwright \
|
||||
&& npm cache clean --force \
|
||||
@@ -117,6 +139,11 @@ COPY --from=builder /app/ui/dist ./ui/dist
|
||||
COPY --from=builder /app/vendor ./vendor
|
||||
COPY pieces ./pieces
|
||||
COPY docs ./docs
|
||||
# 利用者向けヘルプの Markdown 原本。UI は vite が ui/dist にバンドルするので、
|
||||
# raw なファイルはここにしか無い。ReadAppDoc / ListAppDocs (help/<name>) が
|
||||
# 実行時にこれを読むため、置かないと本番だけヘルプが 1 本も引けなくなる。
|
||||
# .md だけ(同じディレクトリに置いてある文言固定テストは持ち込まない)。
|
||||
COPY ui/src/content/help/*.md ./ui/src/content/help/
|
||||
# Browser setup wizard shares its pure LLM logic (probe / parse / worker build /
|
||||
# isLlmConfigured) with the CLI wizard via this single .mjs. The server imports
|
||||
# it at runtime as `../../scripts/setup-lib.mjs` (resolves to /app/scripts from
|
||||
@@ -124,6 +151,24 @@ COPY docs ./docs
|
||||
# endpoints 500 on first `docker compose up` (Codex P2 #7). The .d.mts is
|
||||
# build-time only and intentionally omitted.
|
||||
COPY scripts/setup-lib.mjs ./scripts/setup-lib.mjs
|
||||
# ブラウザにファイル選択の画面を出させない管理ポリシー (#1148)。noVNC の画面は
|
||||
# 人がブラウザをそのまま触れるので、ファイルを選ぶボタンからサーバー上の
|
||||
# ファイルを持ち出せてしまう。銘柄ごとに置き場所が違うため 3 か所に置く
|
||||
# (Playwright 同梱 = Google Chrome for Testing / 本家 Chrome / Chromium)。
|
||||
# msedge は未対応 (置き場所の裏が取れていないので推測で足さない)。
|
||||
# エージェント側は壊れない。エージェントがブラウザへファイルを送る経路が
|
||||
# そもそも無いため (src/ に filechooser / setInputFiles は 1 か所も無い)。
|
||||
# 将来足すなら setInputFiles を使うこと。選択画面を通らないので影響を受けない。
|
||||
COPY deploy/browser-policy/agent-orchestrator.json /tmp/browser-policy.json
|
||||
RUN for d in /etc/opt/chrome_for_testing/policies/managed \
|
||||
/etc/opt/chrome/policies/managed \
|
||||
/etc/chromium/policies/managed; do \
|
||||
mkdir -p "$d" && cp /tmp/browser-policy.json "$d/agent-orchestrator.json" \
|
||||
&& chmod 644 "$d/agent-orchestrator.json"; \
|
||||
done \
|
||||
&& rm /tmp/browser-policy.json
|
||||
# Trusted helper only: agents do not edit or supply this Python source.
|
||||
COPY runtime/excel-recalculate.py ./runtime/excel-recalculate.py
|
||||
|
||||
# Ship config.yaml.example as a REFERENCE, plus a MINIMAL unconfigured
|
||||
# config.yaml. A fresh `docker compose up` (no ./config.yaml bind-mount, no
|
||||
@@ -147,7 +192,9 @@ RUN mkdir -p /app/data /workspaces \
|
||||
# HOST=0.0.0.0 is required INSIDE the container so the published port is
|
||||
# reachable. docker-compose.yml publishes that port on ALL host interfaces by
|
||||
# default, so a Docker deployment is reachable from the LAN out of the box —
|
||||
# enabling auth/TLS before exposing it is the operator's responsibility (see
|
||||
# which is exactly the condition that makes a FRESH install generate an admin
|
||||
# login on first boot instead of coming up open (#1024, initial-admin.ts). TLS
|
||||
# and the rest of the hardening are still the operator's responsibility (see
|
||||
# docs/docker.md, SECURITY.md). The app's own default (when HOST is unset, e.g.
|
||||
# bare-metal) is 127.0.0.1; see createCoreServer in src/bridge/server.ts.
|
||||
ENV NODE_ENV=production \
|
||||
|
||||
Reference in New Issue
Block a user