mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-21 10:16:44 +00:00
fix(docker): pin setup cli container paths
This commit is contained in:
committed by
Peter Steinberger
parent
70df2b8fe2
commit
3cf296185f
+8
-2
@@ -7,13 +7,16 @@ services:
|
||||
required: false
|
||||
environment:
|
||||
HOME: /home/node
|
||||
OPENCLAW_HOME: /home/node
|
||||
TERM: xterm-256color
|
||||
# Pin container-side workspace and config paths so host values written to
|
||||
# Pin container-side state, workspace, and config paths so host values written to
|
||||
# `.env` (used by Compose for the bind-mount source below) cannot leak
|
||||
# into runtime code that resolves these env vars inside the container.
|
||||
# Without this override, a macOS host path like /Users/<you>/.openclaw/...
|
||||
# imported from .env caused first-reply `mkdir '/Users'` EACCES failures
|
||||
# in Linux Docker (#77436).
|
||||
OPENCLAW_STATE_DIR: /home/node/.openclaw
|
||||
OPENCLAW_CONFIG_PATH: /home/node/.openclaw/openclaw.json
|
||||
OPENCLAW_CONFIG_DIR: /home/node/.openclaw
|
||||
OPENCLAW_WORKSPACE_DIR: /home/node/.openclaw/workspace
|
||||
OPENCLAW_GATEWAY_TOKEN: ${OPENCLAW_GATEWAY_TOKEN:-}
|
||||
@@ -98,9 +101,12 @@ services:
|
||||
- no-new-privileges:true
|
||||
environment:
|
||||
HOME: /home/node
|
||||
OPENCLAW_HOME: /home/node
|
||||
TERM: xterm-256color
|
||||
# Pin container-side workspace and config paths so host values written to
|
||||
# Pin container-side state, workspace, and config paths so host values written to
|
||||
# `.env` cannot leak into runtime code via the env_file import (#77436).
|
||||
OPENCLAW_STATE_DIR: /home/node/.openclaw
|
||||
OPENCLAW_CONFIG_PATH: /home/node/.openclaw/openclaw.json
|
||||
OPENCLAW_CONFIG_DIR: /home/node/.openclaw
|
||||
OPENCLAW_WORKSPACE_DIR: /home/node/.openclaw/workspace
|
||||
OPENCLAW_GATEWAY_TOKEN: ${OPENCLAW_GATEWAY_TOKEN:-}
|
||||
|
||||
+10
-1
@@ -149,7 +149,16 @@ run_prestart_cli() {
|
||||
# requires the gateway container's network namespace to already exist. That
|
||||
# creates a circular dependency for config writes that are needed before the
|
||||
# gateway can start cleanly.
|
||||
run_prestart_gateway --entrypoint node openclaw-gateway \
|
||||
# Host OPENCLAW_* paths are Compose bind-mount sources. Setup-time CLI writes
|
||||
# must still resolve state/config paths inside the container.
|
||||
run_prestart_gateway \
|
||||
-e HOME=/home/node \
|
||||
-e OPENCLAW_HOME=/home/node \
|
||||
-e OPENCLAW_STATE_DIR=/home/node/.openclaw \
|
||||
-e OPENCLAW_CONFIG_PATH=/home/node/.openclaw/openclaw.json \
|
||||
-e OPENCLAW_CONFIG_DIR=/home/node/.openclaw \
|
||||
-e OPENCLAW_WORKSPACE_DIR=/home/node/.openclaw/workspace \
|
||||
--entrypoint node openclaw-gateway \
|
||||
dist/index.js "$@"
|
||||
}
|
||||
|
||||
|
||||
@@ -90,6 +90,15 @@ async function createDockerSetupSandbox(): Promise<DockerSetupSandbox> {
|
||||
|
||||
const sandboxRootTracker = createSuiteTempRootTracker({ prefix: "openclaw-docker-setup-" });
|
||||
|
||||
const prestartContainerEnvFlags = [
|
||||
"-e HOME=/home/node",
|
||||
"-e OPENCLAW_HOME=/home/node",
|
||||
"-e OPENCLAW_STATE_DIR=/home/node/.openclaw",
|
||||
"-e OPENCLAW_CONFIG_PATH=/home/node/.openclaw/openclaw.json",
|
||||
"-e OPENCLAW_CONFIG_DIR=/home/node/.openclaw",
|
||||
"-e OPENCLAW_WORKSPACE_DIR=/home/node/.openclaw/workspace",
|
||||
].join(" ");
|
||||
|
||||
function createEnv(
|
||||
sandbox: DockerSetupSandbox,
|
||||
overrides: Record<string, string | undefined> = {},
|
||||
@@ -275,10 +284,10 @@ describe("scripts/docker/setup.sh", () => {
|
||||
const log = await readDockerLog(activeSandbox);
|
||||
expect(log).toContain("--build-arg OPENCLAW_DOCKER_APT_PACKAGES=ffmpeg build-essential");
|
||||
expect(log).toContain(
|
||||
"run --rm --no-deps --entrypoint node openclaw-gateway dist/index.js onboard --mode local --no-install-daemon",
|
||||
`run --rm --no-deps ${prestartContainerEnvFlags} --entrypoint node openclaw-gateway dist/index.js onboard --mode local --no-install-daemon`,
|
||||
);
|
||||
expect(log).toContain(
|
||||
'run --rm --no-deps --entrypoint node openclaw-gateway dist/index.js config set --batch-json [{"path":"gateway.mode","value":"local"},{"path":"gateway.bind","value":"lan"},{"path":"gateway.controlUi.allowedOrigins","value":["http://localhost:18789","http://127.0.0.1:18789"]}]',
|
||||
`run --rm --no-deps ${prestartContainerEnvFlags} --entrypoint node openclaw-gateway dist/index.js config set --batch-json [{"path":"gateway.mode","value":"local"},{"path":"gateway.bind","value":"lan"},{"path":"gateway.controlUi.allowedOrigins","value":["http://localhost:18789","http://127.0.0.1:18789"]}]`,
|
||||
);
|
||||
expect(log).not.toContain("run --rm openclaw-cli onboard --mode local --no-install-daemon");
|
||||
});
|
||||
@@ -313,6 +322,32 @@ describe("scripts/docker/setup.sh", () => {
|
||||
expect(prestartCliRunLines).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it("pins setup-time CLI state paths inside the container", async () => {
|
||||
const activeSandbox = requireSandbox(sandbox);
|
||||
|
||||
await resetDockerLog(activeSandbox);
|
||||
const result = runDockerSetup(activeSandbox, {
|
||||
OPENCLAW_HOME: "/mnt/c/Users/Trevor",
|
||||
OPENCLAW_STATE_DIR: "/mnt/c/Users/Trevor/.openclaw",
|
||||
OPENCLAW_CONFIG_PATH: "/mnt/c/Users/Trevor/.openclaw/openclaw.json",
|
||||
OPENCLAW_SKIP_ONBOARDING: "1",
|
||||
});
|
||||
expect(result.status).toBe(0);
|
||||
|
||||
const lines = await readDockerLogLines(activeSandbox);
|
||||
const gatewayStartIdx = findGatewayStartLineIndex(lines);
|
||||
expect(gatewayStartIdx).toBeGreaterThanOrEqual(0);
|
||||
|
||||
const prestartConfigLines = collectMatchingLines(lines.slice(0, gatewayStartIdx), (line) =>
|
||||
line.includes(" dist/index.js config "),
|
||||
);
|
||||
expect(prestartConfigLines.length).toBeGreaterThan(0);
|
||||
for (const line of prestartConfigLines) {
|
||||
expect(line).toContain(prestartContainerEnvFlags);
|
||||
expect(line).not.toContain("/mnt/c");
|
||||
}
|
||||
});
|
||||
|
||||
it("forces BuildKit for local and sandbox docker builds", async () => {
|
||||
const activeSandbox = requireSandbox(sandbox);
|
||||
await mkdir(join(activeSandbox.rootDir, "scripts", "docker", "sandbox"), { recursive: true });
|
||||
@@ -692,12 +727,16 @@ describe("scripts/docker/setup.sh", () => {
|
||||
expect(compose.match(/TZ: \$\{OPENCLAW_TZ:-UTC\}/g)).toHaveLength(2);
|
||||
});
|
||||
|
||||
it("pins container-side workspace and config dirs on both services so host .env paths cannot leak (#77436)", async () => {
|
||||
it("pins container-side state, workspace, and config dirs on both services so host .env paths cannot leak (#77436)", async () => {
|
||||
const compose = await readFile(join(repoRoot, "docker-compose.yml"), "utf8");
|
||||
// Both gateway and CLI services must override the env_file values with the
|
||||
// canonical container paths so a host-style OPENCLAW_WORKSPACE_DIR like
|
||||
// `/Users/<you>/.openclaw/workspace` written to `.env` by docker-setup.sh
|
||||
// cannot reach runtime code inside Linux Docker.
|
||||
// Both gateway and CLI services must override env_file values with the
|
||||
// canonical container paths so host-style paths written to `.env` cannot
|
||||
// reach runtime code inside Linux Docker.
|
||||
expect(compose.match(/OPENCLAW_HOME: \/home\/node$/gm)).toHaveLength(2);
|
||||
expect(compose.match(/OPENCLAW_STATE_DIR: \/home\/node\/\.openclaw$/gm)).toHaveLength(2);
|
||||
expect(
|
||||
compose.match(/OPENCLAW_CONFIG_PATH: \/home\/node\/\.openclaw\/openclaw\.json$/gm),
|
||||
).toHaveLength(2);
|
||||
expect(compose.match(/OPENCLAW_CONFIG_DIR: \/home\/node\/\.openclaw$/gm)).toHaveLength(2);
|
||||
expect(
|
||||
compose.match(/OPENCLAW_WORKSPACE_DIR: \/home\/node\/\.openclaw\/workspace$/gm),
|
||||
|
||||
Reference in New Issue
Block a user