mirror of
https://github.com/sredevopsorg/deepseek-kubernetes-sandbox.git
synced 2026-11-03 01:13:24 +00:00
152 lines
6.5 KiB
Markdown
152 lines
6.5 KiB
Markdown
Here is the complete updated Dockerfile incorporating the hoisted deploy fix and the dependency patch. The key changes versus the last version are in the deploy block: `--legacy` is dropped, `node-linker=hoisted` and `inject-workspace-packages` are enabled, and the missing workspace peer is added via the `workspace:*` protocol.
|
|
|
|
```dockerfile
|
|
# syntax=docker/dockerfile:1.7
|
|
|
|
ARG NODE_BUILD_IMAGE=docker.io/node:24-trixie
|
|
ARG NODE_RUNTIME_IMAGE=docker.io/node:trixie-slim
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Build stage
|
|
# ---------------------------------------------------------------------------
|
|
FROM ${NODE_BUILD_IMAGE} AS build
|
|
|
|
ARG DSH_REPO=https://github.com/deepseek-ai/deepseek-harness.git
|
|
ARG DSH_VERSION=dsh-v0.2.1-rc.2
|
|
ARG PNPM_VERSION=11.28.5
|
|
|
|
# CI=true skips the repository's lefthook postinstall in the container.
|
|
ENV CI=true \
|
|
NODE_OPTIONS=--max-old-space-size=4096
|
|
|
|
RUN corepack enable \
|
|
&& corepack prepare "pnpm@${PNPM_VERSION}" --activate
|
|
|
|
WORKDIR /src
|
|
|
|
# Exact upstream tag, e.g. dsh-v0.2.1-rc.2.
|
|
RUN git clone --depth 1 --branch "${DSH_VERSION}" "${DSH_REPO}" .
|
|
|
|
RUN pnpm install --frozen-lockfile
|
|
|
|
# ── Workaround for upstream packaging defect ──────────────────────────────
|
|
# dsh-app-boot statically imports @deepseek-ai/cordis-plugin-group, which is
|
|
# only a peer/workspace dependency and is omitted by `pnpm deploy --prod`.
|
|
# Promote it to a real dependency of @deepseek-ai/dsh so it is always part of
|
|
# the deploy closure.
|
|
RUN pnpm --filter @deepseek-ai/dsh add @deepseek-ai/cordis-plugin-group@workspace:*
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
|
|
# Builds native addon, Host/Client bundles, and the Web frontend.
|
|
RUN pnpm run build
|
|
|
|
# ── Production deploy closure ────────────────────────────────────────────
|
|
# A hoisted (npm-style) node_modules is required: the default isolated pnpm
|
|
# layout drops peer dependencies such as @deepseek-ai/cosmokit from the
|
|
# deployed tree, causing ERR_MODULE_NOT_FOUND at runtime. `--legacy` is
|
|
# intentionally NOT used, so pnpm's modern deploy binds peers correctly.
|
|
RUN pnpm --config.node-linker=hoisted \
|
|
--config.inject-workspace-packages=true \
|
|
deploy --prod /opt/dsh \
|
|
&& test -f /opt/dsh/lib/bin.js \
|
|
&& test -d /opt/dsh/node_modules/@deepseek-ai/cosmokit \
|
|
&& test -d /opt/dsh/node_modules/@deepseek-ai/cordis-plugin-group \
|
|
&& node /opt/dsh/lib/bin.js web --help >/dev/null
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Runtime stage
|
|
# ---------------------------------------------------------------------------
|
|
FROM ${NODE_RUNTIME_IMAGE} AS runtime
|
|
|
|
ARG DSH_VERSION
|
|
|
|
LABEL org.opencontainers.image.title="DeepSeek Harness Web" \
|
|
org.opencontainers.image.version="${DSH_VERSION}" \
|
|
org.opencontainers.image.source="https://github.com/deepseek-ai/deepseek-harness"
|
|
|
|
ENV NODE_ENV=production \
|
|
HOME=/home/node \
|
|
DSH_HOME=/home/node/.dsh \
|
|
DSH_PORT=3080 \
|
|
PATH="/app/node_modules/.bin:${PATH}"
|
|
|
|
# git/ripgrep are useful for DSH agent tools; tini handles signals.
|
|
RUN apt-get update \
|
|
&& apt-get install -y --no-install-recommends \
|
|
ca-certificates \
|
|
git \
|
|
ripgrep \
|
|
tini \
|
|
&& rm -rf /var/lib/apt/lists/* \
|
|
&& install -d -o node -g node -m 0755 /workspace "${DSH_HOME}"
|
|
|
|
COPY --from=build --chown=node:node /opt/dsh /app
|
|
|
|
COPY <<'EOF' /usr/local/bin/dsh-entrypoint
|
|
#!/bin/sh
|
|
set -eu
|
|
|
|
: "${DSH_PORT:=3080}"
|
|
: "${DSH_HOST:=}"
|
|
DSH_PUBLIC_URL="${DSH_PUBLIC_URL-http://localhost:${DSH_PORT}}"
|
|
|
|
# DSH rejects wildcard hosts. Pick the container/pod's first non-loopback IPv4.
|
|
if [ -z "$DSH_HOST" ]; then
|
|
DSH_HOST="$(node -e 'const os=require("os"); const ifaces=Object.values(os.networkInterfaces()).flat(); const addr=ifaces.find(v=>v&&v.family==="IPv4"&&!v.internal); if(!addr){process.exit(1)} process.stdout.write(addr.address)')"
|
|
fi
|
|
|
|
if [ -n "$DSH_PUBLIC_URL" ]; then
|
|
set -- --public-url "$DSH_PUBLIC_URL" "$@"
|
|
fi
|
|
|
|
exec node /app/lib/bin.js web \
|
|
--no-open \
|
|
--host "$DSH_HOST" \
|
|
--port "$DSH_PORT" \
|
|
--trusted-host localhost \
|
|
--trusted-host 127.0.0.1 \
|
|
"$@"
|
|
EOF
|
|
|
|
RUN chmod 0755 /usr/local/bin/dsh-entrypoint
|
|
|
|
WORKDIR /workspace
|
|
USER node
|
|
|
|
EXPOSE 3080
|
|
VOLUME ["/home/node/.dsh"]
|
|
STOPSIGNAL SIGTERM
|
|
ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/dsh-entrypoint"]
|
|
```
|
|
|
|
### What changed and why
|
|
|
|
| Area | Before | Now | Reason |
|
|
| ------ | -------- | ----- | -------- |
|
|
| Deploy linker | default isolated `.pnpm` store | `--config.node-linker=hoisted` | Produces a flat npm-style tree so peer deps like `@deepseek-ai/cosmokit` are physically present. |
|
|
| Deploy flag | `--legacy` | removed | Legacy deployer does not reliably bind peer dependencies; the modern deployer does. |
|
|
| Workspace binding | implicit | `--config.inject-workspace-packages=true` | Guarantees workspace packages and their peers are bound into the closure deterministically. |
|
|
| Missing peer patch | `@deepseek-ai/cordis-plugin-group@^1.0.1` | `@deepseek-ai/cordis-plugin-group@workspace:*` | Correct protocol for a monorepo-internal package; no dependency on a published npm version. |
|
|
| Verification | only `bin.js` exists + `web --help` | also asserts `cosmokit` and `cordis-plugin-group` directories exist | Fails the build early if the closure is still incomplete, instead of failing at container start. |
|
|
|
|
### Build and run
|
|
|
|
```bash
|
|
docker build \
|
|
--build-arg DSH_VERSION=dsh-v0.2.1-rc.2 \
|
|
-t dsh-web:0.2.1-rc.2 .
|
|
|
|
docker run --rm -it \
|
|
-p 3080:3080 \
|
|
-v dsh-home:/home/node/.dsh \
|
|
-e DEEPSEEK_API_KEY \
|
|
dsh-web:0.2.1-rc.2
|
|
```
|
|
|
|
Then open the `dsh web:` URL printed in the logs (it carries a per-process access token).
|
|
|
|
### If the `pnpm add …@workspace:*` step ever fails
|
|
|
|
That would mean `@deepseek-ai/cordis-plugin-group` is not a workspace package in the chosen tag. In that case remove the two `pnpm --filter … add` lines; the hoisted linker alone is usually sufficient to include peer dependencies. You can confirm by checking that the `test -d /opt/dsh/node_modules/@deepseek-ai/cordis-plugin-group` assertion still passes.
|