Skip to content

Commit f0301c1

Browse files
feat: update openclaw Dockerfile
1 parent 1dd5a47 commit f0301c1

1 file changed

Lines changed: 52 additions & 41 deletions

File tree

openclaw/Dockerfile

Lines changed: 52 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# syntax=docker/dockerfile:1.7
2+
13
# Opt-in extension dependencies at build time (space-separated directory names).
24
# Example: docker build --build-arg OPENCLAW_EXTENSIONS="diagnostics-otel matrix" .
35
#
@@ -47,16 +49,25 @@ WORKDIR /app
4749
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./
4850
COPY ui/package.json ./ui/package.json
4951
COPY patches ./patches
50-
COPY scripts ./scripts
5152

5253
COPY --from=ext-deps /out/ ./extensions/
5354

5455
# Reduce OOM risk on low-memory hosts during dependency installation.
5556
# Docker builds on small VMs may otherwise fail with "Killed" (exit 137).
56-
RUN NODE_OPTIONS=--max-old-space-size=2048 pnpm install --frozen-lockfile
57+
RUN --mount=type=cache,id=openclaw-pnpm-store,target=/root/.local/share/pnpm/store,sharing=locked \
58+
NODE_OPTIONS=--max-old-space-size=2048 pnpm install --frozen-lockfile
5759

5860
COPY . .
5961

62+
# Normalize extension paths now so runtime COPY preserves safe modes
63+
# without adding a second full extensions layer.
64+
RUN for dir in /app/extensions /app/.agent /app/.agents; do \
65+
if [ -d "$dir" ]; then \
66+
find "$dir" -type d -exec chmod 755 {} +; \
67+
find "$dir" -type f -exec chmod 644 {} +; \
68+
fi; \
69+
done
70+
6071
# A2UI bundle may fail under QEMU cross-compilation (e.g. building amd64
6172
# on Apple Silicon). CI builds natively per-arch so this is a no-op there.
6273
# Stub it so local cross-arch builds still succeed.
@@ -66,12 +77,18 @@ RUN pnpm canvas:a2ui:bundle || \
6677
echo "/* A2UI bundle unavailable in this build */" > src/canvas-host/a2ui/a2ui.bundle.js && \
6778
echo "stub" > src/canvas-host/a2ui/.bundle.hash && \
6879
rm -rf vendor/a2ui apps/shared/OpenClawKit/Tools/CanvasA2UI)
69-
RUN pnpm build
80+
RUN pnpm build:docker
7081

7182
# Force pnpm for UI build (Bun may fail on ARM/Synology architectures)
7283
ENV OPENCLAW_PREFER_PNPM=1
7384
RUN pnpm ui:build
7485

86+
# Prune dev dependencies and strip build-only metadata before copying
87+
# runtime assets into the final image.
88+
FROM build AS runtime-assets
89+
RUN CI=true pnpm prune --prod && \
90+
find dist -type f \( -name '*.d.ts' -o -name '*.d.mts' -o -name '*.d.cts' -o -name '*.map' \) -delete
91+
7592
FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS base-default
7693
ARG OPENCLAW_NODE_BOOKWORM_DIGEST
7794
LABEL org.opencontainers.image.base.name="docker.io/library/node:22-bookworm" \
@@ -100,52 +117,55 @@ WORKDIR /app
100117

101118
# Install system utilities present in bookworm but missing in bookworm-slim.
102119
# On the full bookworm image these are already installed (apt-get is a no-op).
103-
RUN apt-get update && \
120+
RUN --mount=type=cache,id=openclaw-bookworm-apt-cache,target=/var/cache/apt,sharing=locked \
121+
--mount=type=cache,id=openclaw-bookworm-apt-lists,target=/var/lib/apt,sharing=locked \
122+
apt-get update && \
104123
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
105-
procps hostname curl git openssl && \
106-
apt-get clean && \
107-
rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
124+
procps hostname curl git openssl
108125

109126
RUN chown node:node /app
110127

111-
COPY --from=build --chown=node:node /app/dist ./dist
112-
COPY --from=build --chown=node:node /app/node_modules ./node_modules
113-
COPY --from=build --chown=node:node /app/package.json .
114-
COPY --from=build --chown=node:node /app/openclaw.mjs .
115-
COPY --from=build --chown=node:node /app/extensions ./extensions
116-
COPY --from=build --chown=node:node /app/skills ./skills
117-
COPY --from=build --chown=node:node /app/docs ./docs
118-
119-
# Docker live-test runners invoke `pnpm` inside the runtime image.
120-
# Activate the exact pinned package manager now so the container does not
121-
# rely on a first-run network fetch or missing shims under the non-root user.
122-
RUN corepack enable && \
123-
corepack prepare "$(node -p "require('./package.json').packageManager")" --activate
128+
COPY --from=runtime-assets --chown=node:node /app/dist ./dist
129+
COPY --from=runtime-assets --chown=node:node /app/node_modules ./node_modules
130+
COPY --from=runtime-assets --chown=node:node /app/package.json .
131+
COPY --from=runtime-assets --chown=node:node /app/openclaw.mjs .
132+
COPY --from=runtime-assets --chown=node:node /app/extensions ./extensions
133+
COPY --from=runtime-assets --chown=node:node /app/skills ./skills
134+
COPY --from=runtime-assets --chown=node:node /app/docs ./docs
135+
136+
# Keep pnpm available in the runtime image for container-local workflows.
137+
# Use a shared Corepack home so the non-root `node` user does not need a
138+
# first-run network fetch when invoking pnpm.
139+
ENV COREPACK_HOME=/usr/local/share/corepack
140+
RUN install -d -m 0755 "$COREPACK_HOME" && \
141+
corepack enable && \
142+
corepack prepare "$(node -p "require('./package.json').packageManager")" --activate && \
143+
chmod -R a+rX "$COREPACK_HOME"
124144

