diff --git a/openclaw/Dockerfile b/openclaw/Dockerfile index c15b761..449fe2c 100644 --- a/openclaw/Dockerfile +++ b/openclaw/Dockerfile @@ -9,23 +9,20 @@ # extensions/, so the main build layer is not invalidated by unrelated # extension source changes. # -# Two runtime variants: -# Default (bookworm): docker build . -# Slim (bookworm-slim): docker build --build-arg OPENCLAW_VARIANT=slim . +# Build stages use full bookworm; the runtime image is always bookworm-slim. ARG OPENCLAW_EXTENSIONS="" -ARG OPENCLAW_VARIANT=default ARG OPENCLAW_BUNDLED_PLUGIN_DIR=extensions ARG OPENCLAW_EXCLUDE_BUNDLED_PLUGINS="qqbot feishu" -ARG OPENCLAW_DOCKER_APT_UPGRADE=1 ARG OPENCLAW_NODE_BOOKWORM_IMAGE="node:24-bookworm@sha256:3a09aa6354567619221ef6c45a5051b671f953f0a1924d1f819ffb236e520e6b" -ARG OPENCLAW_NODE_BOOKWORM_DIGEST="sha256:3a09aa6354567619221ef6c45a5051b671f953f0a1924d1f819ffb236e520e6b" ARG OPENCLAW_NODE_BOOKWORM_SLIM_IMAGE="node:24-bookworm-slim@sha256:e8e2e91b1378f83c5b2dd15f0247f34110e2fe895f6ca7719dbb780f929368eb" ARG OPENCLAW_NODE_BOOKWORM_SLIM_DIGEST="sha256:e8e2e91b1378f83c5b2dd15f0247f34110e2fe895f6ca7719dbb780f929368eb" # Base images are pinned to SHA256 digests for reproducible builds. -# Trade-off: digests must be updated manually when upstream tags move. -# To update, run: docker buildx imagetools inspect node:24-bookworm (or podman) -# and replace the digest below with the current multi-arch manifest list entry. +# Dependabot refreshes these blessed digests; release builds consume the +# reviewed base snapshot instead of mutating distro state on every build. +# To update, run: docker buildx imagetools inspect node:24-bookworm and +# node:24-bookworm-slim (or podman) and replace the digests below with the +# current multi-arch manifest list entries. FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS ext-deps ARG OPENCLAW_EXTENSIONS @@ -75,10 +72,20 @@ RUN --mount=type=cache,id=openclaw-pnpm-store,target=/root/.local/share/pnpm/sto NODE_OPTIONS=--max-old-space-size=2048 pnpm install --frozen-lockfile # pnpm v10+ may append peer-resolution hashes to virtual-store folder names; do not hardcode `.pnpm/...` -# paths. Fail fast here if the Matrix native binding did not materialize after install. -RUN echo "==> Verifying critical native addons..." && \ +# paths. Matrix's native downloader can hit transient release CDN errors while +# still exiting successfully, so retry the package downloader before failing. +RUN set -eux; \ + echo "==> Verifying critical native addons..."; \ + for attempt in 1 2 3 4 5; do \ + if find /app/node_modules -name "matrix-sdk-crypto*.node" 2>/dev/null | grep -q .; then \ + exit 0; \ + fi; \ + echo "matrix-sdk-crypto native addon missing; retrying download (${attempt}/5)"; \ + node /app/node_modules/@matrix-org/matrix-sdk-crypto-nodejs/download-lib.js || true; \ + sleep $((attempt * 2)); \ + done; \ find /app/node_modules -name "matrix-sdk-crypto*.node" 2>/dev/null | grep -q . || \ - (echo "ERROR: matrix-sdk-crypto native addon missing (pnpm install may have silently failed on this arch)" >&2 && exit 1) + (echo "ERROR: matrix-sdk-crypto native addon missing after retries" >&2 && exit 1) COPY . . @@ -127,20 +134,13 @@ RUN printf 'packages:\n - .\n - ui\n' > /tmp/pnpm-workspace.runtime.yaml && \ done && \ find dist -type f \( -name '*.d.ts' -o -name '*.d.mts' -o -name '*.d.cts' -o -name '*.map' \) -delete -FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS base-default -ARG OPENCLAW_NODE_BOOKWORM_DIGEST -LABEL org.opencontainers.image.base.name="docker.io/library/node:24-bookworm" \ - org.opencontainers.image.base.digest="${OPENCLAW_NODE_BOOKWORM_DIGEST}" - -FROM ${OPENCLAW_NODE_BOOKWORM_SLIM_IMAGE} AS base-slim +FROM ${OPENCLAW_NODE_BOOKWORM_SLIM_IMAGE} AS base-runtime ARG OPENCLAW_NODE_BOOKWORM_SLIM_DIGEST LABEL org.opencontainers.image.base.name="docker.io/library/node:24-bookworm-slim" \ org.opencontainers.image.base.digest="${OPENCLAW_NODE_BOOKWORM_SLIM_DIGEST}" -FROM base-${OPENCLAW_VARIANT} -ARG OPENCLAW_VARIANT +FROM base-runtime ARG OPENCLAW_BUNDLED_PLUGIN_DIR -ARG OPENCLAW_DOCKER_APT_UPGRADE # OCI base-image metadata for downstream image consumers. # If you change these annotations, also update: @@ -155,24 +155,20 @@ LABEL org.opencontainers.image.source="https://github.com/openclaw/openclaw" \ WORKDIR /app -# Install system utilities present in bookworm but missing in bookworm-slim. -# On the full bookworm image these are already installed (apt-get is a no-op). -# Smoke workflows can opt out of distro upgrades to cut repeated CI time while -# keeping the default runtime image behavior unchanged. +# Install runtime system utilities missing from bookworm-slim. RUN --mount=type=cache,id=openclaw-bookworm-apt-cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,id=openclaw-bookworm-apt-lists,target=/var/lib/apt,sharing=locked \ apt-get update && \ - if [ "${OPENCLAW_DOCKER_APT_UPGRADE}" != "0" ]; then \ - DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends; \ - fi && \ DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ - procps hostname curl git lsof openssl + ca-certificates procps hostname curl git lsof openssl && \ + update-ca-certificates RUN chown node:node /app COPY --from=runtime-assets --chown=node:node /app/dist ./dist COPY --from=runtime-assets --chown=node:node /app/node_modules ./node_modules COPY --from=runtime-assets --chown=node:node /app/package.json . +COPY --from=runtime-assets --chown=node:node /app/patches ./patches COPY --from=runtime-assets --chown=node:node /app/openclaw.mjs . COPY --from=runtime-assets --chown=node:node /app/${OPENCLAW_BUNDLED_PLUGIN_DIR} ./${OPENCLAW_BUNDLED_PLUGIN_DIR} COPY --from=runtime-assets --chown=node:node /app/skills ./skills @@ -200,11 +196,6 @@ RUN install -d -m 0755 "$COREPACK_HOME" && \ RUN npm install -g clawhub@latest && \ npm cache clean --force -RUN install -d -o node -g node /home/node/.local/bin && \ - su -s /bin/sh node -c 'curl -fsSL https://skillhub-1388575217.cos.ap-guangzhou.myqcloud.com/install/install.sh | bash -s -- --no-skills' && \ - ln -sf /home/node/.local/bin/skillhub /usr/local/bin/skillhub && \ - chmod 755 /usr/local/bin/skillhub - # Install additional system packages needed by your skills or extensions. # The runtime already includes git and curl from the base package set. # Default extras focus on common media and CLI workflows. @@ -220,6 +211,11 @@ RUN --mount=type=cache,id=openclaw-bookworm-apt-cache,target=/var/cache/apt,shar fi; \ fi +RUN install -d -o node -g node /home/node/.local/bin && \ + su -s /bin/sh node -c 'HOME=/home/node curl -fsSL https://skillhub.cn/install/install.sh | HOME=/home/node bash -s -- --no-skills' && \ + ln -sf /home/node/.local/bin/skillhub /usr/local/bin/skillhub && \ + chmod 755 /usr/local/bin/skillhub + # Optionally install Chromium and Xvfb for browser automation. # Build with: docker build --build-arg OPENCLAW_INSTALL_BROWSER=1 ... # Adds ~300MB but eliminates the 60-90s Playwright install on every container start. @@ -271,6 +267,9 @@ RUN --mount=type=cache,id=openclaw-bookworm-apt-cache,target=/var/cache/apt,shar RUN ln -sf /app/openclaw.mjs /usr/local/bin/openclaw && \ chmod 755 /usr/local/bin/docker-entrypoint.sh /app/openclaw.mjs +RUN install -d -m 0700 -o node -g node /home/node/.openclaw && \ + stat -c '%U:%G %a' /home/node/.openclaw | grep -qx 'node:node 700' + ENV NODE_ENV=production ENV PLAYWRIGHT_BROWSERS_PATH=/home/node/.cache/ms-playwright