| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| ARG OPENCLAW_EXTENSIONS="" |
| ARG OPENCLAW_VARIANT=default |
| 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" |
|
|
| |
| |
| |
| |
|
|
| FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS ext-deps |
| ARG OPENCLAW_EXTENSIONS |
| COPY extensions /tmp/extensions |
| |
| RUN mkdir -p /out && \ |
| for ext in $OPENCLAW_EXTENSIONS; do \ |
| if [ -f "/tmp/extensions/$ext/package.json" ]; then \ |
| mkdir -p "/out/$ext" && \ |
| cp "/tmp/extensions/$ext/package.json" "/out/$ext/package.json"; \ |
| fi; \ |
| done |
|
|
| |
| FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS build |
|
|
| |
| |
| RUN set -eux; \ |
| for attempt in 1 2 3 4 5; do \ |
| if curl --retry 5 --retry-all-errors --retry-delay 2 -fsSL https://bun.sh/install | bash; then \ |
| break; \ |
| fi; \ |
| if [ "$attempt" -eq 5 ]; then \ |
| exit 1; \ |
| fi; \ |
| sleep $((attempt * 2)); \ |
| done |
| ENV PATH="/root/.bun/bin:${PATH}" |
|
|
| RUN corepack enable |
|
|
| WORKDIR /app |
|
|
| COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./ |
| COPY ui/package.json ./ui/package.json |
| COPY patches ./patches |
|
|
| COPY --from=ext-deps /out/ ./extensions/ |
|
|
| |
| |
| RUN --mount=type=cache,id=openclaw-pnpm-store,target=/root/.local/share/pnpm/store,sharing=locked \ |
| NODE_OPTIONS=--max-old-space-size=2048 pnpm install --frozen-lockfile |
|
|
| COPY . . |
|
|
| |
| |
| RUN for dir in /app/extensions /app/.agent /app/.agents; do \ |
| if [ -d "$dir" ]; then \ |
| find "$dir" -type d -exec chmod 755 {} +; \ |
| find "$dir" -type f -exec chmod 644 {} +; \ |
| fi; \ |
| done |
|
|
| |
| |
| |
| RUN pnpm canvas:a2ui:bundle || \ |
| (echo "A2UI bundle: creating stub (non-fatal)" && \ |
| mkdir -p src/canvas-host/a2ui && \ |
| echo "/* A2UI bundle unavailable in this build */" > src/canvas-host/a2ui/a2ui.bundle.js && \ |
| echo "stub" > src/canvas-host/a2ui/.bundle.hash && \ |
| rm -rf vendor/a2ui apps/shared/OpenClawKit/Tools/CanvasA2UI) |
| RUN pnpm build:docker |
| |
| ENV OPENCLAW_PREFER_PNPM=1 |
| RUN pnpm ui:build |
|
|
| |
| |
| FROM build AS runtime-assets |
| RUN CI=true pnpm prune --prod && \ |
| 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 |
| 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 |
|
|
| |
| |
| |
| |
| LABEL org.opencontainers.image.source="https://github.com/openclaw/openclaw" \ |
| org.opencontainers.image.url="https://openclaw.ai" \ |
| org.opencontainers.image.documentation="https://docs.openclaw.ai/install/docker" \ |
| org.opencontainers.image.licenses="MIT" \ |
| org.opencontainers.image.title="OpenClaw" \ |
| org.opencontainers.image.description="OpenClaw gateway and CLI runtime container image" |
|
|
| WORKDIR /app |
|
|
| |
| |
| 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 && \ |
| DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends && \ |
| DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ |
| procps hostname curl git openssl |
|
|
| 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/openclaw.mjs . |
| COPY --from=runtime-assets --chown=node:node /app/extensions ./extensions |
| COPY --from=runtime-assets --chown=node:node /app/skills ./skills |
| COPY --from=runtime-assets --chown=node:node /app/docs ./docs |
|
|
| |
| |
| |
| ENV COREPACK_HOME=/usr/local/share/corepack |
| RUN install -d -m 0755 "$COREPACK_HOME" && \ |
| corepack enable && \ |
| for attempt in 1 2 3 4 5; do \ |
| if corepack prepare "$(node -p "require('./package.json').packageManager")" --activate; then \ |
| break; \ |
| fi; \ |
| if [ "$attempt" -eq 5 ]; then \ |
| exit 1; \ |
| fi; \ |
| sleep $((attempt * 2)); \ |
| done && \ |
| chmod -R a+rX "$COREPACK_HOME" |
|
|
| |
| |
| ARG OPENCLAW_DOCKER_APT_PACKAGES="" |
| 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 \ |
| if [ -n "$OPENCLAW_DOCKER_APT_PACKAGES" ]; then \ |
| apt-get update && \ |
| DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends $OPENCLAW_DOCKER_APT_PACKAGES; \ |
| fi |
|
|
| |
| |
| |
| |
| ARG OPENCLAW_INSTALL_BROWSER="" |
| 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 \ |
| if [ -n "$OPENCLAW_INSTALL_BROWSER" ]; then \ |
| apt-get update && \ |
| DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends xvfb && \ |
| mkdir -p /home/node/.cache/ms-playwright && \ |
| PLAYWRIGHT_BROWSERS_PATH=/home/node/.cache/ms-playwright \ |
| node /app/node_modules/playwright-core/cli.js install --with-deps chromium && \ |
| chown -R node:node /home/node/.cache/ms-playwright; \ |
| fi |
|
|
| |
| |
| |
| |
| ARG OPENCLAW_INSTALL_DOCKER_CLI="" |
| ARG OPENCLAW_DOCKER_GPG_FINGERPRINT="9DC858229FC7DD38854AE2D88D81803C0EBFCD88" |
| 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 \ |
| if [ -n "$OPENCLAW_INSTALL_DOCKER_CLI" ]; then \ |
| apt-get update && \ |
| DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ |
| ca-certificates curl gnupg && \ |
| install -m 0755 -d /etc/apt/keyrings && \ |
| |
| |
| curl -fsSL https://download.docker.com/linux/debian/gpg -o /tmp/docker.gpg.asc && \ |
| expected_fingerprint="$(printf '%s' "$OPENCLAW_DOCKER_GPG_FINGERPRINT" | tr '[:lower:]' '[:upper:]' | tr -d '[:space:]')" && \ |
| actual_fingerprint="$(gpg --batch --show-keys --with-colons /tmp/docker.gpg.asc | awk -F: '$1 == "fpr" { print toupper($10); exit }')" && \ |
| if [ -z "$actual_fingerprint" ] || [ "$actual_fingerprint" != "$expected_fingerprint" ]; then \ |
| echo "ERROR: Docker apt key fingerprint mismatch (expected $expected_fingerprint, got ${actual_fingerprint:-<empty>})" >&2; \ |
| exit 1; \ |
| fi && \ |
| gpg --dearmor -o /etc/apt/keyrings/docker.gpg /tmp/docker.gpg.asc && \ |
| rm -f /tmp/docker.gpg.asc && \ |
| chmod a+r /etc/apt/keyrings/docker.gpg && \ |
| printf 'deb [arch=%s signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian bookworm stable\n' \ |
| "$(dpkg --print-architecture)" > /etc/apt/sources.list.d/docker.list && \ |
| apt-get update && \ |
| DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ |
| docker-ce-cli docker-compose-plugin; \ |
| fi |
|
|
| |
| RUN ln -sf /app/openclaw.mjs /usr/local/bin/openclaw \ |
| && chmod 755 /app/openclaw.mjs |
|
|
| ENV NODE_ENV=production |
|
|
| |
| |
| |
| USER node |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| HEALTHCHECK --interval=3m --timeout=10s --start-period=15s --retries=3 \ |
| CMD node -e "fetch('http://127.0.0.1:18789/healthz').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))" |
| CMD ["node", "openclaw.mjs", "gateway", "--allow-unconfigured"] |
|
|