Docker: avoid setup CLI namespace loop

This commit is contained in:
김채완
2026-03-24 13:26:01 +09:00
committed by Peter Steinberger
parent 6f6468027a
commit dbb806d257
2 changed files with 48 additions and 13 deletions

View File

@@ -108,8 +108,7 @@ ensure_control_ui_allowed_origins() {
local current_allowed_origins
allowed_origin_json="$(printf '["http://127.0.0.1:%s"]' "$OPENCLAW_GATEWAY_PORT")"
current_allowed_origins="$(
docker compose "${COMPOSE_ARGS[@]}" run --rm openclaw-cli \
config get gateway.controlUi.allowedOrigins 2>/dev/null || true
run_setup_cli config get gateway.controlUi.allowedOrigins 2>/dev/null || true
)"
current_allowed_origins="${current_allowed_origins//$'\r'/}"
@@ -118,19 +117,26 @@ ensure_control_ui_allowed_origins() {
return 0
fi
docker compose "${COMPOSE_ARGS[@]}" run --rm openclaw-cli \
config set gateway.controlUi.allowedOrigins "$allowed_origin_json" --strict-json >/dev/null
run_setup_cli config set gateway.controlUi.allowedOrigins "$allowed_origin_json" --strict-json \
>/dev/null
echo "Set gateway.controlUi.allowedOrigins to $allowed_origin_json for non-loopback bind."
}
sync_gateway_mode_and_bind() {
docker compose "${COMPOSE_ARGS[@]}" run --rm openclaw-cli \
config set gateway.mode local >/dev/null
docker compose "${COMPOSE_ARGS[@]}" run --rm openclaw-cli \
config set gateway.bind "$OPENCLAW_GATEWAY_BIND" >/dev/null
run_setup_cli config set gateway.mode local >/dev/null
run_setup_cli config set gateway.bind "$OPENCLAW_GATEWAY_BIND" >/dev/null
echo "Pinned gateway.mode=local and gateway.bind=$OPENCLAW_GATEWAY_BIND for Docker setup."
}
run_setup_cli() {
# During setup, avoid the shared-network openclaw-cli service because it
# 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.
docker compose "${COMPOSE_ARGS[@]}" run --rm --no-deps --entrypoint node openclaw-gateway \
dist/index.js "$@"
}
contains_disallowed_chars() {
local value="$1"
[[ "$value" == *$'\n'* || "$value" == *$'\r'* || "$value" == *$'\t'* ]]
@@ -458,7 +464,7 @@ echo "==> Fixing data-directory permissions"
# ownership of all user project files on Linux hosts.
# After fixing the config dir, only the OpenClaw metadata subdirectory
# (.openclaw/) inside the workspace gets chowned, not the user's project files.
docker compose "${COMPOSE_ARGS[@]}" run --rm --user root --entrypoint sh openclaw-cli -c \
docker compose "${COMPOSE_ARGS[@]}" run --rm --no-deps --user root --entrypoint sh openclaw-gateway -c \
'find /home/node/.openclaw -xdev -exec chown node:node {} +; \
[ -d /home/node/.openclaw/workspace/.openclaw ] && chown -R node:node /home/node/.openclaw/workspace/.openclaw || true'
@@ -471,7 +477,7 @@ echo "Gateway token: $OPENCLAW_GATEWAY_TOKEN"
echo "Tailscale exposure: Off (use host-level tailnet/Tailscale setup separately)."
echo "Install Gateway daemon: No (managed by Docker Compose)"
echo ""
docker compose "${COMPOSE_ARGS[@]}" run --rm openclaw-cli onboard --mode local --no-install-daemon
run_setup_cli onboard --mode local --no-install-daemon
echo ""
echo "==> Docker gateway defaults"

View File

@@ -206,9 +206,37 @@ describe("scripts/docker/setup.sh", () => {
expect(extraCompose).toContain("openclaw-home:");
const log = await readFile(activeSandbox.logPath, "utf8");
expect(log).toContain("--build-arg OPENCLAW_DOCKER_APT_PACKAGES=ffmpeg build-essential");
expect(log).toContain("run --rm openclaw-cli onboard --mode local --no-install-daemon");
expect(log).toContain("run --rm openclaw-cli config set gateway.mode local");
expect(log).toContain("run --rm openclaw-cli config set gateway.bind lan");
expect(log).toContain(
"run --rm --no-deps --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 gateway.mode local",
);
expect(log).toContain(
"run --rm --no-deps --entrypoint node openclaw-gateway dist/index.js config set gateway.bind lan",
);
expect(log).toContain(
'run --rm --no-deps --entrypoint node openclaw-gateway dist/index.js config set gateway.controlUi.allowedOrigins ["http://127.0.0.1:18789"] --strict-json',
);
expect(log).not.toContain("run --rm openclaw-cli onboard --mode local --no-install-daemon");
});
it("avoids shared-network openclaw-cli before the gateway is started", async () => {
const activeSandbox = requireSandbox(sandbox);
const result = runDockerSetup(activeSandbox);
expect(result.status).toBe(0);
const log = await readFile(activeSandbox.logPath, "utf8");
const lines = log.split("\n").filter(Boolean);
const gatewayStartIdx = lines.findIndex(
(line) =>
line.includes("compose") && line.includes(" up -d") && line.includes("openclaw-gateway"),
);
expect(gatewayStartIdx).toBeGreaterThanOrEqual(0);
const prestartLines = lines.slice(0, gatewayStartIdx);
expect(prestartLines.some((line) => line.includes("run --rm openclaw-cli"))).toBe(false);
});
it("precreates config identity dir for CLI device auth writes", async () => {
@@ -260,6 +288,7 @@ describe("scripts/docker/setup.sh", () => {
const onboardIdx = log.indexOf("onboard");
expect(chownIdx).toBeGreaterThanOrEqual(0);
expect(onboardIdx).toBeGreaterThan(chownIdx);
expect(log).toContain("run --rm --no-deps --user root --entrypoint sh openclaw-gateway -c");
});
it("reuses existing config token when OPENCLAW_GATEWAY_TOKEN is unset", async () => {