fix(docker): repair named-volume state directory ownership

Preserve contributor credit and land the narrowed Docker ownership fix after ProjectClownfish review/follow-up.
This commit is contained in:
Vincent Koc
2026-04-27 04:34:35 -07:00
committed by GitHub
parent e9bce3f81c
commit 727927aae0
3 changed files with 26 additions and 0 deletions

View File

@@ -95,6 +95,7 @@ Docs: https://docs.openclaw.ai
- Plugins/registry: cache repeated installed-index manifest registry fallback rebuilds behind a bounded invalidating cache so cold provider-discovery paths avoid rereading unchanged manifests. Thanks @mcaxtr.
- Plugins/web: reuse manifest records already loaded for bundled web provider candidate discovery when falling back to public artifact provider loading. Thanks @shakkernerd.
- Mattermost: keep direct-message replies top-level by suppressing reply roots for DM delivery while preserving channel and group thread roots, and derive inbound chat kind from the trusted channel lookup instead of the websocket event channel type. Carries forward #60115, #55186, #72305, and #72659; refs #59758, #59981, #59791, and #57565. Thanks @vincentkoc, @jwchmodx, and @hnykda.
- Docker: pre-create `/home/node/.openclaw` with node ownership and private permissions so first-run Docker Compose named volumes no longer fail startup with EACCES. (#48072, #63959; fixes #61279) Thanks @timoxue and @jeanibarz.
- Process/Windows: decode command stdout and stderr from raw bytes with console-codepage awareness, while preserving valid UTF-8 output and multibyte characters split across chunks. Fixes #50519. Thanks @iready, @kevinten10, @zhangyongjie1997, @knightplat-blip, @heiqishi666, and @slepybear.
- Bonjour/Windows: hide the bundled mDNS advertiser's Windows ARP shell probe so Gateway startup no longer flashes command-prompt windows. Fixes #70238. Thanks @alexandre-leng, @PratikRai0101, @infinitypacific, and @tomerpeled.
- Agents/bootstrap: dedupe hook-injected bootstrap context files by workspace-relative path and store normalized resolved paths so duplicate relative and absolute hook paths no longer depend on the process cwd. (#59344; fixes #59319; related #56721, #56725, and #57587) Thanks @koen666.

View File

@@ -253,6 +253,11 @@ 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 /app/openclaw.mjs
# Pre-create the default state dir so first-run Docker named volumes mounted
# here inherit node ownership instead of starting as root-owned state.
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
# Security hardening: Run as non-root user

View File

@@ -117,4 +117,24 @@ describe("Dockerfile", () => {
'corepack prepare "$(node -p "require(\'./package.json\').packageManager")" --activate',
);
});
it("pre-creates the OpenClaw home before switching to the node user", async () => {
const dockerfile = await readFile(dockerfilePath, "utf8");
const runtimeStageIndex = dockerfile.lastIndexOf("FROM base-runtime");
const stateDirIndex = dockerfile.indexOf(
"RUN install -d -m 0700 -o node -g node /home/node/.openclaw && \\",
runtimeStageIndex,
);
const userIndex = dockerfile.indexOf("USER node", runtimeStageIndex);
expect(runtimeStageIndex).toBeGreaterThan(-1);
expect(stateDirIndex).toBeGreaterThan(-1);
expect(userIndex).toBeGreaterThan(-1);
expect(stateDirIndex).toBeGreaterThan(runtimeStageIndex);
expect(stateDirIndex).toBeLessThan(userIndex);
expect(dockerfile).not.toContain("mkdir -p /home/node/.openclaw");
expect(dockerfile).toContain(
"stat -c '%U:%G %a' /home/node/.openclaw | grep -qx 'node:node 700'",
);
});
});