diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b257f2fbe8..ff1f1cdcd67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Docs: https://docs.openclaw.ai ### Changes +- Docker: run the runtime image under `tini` so long-lived containers reap orphaned child processes and forward signals correctly. (#77885) Thanks @VintageAyu. - Google/Gemini: normalize retired `google/gemini-3-pro-preview` and `google-gemini-cli/gemini-3-pro-preview` selections to `google/gemini-3.1-pro-preview` before they are written to model config. - Amazon Bedrock: support `serviceTier` parameter for Bedrock models, configurable via `agents.defaults.params.serviceTier` or per-model in `agents.defaults.models`. Valid values: `default`, `flex`, `priority`, `reserved`. (#64512) Thanks @mobilinkd. - Control UI: read the Quick Settings exec policy badge from `tools.exec.security` instead of the non-schema `agents.defaults.exec.security` path, so configured `full`/`deny` values render accurately. Fixes #78311. Thanks @FriedBack. diff --git a/Dockerfile b/Dockerfile index 3e9213bb882..cc411a8a2f2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -160,7 +160,7 @@ RUN --mount=type=cache,id=openclaw-bookworm-apt-cache,target=/var/cache/apt,shar --mount=type=cache,id=openclaw-bookworm-apt-lists,target=/var/lib/apt,sharing=locked \ apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ - ca-certificates procps hostname curl git lsof openssl python3 && \ + ca-certificates procps hostname curl git lsof openssl python3 tini && \ update-ca-certificates RUN chown node:node /app @@ -287,4 +287,5 @@ USER node # For external access from host/ingress, override bind to "lan" and set auth. 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))" +ENTRYPOINT ["tini", "-s", "--"] CMD ["node", "openclaw.mjs", "gateway", "--allow-unconfigured"] diff --git a/docs/install/docker.md b/docs/install/docker.md index 6862f845565..0bd131ad5d8 100644 --- a/docs/install/docker.md +++ b/docs/install/docker.md @@ -427,8 +427,7 @@ See [ClawDock](/install/clawdock) for the full helper guide. - The main Docker runtime image uses `node:24-bookworm-slim` and publishes OCI - base-image annotations including `org.opencontainers.image.base.name`, + The main Docker runtime image uses `node:24-bookworm-slim` and includes `tini` as the entrypoint init process (PID 1) to ensure zombie processes are reaped and signals are handled correctly in long-running containers. It publishes OCI base-image annotations including `org.opencontainers.image.base.name`, `org.opencontainers.image.source`, and others. The Node base digest is refreshed through Dependabot Docker base-image PRs; release builds do not run a distro upgrade layer. See diff --git a/docs/install/fly.md b/docs/install/fly.md index 4dfa083d74d..b88e810a785 100644 --- a/docs/install/fly.md +++ b/docs/install/fly.md @@ -78,6 +78,8 @@ read_when: destination = "/data" ``` + The OpenClaw Docker image uses `tini` as its entrypoint. Fly process commands replace Docker `CMD` without replacing `ENTRYPOINT`, so the process still runs under `tini`. + **Key settings:** | Setting | Why | diff --git a/src/dockerfile.test.ts b/src/dockerfile.test.ts index ef7e2d35f88..2ef7dfa5a5a 100644 --- a/src/dockerfile.test.ts +++ b/src/dockerfile.test.ts @@ -47,7 +47,7 @@ describe("Dockerfile", () => { expect(collapsed).toContain("update-ca-certificates"); }); - it("installs python3 in the slim runtime stage for workspace scripts", async () => { + it("installs python3 and tini in the slim runtime stage", async () => { const dockerfile = collapseDockerContinuations(await readFile(dockerfilePath, "utf8")); const runtimeIndex = dockerfile.indexOf( "FROM ${OPENCLAW_NODE_BOOKWORM_SLIM_IMAGE} AS base-runtime", @@ -59,7 +59,10 @@ describe("Dockerfile", () => { expect(runtimeIndex).toBeGreaterThan(-1); expect(pythonInstallIndex).toBeGreaterThan(runtimeIndex); expect(pythonInstallIndex).toBeLessThan(dockerfile.indexOf("RUN chown node:node /app")); - expect(dockerfile).toContain("ca-certificates procps hostname curl git lsof openssl python3"); + expect(dockerfile).toContain( + "ca-certificates procps hostname curl git lsof openssl python3 tini", + ); + expect(dockerfile).toContain('ENTRYPOINT ["tini", "-s", "--"]'); }); it("installs optional browser dependencies after pnpm install", async () => {