125145
# Install additional system packages needed by your skills or extensions.
126146
# Example: docker build --build-arg OPENCLAW_DOCKER_APT_PACKAGES="python3 wget" .
127147
ARG OPENCLAW_DOCKER_APT_PACKAGES=""
128-
RUN if [ -n "$OPENCLAW_DOCKER_APT_PACKAGES" ]; then \
148+
RUN --mount=type=cache,id=openclaw-bookworm-apt-cache,target=/var/cache/apt,sharing=locked \
149+
--mount=type=cache,id=openclaw-bookworm-apt-lists,target=/var/lib/apt,sharing=locked \
150+
if [ -n "$OPENCLAW_DOCKER_APT_PACKAGES" ]; then \
129151
apt-get update && \
130-
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends $OPENCLAW_DOCKER_APT_PACKAGES && \
131-
apt-get clean && \
132-
rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*; \
152+
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends $OPENCLAW_DOCKER_APT_PACKAGES; \
133153
fi
134154

135155
# Optionally install Chromium and Xvfb for browser automation.
136156
# Build with: docker build --build-arg OPENCLAW_INSTALL_BROWSER=1 ...
137157
# Adds ~300MB but eliminates the 60-90s Playwright install on every container start.
138158
# Must run after node_modules COPY so playwright-core is available.
139159
ARG OPENCLAW_INSTALL_BROWSER=""
140-
RUN if [ -n "$OPENCLAW_INSTALL_BROWSER" ]; then \
160+
RUN --mount=type=cache,id=openclaw-bookworm-apt-cache,target=/var/cache/apt,sharing=locked \
161+
--mount=type=cache,id=openclaw-bookworm-apt-lists,target=/var/lib/apt,sharing=locked \
162+
if [ -n "$OPENCLAW_INSTALL_BROWSER" ]; then \
141163
apt-get update && \
142164
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends xvfb && \
143165
mkdir -p /home/node/.cache/ms-playwright && \
144166
PLAYWRIGHT_BROWSERS_PATH=/home/node/.cache/ms-playwright \
145167
node /app/node_modules/playwright-core/cli.js install --with-deps chromium && \
146-
chown -R node:node /home/node/.cache/ms-playwright && \
147-
apt-get clean && \
148-
rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*; \
168+
chown -R node:node /home/node/.cache/ms-playwright; \
149169
fi
150170

151171
# Optionally install Docker CLI for sandbox container management.
@@ -154,7 +174,9 @@ RUN if [ -n "$OPENCLAW_INSTALL_BROWSER" ]; then \
154174
# Required for agents.defaults.sandbox to function in Docker deployments.
155175
ARG OPENCLAW_INSTALL_DOCKER_CLI=""
156176
ARG OPENCLAW_DOCKER_GPG_FINGERPRINT="9DC858229FC7DD38854AE2D88D81803C0EBFCD88"
157-
RUN if [ -n "$OPENCLAW_INSTALL_DOCKER_CLI" ]; then \
177+
RUN --mount=type=cache,id=openclaw-bookworm-apt-cache,target=/var/cache/apt,sharing=locked \
178+
--mount=type=cache,id=openclaw-bookworm-apt-lists,target=/var/lib/apt,sharing=locked \
179+
if [ -n "$OPENCLAW_INSTALL_DOCKER_CLI" ]; then \
158180
apt-get update && \
159181
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
160182
ca-certificates curl gnupg && \
@@ -175,20 +197,9 @@ RUN if [ -n "$OPENCLAW_INSTALL_DOCKER_CLI" ]; then \
175197
"$(dpkg --print-architecture)" > /etc/apt/sources.list.d/docker.list && \
176198
apt-get update && \
177199
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
178-
docker-ce-cli docker-compose-plugin && \
179-
apt-get clean && \
180-
rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*; \
200+
docker-ce-cli docker-compose-plugin; \
181201
fi
182202

183-
# Normalize extension paths so plugin safety checks do not reject
184-
# world-writable directories inherited from source file modes.
185-
RUN for dir in /app/extensions /app/.agent /app/.agents; do \
186-
if [ -d "$dir" ]; then \
187-
find "$dir" -type d -exec chmod 755 {} +; \
188-
find "$dir" -type f -exec chmod 644 {} +; \
189-
fi; \
190-
done
191-
192203
# ---- add openclaw command ----
193204
# Keeps the customized CMD shape while following the upstream launcher.
194205
RUN printf '%s\n' \

0 commit comments

Comments
 (0)