1
0
mirror of https://github.com/sredevopsorg/deepseek-kubernetes-sandbox.git synced 2026-11-03 01:13:24 +00:00
Files
deepseek-kubernetes-sandbox/README.md
Nicolás Georger f3d4312089 Initial commit
Signed-off-by: Nicolás Georger <info@sredevops.org>
2026-10-21 00:39:54 -03:00

6.5 KiB

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.

# 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

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.