mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 12:00:44 +00:00
build: use slim docker runtime
This commit is contained in:
83
.github/workflows/docker-release.yml
vendored
83
.github/workflows/docker-release.yml
vendored
@@ -63,7 +63,7 @@ jobs:
|
|||||||
|
|
||||||
# KEEP THIS WORKFLOW ON GITHUB-HOSTED RUNNERS.
|
# KEEP THIS WORKFLOW ON GITHUB-HOSTED RUNNERS.
|
||||||
# DO NOT MOVE IT BACK TO BLACKSMITH WITHOUT RE-VALIDATING TAG BUILDS AND BACKFILLS.
|
# DO NOT MOVE IT BACK TO BLACKSMITH WITHOUT RE-VALIDATING TAG BUILDS AND BACKFILLS.
|
||||||
# Build amd64 images (default + slim share the build stage cache)
|
# Build amd64 image. Default and slim tags point to the same slim runtime.
|
||||||
build-amd64:
|
build-amd64:
|
||||||
needs: [approve_manual_backfill]
|
needs: [approve_manual_backfill]
|
||||||
if: ${{ always() && (github.event_name != 'workflow_dispatch' || needs.approve_manual_backfill.result == 'success') }}
|
if: ${{ always() && (github.event_name != 'workflow_dispatch' || needs.approve_manual_backfill.result == 'success') }}
|
||||||
@@ -74,7 +74,6 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
outputs:
|
outputs:
|
||||||
digest: ${{ steps.build.outputs.digest }}
|
digest: ${{ steps.build.outputs.digest }}
|
||||||
slim-digest: ${{ steps.build-slim.outputs.digest }}
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v6
|
||||||
@@ -117,12 +116,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
{
|
{
|
||||||
echo "value<<EOF"
|
echo "value<<EOF"
|
||||||
printf "%s\n" "${tags[@]}"
|
printf "%s\n" "${tags[@]}" "${slim_tags[@]}"
|
||||||
echo "EOF"
|
|
||||||
} >> "$GITHUB_OUTPUT"
|
|
||||||
{
|
|
||||||
echo "slim<<EOF"
|
|
||||||
printf "%s\n" "${slim_tags[@]}"
|
|
||||||
echo "EOF"
|
echo "EOF"
|
||||||
} >> "$GITHUB_OUTPUT"
|
} >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
@@ -167,25 +161,7 @@ jobs:
|
|||||||
provenance: mode=max
|
provenance: mode=max
|
||||||
push: true
|
push: true
|
||||||
|
|
||||||
- name: Build and push amd64 slim image
|
# Build arm64 image. Default and slim tags point to the same slim runtime.
|
||||||
id: build-slim
|
|
||||||
# WARNING: KEEP THE OFFICIAL DOCKER ACTION HERE; DO NOT SWITCH THIS BACK TO BLACKSMITH BLINDLY.
|
|
||||||
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
platforms: linux/amd64
|
|
||||||
cache-from: type=gha,scope=docker-release-amd64
|
|
||||||
cache-to: type=gha,mode=max,scope=docker-release-amd64
|
|
||||||
build-args: |
|
|
||||||
OPENCLAW_EXTENSIONS=diagnostics-otel
|
|
||||||
OPENCLAW_VARIANT=slim
|
|
||||||
tags: ${{ steps.tags.outputs.slim }}
|
|
||||||
labels: ${{ steps.labels.outputs.value }}
|
|
||||||
sbom: true
|
|
||||||
provenance: mode=max
|
|
||||||
push: true
|
|
||||||
|
|
||||||
# Build arm64 images (default + slim share the build stage cache)
|
|
||||||
build-arm64:
|
build-arm64:
|
||||||
needs: [approve_manual_backfill]
|
needs: [approve_manual_backfill]
|
||||||
if: ${{ always() && (github.event_name != 'workflow_dispatch' || needs.approve_manual_backfill.result == 'success') }}
|
if: ${{ always() && (github.event_name != 'workflow_dispatch' || needs.approve_manual_backfill.result == 'success') }}
|
||||||
@@ -196,7 +172,6 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
outputs:
|
outputs:
|
||||||
digest: ${{ steps.build.outputs.digest }}
|
digest: ${{ steps.build.outputs.digest }}
|
||||||
slim-digest: ${{ steps.build-slim.outputs.digest }}
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v6
|
||||||
@@ -239,12 +214,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
{
|
{
|
||||||
echo "value<<EOF"
|
echo "value<<EOF"
|
||||||
printf "%s\n" "${tags[@]}"
|
printf "%s\n" "${tags[@]}" "${slim_tags[@]}"
|
||||||
echo "EOF"
|
|
||||||
} >> "$GITHUB_OUTPUT"
|
|
||||||
{
|
|
||||||
echo "slim<<EOF"
|
|
||||||
printf "%s\n" "${slim_tags[@]}"
|
|
||||||
echo "EOF"
|
echo "EOF"
|
||||||
} >> "$GITHUB_OUTPUT"
|
} >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
@@ -289,24 +259,6 @@ jobs:
|
|||||||
provenance: mode=max
|
provenance: mode=max
|
||||||
push: true
|
push: true
|
||||||
|
|
||||||
- name: Build and push arm64 slim image
|
|
||||||
id: build-slim
|
|
||||||
# WARNING: KEEP THE OFFICIAL DOCKER ACTION HERE; DO NOT SWITCH THIS BACK TO BLACKSMITH BLINDLY.
|
|
||||||
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
platforms: linux/arm64
|
|
||||||
cache-from: type=gha,scope=docker-release-arm64
|
|
||||||
cache-to: type=gha,mode=max,scope=docker-release-arm64
|
|
||||||
build-args: |
|
|
||||||
OPENCLAW_EXTENSIONS=diagnostics-otel
|
|
||||||
OPENCLAW_VARIANT=slim
|
|
||||||
tags: ${{ steps.tags.outputs.slim }}
|
|
||||||
labels: ${{ steps.labels.outputs.value }}
|
|
||||||
sbom: true
|
|
||||||
provenance: mode=max
|
|
||||||
push: true
|
|
||||||
|
|
||||||
# Create multi-platform manifests
|
# Create multi-platform manifests
|
||||||
create-manifest:
|
create-manifest:
|
||||||
needs: [approve_manual_backfill, build-amd64, build-arm64]
|
needs: [approve_manual_backfill, build-amd64, build-arm64]
|
||||||
@@ -361,16 +313,11 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
{
|
{
|
||||||
echo "value<<EOF"
|
echo "value<<EOF"
|
||||||
printf "%s\n" "${tags[@]}"
|
printf "%s\n" "${tags[@]}" "${slim_tags[@]}"
|
||||||
echo "EOF"
|
|
||||||
} >> "$GITHUB_OUTPUT"
|
|
||||||
{
|
|
||||||
echo "slim<<EOF"
|
|
||||||
printf "%s\n" "${slim_tags[@]}"
|
|
||||||
echo "EOF"
|
echo "EOF"
|
||||||
} >> "$GITHUB_OUTPUT"
|
} >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Create and push default manifest
|
- name: Create and push manifest
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
TAGS: ${{ steps.tags.outputs.value }}
|
TAGS: ${{ steps.tags.outputs.value }}
|
||||||
@@ -388,24 +335,6 @@ jobs:
|
|||||||
"${AMD64_DIGEST}" \
|
"${AMD64_DIGEST}" \
|
||||||
"${ARM64_DIGEST}"
|
"${ARM64_DIGEST}"
|
||||||
|
|
||||||
- name: Create and push slim manifest
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
SLIM_TAGS: ${{ steps.tags.outputs.slim }}
|
|
||||||
AMD64_SLIM_DIGEST: ${{ needs.build-amd64.outputs.slim-digest }}
|
|
||||||
ARM64_SLIM_DIGEST: ${{ needs.build-arm64.outputs.slim-digest }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
mapfile -t tags <<< "${SLIM_TAGS}"
|
|
||||||
args=()
|
|
||||||
for tag in "${tags[@]}"; do
|
|
||||||
[ -z "$tag" ] && continue
|
|
||||||
args+=("-t" "$tag")
|
|
||||||
done
|
|
||||||
docker buildx imagetools create "${args[@]}" \
|
|
||||||
"${AMD64_SLIM_DIGEST}" \
|
|
||||||
"${ARM64_SLIM_DIGEST}"
|
|
||||||
|
|
||||||
verify-attestations:
|
verify-attestations:
|
||||||
needs: [create-manifest]
|
needs: [create-manifest]
|
||||||
if: ${{ always() && needs.create-manifest.result == 'success' }}
|
if: ${{ always() && needs.create-manifest.result == 'success' }}
|
||||||
|
|||||||
26
Dockerfile
26
Dockerfile
@@ -9,22 +9,19 @@
|
|||||||
# bundled plugin workspace tree, so the main build layer is not invalidated by
|
# bundled plugin workspace tree, so the main build layer is not invalidated by
|
||||||
# unrelated plugin source changes.
|
# unrelated plugin source changes.
|
||||||
#
|
#
|
||||||
# Two runtime variants:
|
# Build stages use full bookworm; the runtime image is always bookworm-slim.
|
||||||
# Default (bookworm): docker build .
|
|
||||||
# Slim (bookworm-slim): docker build --build-arg OPENCLAW_VARIANT=slim .
|
|
||||||
ARG OPENCLAW_EXTENSIONS=""
|
ARG OPENCLAW_EXTENSIONS=""
|
||||||
ARG OPENCLAW_VARIANT=default
|
|
||||||
ARG OPENCLAW_BUNDLED_PLUGIN_DIR=extensions
|
ARG OPENCLAW_BUNDLED_PLUGIN_DIR=extensions
|
||||||
ARG OPENCLAW_NODE_BOOKWORM_IMAGE="node:24-bookworm@sha256:3a09aa6354567619221ef6c45a5051b671f953f0a1924d1f819ffb236e520e6b"
|
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_IMAGE="node:24-bookworm-slim@sha256:e8e2e91b1378f83c5b2dd15f0247f34110e2fe895f6ca7719dbb780f929368eb"
|
||||||
ARG OPENCLAW_NODE_BOOKWORM_SLIM_DIGEST="sha256:e8e2e91b1378f83c5b2dd15f0247f34110e2fe895f6ca7719dbb780f929368eb"
|
ARG OPENCLAW_NODE_BOOKWORM_SLIM_DIGEST="sha256:e8e2e91b1378f83c5b2dd15f0247f34110e2fe895f6ca7719dbb780f929368eb"
|
||||||
|
|
||||||
# Base images are pinned to SHA256 digests for reproducible builds.
|
# Base images are pinned to SHA256 digests for reproducible builds.
|
||||||
# Dependabot refreshes these blessed digests; release builds consume the
|
# Dependabot refreshes these blessed digests; release builds consume the
|
||||||
# reviewed base snapshot instead of mutating distro state on every build.
|
# reviewed base snapshot instead of mutating distro state on every build.
|
||||||
# To update, run: docker buildx imagetools inspect node:24-bookworm (or podman)
|
# To update, run: docker buildx imagetools inspect node:24-bookworm and
|
||||||
# and replace the digest below with the current multi-arch manifest list entry.
|
# 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
|
FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS ext-deps
|
||||||
ARG OPENCLAW_EXTENSIONS
|
ARG OPENCLAW_EXTENSIONS
|
||||||
@@ -125,20 +122,14 @@ RUN printf 'packages:\n - .\n - ui\n' > /tmp/pnpm-workspace.runtime.yaml && \
|
|||||||
node scripts/postinstall-bundled-plugins.mjs && \
|
node scripts/postinstall-bundled-plugins.mjs && \
|
||||||
find dist -type f \( -name '*.d.ts' -o -name '*.d.mts' -o -name '*.d.cts' -o -name '*.map' \) -delete
|
find dist -type f \( -name '*.d.ts' -o -name '*.d.mts' -o -name '*.d.cts' -o -name '*.map' \) -delete
|
||||||
|
|
||||||
# ── Runtime base images ─────────────────────────────────────────
|
# ── Runtime base image ──────────────────────────────────────────
|
||||||
FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS base-default
|
FROM ${OPENCLAW_NODE_BOOKWORM_SLIM_IMAGE} AS base-runtime
|
||||||
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
|
ARG OPENCLAW_NODE_BOOKWORM_SLIM_DIGEST
|
||||||
LABEL org.opencontainers.image.base.name="docker.io/library/node:24-bookworm-slim" \
|
LABEL org.opencontainers.image.base.name="docker.io/library/node:24-bookworm-slim" \
|
||||||
org.opencontainers.image.base.digest="${OPENCLAW_NODE_BOOKWORM_SLIM_DIGEST}"
|
org.opencontainers.image.base.digest="${OPENCLAW_NODE_BOOKWORM_SLIM_DIGEST}"
|
||||||
|
|
||||||
# ── Stage 3: Runtime ────────────────────────────────────────────
|
# ── Stage 3: Runtime ────────────────────────────────────────────
|
||||||
FROM base-${OPENCLAW_VARIANT}
|
FROM base-runtime
|
||||||
ARG OPENCLAW_VARIANT
|
|
||||||
ARG OPENCLAW_BUNDLED_PLUGIN_DIR
|
ARG OPENCLAW_BUNDLED_PLUGIN_DIR
|
||||||
|
|
||||||
# OCI base-image metadata for downstream image consumers.
|
# OCI base-image metadata for downstream image consumers.
|
||||||
@@ -154,8 +145,7 @@ LABEL org.opencontainers.image.source="https://github.com/openclaw/openclaw" \
|
|||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Install system utilities present in bookworm but missing in bookworm-slim.
|
# Install runtime system utilities missing from bookworm-slim.
|
||||||
# On the full bookworm image these are already installed (apt-get is a no-op).
|
|
||||||
RUN --mount=type=cache,id=openclaw-bookworm-apt-cache,target=/var/cache/apt,sharing=locked \
|
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 \
|
--mount=type=cache,id=openclaw-bookworm-apt-lists,target=/var/lib/apt,sharing=locked \
|
||||||
apt-get update && \
|
apt-get update && \
|
||||||
|
|||||||
@@ -357,8 +357,8 @@ See [ClawDock](/install/clawdock) for the full helper guide.
|
|||||||
</Accordion>
|
</Accordion>
|
||||||
|
|
||||||
<Accordion title="Base image metadata">
|
<Accordion title="Base image metadata">
|
||||||
The main Docker image uses `node:24-bookworm` and publishes OCI base-image
|
The main Docker runtime image uses `node:24-bookworm-slim` and publishes OCI
|
||||||
annotations including `org.opencontainers.image.base.name`,
|
base-image annotations including `org.opencontainers.image.base.name`,
|
||||||
`org.opencontainers.image.source`, and others. The Node base digest is
|
`org.opencontainers.image.source`, and others. The Node base digest is
|
||||||
refreshed through Dependabot Docker base-image PRs; release builds do not run
|
refreshed through Dependabot Docker base-image PRs; release builds do not run
|
||||||
a distro upgrade layer. See
|
a distro upgrade layer. See
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# syntax=docker/dockerfile:1.7
|
# syntax=docker/dockerfile:1.7
|
||||||
|
|
||||||
FROM node:24-bookworm@sha256:3a09aa6354567619221ef6c45a5051b671f953f0a1924d1f819ffb236e520e6b AS e2e-runner
|
FROM node:24-bookworm-slim@sha256:e8e2e91b1378f83c5b2dd15f0247f34110e2fe895f6ca7719dbb780f929368eb AS e2e-runner
|
||||||
|
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y --no-install-recommends ca-certificates git \
|
&& apt-get install -y --no-install-recommends ca-certificates git \
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# syntax=docker/dockerfile:1.7
|
# syntax=docker/dockerfile:1.7
|
||||||
|
|
||||||
FROM node:24-bookworm@sha256:3a09aa6354567619221ef6c45a5051b671f953f0a1924d1f819ffb236e520e6b
|
FROM node:24-bookworm-slim@sha256:e8e2e91b1378f83c5b2dd15f0247f34110e2fe895f6ca7719dbb780f929368eb
|
||||||
|
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ function collapseDockerContinuations(dockerfile: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe("Dockerfile", () => {
|
describe("Dockerfile", () => {
|
||||||
it("uses shared multi-arch base image refs for all root Node stages", async () => {
|
it("uses full bookworm for build stages and slim bookworm for runtime", async () => {
|
||||||
const dockerfile = await readFile(dockerfilePath, "utf8");
|
const dockerfile = await readFile(dockerfilePath, "utf8");
|
||||||
expect(dockerfile).toContain(
|
expect(dockerfile).toContain(
|
||||||
'ARG OPENCLAW_NODE_BOOKWORM_IMAGE="node:24-bookworm@sha256:3a09aa6354567619221ef6c45a5051b671f953f0a1924d1f819ffb236e520e6b"',
|
'ARG OPENCLAW_NODE_BOOKWORM_IMAGE="node:24-bookworm@sha256:3a09aa6354567619221ef6c45a5051b671f953f0a1924d1f819ffb236e520e6b"',
|
||||||
@@ -23,10 +23,11 @@ describe("Dockerfile", () => {
|
|||||||
);
|
);
|
||||||
expect(dockerfile).toContain("FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS ext-deps");
|
expect(dockerfile).toContain("FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS ext-deps");
|
||||||
expect(dockerfile).toContain("FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS build");
|
expect(dockerfile).toContain("FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS build");
|
||||||
expect(dockerfile).toContain("FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS base-default");
|
expect(dockerfile).toContain("FROM ${OPENCLAW_NODE_BOOKWORM_SLIM_IMAGE} AS base-runtime");
|
||||||
expect(dockerfile).toContain("FROM ${OPENCLAW_NODE_BOOKWORM_SLIM_IMAGE} AS base-slim");
|
expect(dockerfile).toContain("FROM base-runtime");
|
||||||
expect(dockerfile).toContain("current multi-arch manifest list entry");
|
expect(dockerfile).toContain("current multi-arch manifest list entries");
|
||||||
expect(dockerfile).not.toContain("current amd64 entry");
|
expect(dockerfile).not.toContain("current amd64 entry");
|
||||||
|
expect(dockerfile).not.toContain("OPENCLAW_VARIANT");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("installs optional browser dependencies after pnpm install", async () => {
|
it("installs optional browser dependencies after pnpm install", async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user