Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/sandbox-images-and-e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@ jobs:
--memory 256m \
--entrypoint /bin/sh \
nemoclaw-hermes-production -eu -c '
test "$NODE_EXTRA_CA_CERTS" = /usr/local/share/nemoclaw/corporate-ca.pem
test -z "${NODE_EXTRA_CA_CERTS:-}"
test -z "${CURL_CA_BUNDLE:-}"
test ! -e /usr/local/share/nemoclaw/corporate-ca.pem
test ! -L /usr/local/share/nemoclaw/corporate-ca.pem
test -x /usr/local/bin/hermes
Expand Down
50 changes: 32 additions & 18 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -629,17 +629,6 @@
# final-image layer while preserving metadata on existing parent directories.
COPY --from=openclaw-dependency-payload / /

# The final image owns the shipped dependency boundary independently of base
# freshness. Reassert the npm-private node-tar fix here; the helper is
# idempotent for a remediated base and fails closed on unexpected npm layouts.
RUN node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts \
--npm-root /usr/local/lib/node_modules/npm

# Reassert the npm-private brace-expansion fix for the exact final filesystem.
# hadolint ignore=DL3059
RUN node --experimental-strip-types /scripts/patch-bundled-npm-brace-expansion.mts \
--npm-root /usr/local/lib/node_modules/npm

# OpenClaw 2026.7.1 loads some generated source through jiti. Disable its
# filesystem transform cache so source fragments that mention provider marker
# names do not persist under /tmp/jiti inside the sandbox.
Expand Down Expand Up @@ -676,18 +665,35 @@
&& echo "[nemoclaw] baked host corporate-proxy CA into image trust (#6210)"; \
fi

# Anchor the corporate CA for build-time TLS too, not just runtime. The
# OpenClaw/mcporter reinstall path makes registry-backed npm requests; behind a
# TLS-intercepting corporate proxy those requests need the operator CA. Node
# ignores a missing file, so this is a no-op when no CA was baked; at runtime
# nemoclaw-start overrides it with the merged OpenShell + corporate bundle.
ENV NODE_EXTRA_CA_CERTS=/usr/local/share/nemoclaw/corporate-ca.pem
# Use the corporate CA for build-time Node TLS only when onboarding supplied
# it. The runtime entrypoint builds its own merged OpenShell and corporate
# bundle.

# The final image owns the shipped dependency boundary independently of base
# freshness. Reassert the idempotent npm-private fixes after corporate CA setup
# so cold registry-backed remediation can use the operator-supplied trust root.
RUN if [ -f /usr/local/share/nemoclaw/corporate-ca.pem ]; then \
export CURL_CA_BUNDLE=/usr/local/share/nemoclaw/corporate-ca.pem; \
export NODE_EXTRA_CA_CERTS=/usr/local/share/nemoclaw/corporate-ca.pem; \
fi; \
node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts \
--npm-root /usr/local/lib/node_modules/npm

# Reassert the npm-private brace-expansion fix for the exact final filesystem.
# hadolint ignore=DL3059
RUN if [ -f /usr/local/share/nemoclaw/corporate-ca.pem ]; then \
export CURL_CA_BUNDLE=/usr/local/share/nemoclaw/corporate-ca.pem; \
export NODE_EXTRA_CA_CERTS=/usr/local/share/nemoclaw/corporate-ca.pem; \
fi; \
node --experimental-strip-types /scripts/patch-bundled-npm-brace-expansion.mts \
--npm-root /usr/local/lib/node_modules/npm

# Reassert the npm-private ip-address fix for the exact final filesystem. When
# onboarding supplied a corporate CA, use it for the registry-backed download.
# hadolint ignore=DL3059
RUN if [ -f /usr/local/share/nemoclaw/corporate-ca.pem ]; then \
export CURL_CA_BUNDLE=/usr/local/share/nemoclaw/corporate-ca.pem; \
export NODE_EXTRA_CA_CERTS=/usr/local/share/nemoclaw/corporate-ca.pem; \
Comment thread
apurvvkumaria marked this conversation as resolved.
fi; \
node --experimental-strip-types /scripts/lib/patch-bundled-npm-ip-address.mts \
--npm-root /usr/local/lib/node_modules/npm
Expand Down Expand Up @@ -743,7 +749,11 @@
NPM_CONFIG_FETCH_RETRY_MINTIMEOUT=1000 \
NPM_CONFIG_FETCH_RETRY_MAXTIMEOUT=20000 \
NPM_CONFIG_FETCH_TIMEOUT=60000
RUN --network=default NODE_OPTIONS=--dns-result-order=ipv4first \
RUN --network=default if [ -f /usr/local/share/nemoclaw/corporate-ca.pem ]; then \
export CURL_CA_BUNDLE=/usr/local/share/nemoclaw/corporate-ca.pem; \
export NODE_EXTRA_CA_CERTS=/usr/local/share/nemoclaw/corporate-ca.pem; \
fi; \
NODE_OPTIONS=--dns-result-order=ipv4first \
/usr/local/lib/nemoclaw-build-tools/npm-ci-locked.sh --omit=dev \
&& rm -rf /usr/local/lib/nemoclaw-build-tools/npm-cache-seed \
&& rm -f /usr/local/lib/nemoclaw-build-tools/npm-ci-locked.sh
Expand Down Expand Up @@ -825,6 +835,10 @@
# basename in a fresh directory, local-archive-only install, and cleanup.
# hadolint ignore=DL3059,DL4006,DL3016
RUN --network=default set -eu; \
if [ -f /usr/local/share/nemoclaw/corporate-ca.pem ]; then \
export CURL_CA_BUNDLE=/usr/local/share/nemoclaw/corporate-ca.pem; \
export NODE_EXTRA_CA_CERTS=/usr/local/share/nemoclaw/corporate-ca.pem; \
fi; \
echo "$OPENCLAW_VERSION" | grep -qxE '[0-9]+(\.[0-9]+)*' \
|| { echo "ERROR: OPENCLAW_VERSION='$OPENCLAW_VERSION' is invalid (expected e.g. 2026.3.11)" >&2; exit 1; }; \
MIN_VER=$(grep -m 1 'min_openclaw_version' /opt/nemoclaw-blueprint/blueprint.yaml | awk '{print $2}' | tr -d '"'); \
Expand Down Expand Up @@ -1646,10 +1660,10 @@
# CHAT_UI_URL is a non-loopback address (Brev Launchable, remote deployments)
# since terminal-based pairing is impossible in those contexts.
# Default: "0" (device auth enabled for local deployments — secure by default).
ARG NEMOCLAW_DISABLE_DEVICE_AUTH=0

Check warning on line 1663 in Dockerfile

View workflow job for this annotation

GitHub Actions / PR build and direct managed startup (OpenClaw)

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "NEMOCLAW_DISABLE_DEVICE_AUTH") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/

Check warning on line 1663 in Dockerfile

View workflow job for this annotation

GitHub Actions / PR build and direct managed startup (OpenClaw)

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "NEMOCLAW_DISABLE_DEVICE_AUTH") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
# Internal audit provenance for the opt-out above. Standard onboarding rewrites
# this to managed-onboard; direct image builders retain operator provenance.
ARG NEMOCLAW_DEVICE_AUTH_OPT_OUT_SOURCE=operator

Check warning on line 1666 in Dockerfile

View workflow job for this annotation

GitHub Actions / PR build and direct managed startup (OpenClaw)

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "NEMOCLAW_DEVICE_AUTH_OPT_OUT_SOURCE") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/

Check warning on line 1666 in Dockerfile

View workflow job for this annotation

GitHub Actions / PR build and direct managed startup (OpenClaw)

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "NEMOCLAW_DEVICE_AUTH_OPT_OUT_SOURCE") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
# Compatibility build arg for older custom Dockerfiles and rebuild tooling.
# NemoClaw-managed images intentionally do not consume it; gateway auth tokens
# are generated at container startup and are never baked into image layers.
Expand Down Expand Up @@ -1683,7 +1697,7 @@
# NEMOCLAW_MESSAGING_PLAN_B64 intentionally remains ARG-only: Docker exposes it
# to build RUN processes without retaining the full plan in the final image env.
# Direct ARG interpolation into inline source is a code injection vector (C-2).
ENV NEMOCLAW_MODEL=${NEMOCLAW_MODEL} \

Check warning on line 1700 in Dockerfile

View workflow job for this annotation

GitHub Actions / PR build and direct managed startup (OpenClaw)

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "NEMOCLAW_DEVICE_AUTH_OPT_OUT_SOURCE") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/

Check warning on line 1700 in Dockerfile

View workflow job for this annotation

GitHub Actions / PR build and direct managed startup (OpenClaw)

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "NEMOCLAW_DISABLE_DEVICE_AUTH") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/

Check warning on line 1700 in Dockerfile

View workflow job for this annotation

GitHub Actions / PR build and direct managed startup (OpenClaw)

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "NEMOCLAW_DEVICE_AUTH_OPT_OUT_SOURCE") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/

Check warning on line 1700 in Dockerfile

View workflow job for this annotation

GitHub Actions / PR build and direct managed startup (OpenClaw)

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "NEMOCLAW_DISABLE_DEVICE_AUTH") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
NEMOCLAW_INFERENCE_PROVIDER_ID=${NEMOCLAW_INFERENCE_PROVIDER_ID} \
NEMOCLAW_UPSTREAM_PROVIDER=${NEMOCLAW_UPSTREAM_PROVIDER} \
NEMOCLAW_PRIMARY_MODEL_REF=${NEMOCLAW_PRIMARY_MODEL_REF} \
Expand Down
14 changes: 10 additions & 4 deletions agents/hermes/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,9 @@ RUN if [ -n "${NEMOCLAW_CORPORATE_CA_B64}" ]; then \
&& echo "[nemoclaw] baked host corporate-proxy CA into image trust (#6210)"; \
fi

# Use the decoded CA for Node.js package operations in this final stage. Node.js
# ignores the path when no CA was baked. At runtime, nemoclaw-start replaces it
# with the merged OpenShell and corporate bundle.
ENV NODE_EXTRA_CA_CERTS=/usr/local/share/nemoclaw/corporate-ca.pem
# Use the decoded CA for Node.js package operations in this final stage only
# when onboarding supplied it. At runtime, nemoclaw-start builds the merged
# OpenShell and corporate bundle.

# Cross-stage root copies are accepted by Docker's legacy builder and create
# one final-image layer while preserving metadata on existing parent paths.
Expand All @@ -212,6 +211,7 @@ COPY --from=hermes-npm-patch-payload / /
# onboarding supplied a corporate CA, use it for the registry-backed download.
RUN if [ -f /usr/local/share/nemoclaw/corporate-ca.pem ]; then \
export CURL_CA_BUNDLE=/usr/local/share/nemoclaw/corporate-ca.pem; \
export NODE_EXTRA_CA_CERTS=/usr/local/share/nemoclaw/corporate-ca.pem; \
fi; \
node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts \
--npm-root /usr/local/lib/node_modules/npm
Expand All @@ -222,6 +222,7 @@ RUN if [ -f /usr/local/share/nemoclaw/corporate-ca.pem ]; then \
# hadolint ignore=DL3059
RUN if [ -f /usr/local/share/nemoclaw/corporate-ca.pem ]; then \
export CURL_CA_BUNDLE=/usr/local/share/nemoclaw/corporate-ca.pem; \
export NODE_EXTRA_CA_CERTS=/usr/local/share/nemoclaw/corporate-ca.pem; \
fi; \
node --experimental-strip-types /scripts/patch-bundled-npm-brace-expansion.mts \
--npm-root /usr/local/lib/node_modules/npm
Expand All @@ -231,6 +232,7 @@ RUN if [ -f /usr/local/share/nemoclaw/corporate-ca.pem ]; then \
# hadolint ignore=DL3059
RUN if [ -f /usr/local/share/nemoclaw/corporate-ca.pem ]; then \
export CURL_CA_BUNDLE=/usr/local/share/nemoclaw/corporate-ca.pem; \
export NODE_EXTRA_CA_CERTS=/usr/local/share/nemoclaw/corporate-ca.pem; \
fi; \
node --experimental-strip-types /scripts/lib/patch-bundled-npm-ip-address.mts \
--npm-root /usr/local/lib/node_modules/npm
Expand Down Expand Up @@ -265,6 +267,10 @@ RUN chmod -R a+rX /opt/hermes/.venv \
# the sandbox user account. Remove this fallback after all supported base image
# tags are built from Dockerfile.base with HERMES_WEB_DIST prepopulated.
RUN set -eu; \
if [ -f /usr/local/share/nemoclaw/corporate-ca.pem ]; then \
export CURL_CA_BUNDLE=/usr/local/share/nemoclaw/corporate-ca.pem; \
export NODE_EXTRA_CA_CERTS=/usr/local/share/nemoclaw/corporate-ca.pem; \
fi; \
hermes_web_dist=/opt/hermes/hermes_cli/web_dist; \
hermes_web_dir=/opt/hermes/web; \
if [ ! -d "$hermes_web_dist" ]; then \
Expand Down
2 changes: 1 addition & 1 deletion ci/source-shape-test-budget.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
},
{
"file": "test/corporate-ca-build-tls-anchor.test.ts",
"test": "decodes the CA and exports NODE_EXTRA_CA_CERTS before registry-backed dependency requests (#8925)",
"test": "uses conditional Node and curl trust in every final-stage registry step",
"category": "security"
},
{
Expand Down
4 changes: 2 additions & 2 deletions docs/manage-sandboxes/recover-rebuild-sandboxes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ Use the lightest recovery operation that repairs the sandbox while preserving it

## Restart a Stopped Sandbox Container

If status reports `Phase: Error` and confirms that the sandbox container exists but is stopped, restart the existing container:
If NemoClaw reports that a Docker-driver sandbox is stopped, restart the existing container:

```bash
$$nemoclaw <sandbox-name> start
```

This path preserves the sandbox workspace and repairs the agent runtime and host-side forwards after the container starts.
If the container is paused, follow the printed `docker unpause` guidance instead.
If the container is missing or OpenShell reports another terminal phase such as `Failed`, follow the printed `rebuild --yes` guidance so NemoClaw can recreate the sandbox from its recorded metadata.
If Docker no longer has the container, follow the printed `rebuild --yes` guidance so NemoClaw can recreate the sandbox from its recorded metadata.

<AgentOnly variant="openclaw,hermes">
The `start` command returns success only after it authenticates the recovered agent runtime, OpenShell reports the sandbox ready, and host-side port forwards pass their checks.
Expand Down
12 changes: 9 additions & 3 deletions docs/security/configure-corporate-ca-trust.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ This lets the in-sandbox OpenShell proxy validate TLS when it opens the upstream

<AgentOnly variant="openclaw">

It sets `NODE_EXTRA_CA_CERTS` before registry-backed build-time Node.js dependency requests that cross a TLS-inspecting proxy.
When onboarding supplies a corporate CA, the Dockerfile sets `NODE_EXTRA_CA_CERTS` and `CURL_CA_BUNDLE` in each final-stage build step that accesses the npm registry.
This includes registry-backed npm remediation and runtime dependency installation that cross a TLS-inspecting proxy.
The build does not retain either variable in the image configuration.

The required `reviewed-npm-audit` CI check materializes the dependency graph from the committed lock and verifies its registry signatures.
Any nonzero `npm audit signatures` status fails the check.
The pull request (PR) check must pass before merge.
Expand All @@ -58,8 +61,11 @@ Sandboxes still using the staged legacy direct-start path create `/tmp/nemoclaw-
<AgentOnly variant="hermes">

The Hermes discovery-runtime installer applies the corporate CA before its npm operations.
The final Hermes image stage decodes the CA immediately after `FROM ${BASE_IMAGE}` and sets `NODE_EXTRA_CA_CERTS` before later npm operations.
The registry-backed npm remediations set `CURL_CA_BUNDLE` before each download only when the decoded certificate file exists.
The final Hermes image stage decodes the CA immediately after `FROM ${BASE_IMAGE}`.
When the decoded CA file exists, the Dockerfile sets `NODE_EXTRA_CA_CERTS` and `CURL_CA_BUNDLE` in each later build step that accesses the npm registry.
These operations include registry-backed npm remediation and the fallback Hermes dashboard build.
The build does not retain either variable in the image configuration.
When the decoded CA file does not exist, these operations use their default trust configuration.
The Hermes package installer clears inherited `SSL_CERT_FILE` and `REQUESTS_CA_BUNDLE` values before its build-time `uv pip install` commands.
When the decoded CA exists, it sets both variables to that file for those commands.
If the file does not exist, uv and Python use their default trust configuration.
Expand Down
21 changes: 18 additions & 3 deletions src/lib/actions/sandbox/docker-health.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ describe("getSandboxDockerRuntime (#4495)", () => {
expect(getSandboxDockerRuntime("my-assistant", deps)).toEqual({
health: "none",
paused: false,
running: false,
containerName: null,
});
});
Expand All @@ -193,6 +194,7 @@ describe("getSandboxDockerRuntime (#4495)", () => {
expect(getSandboxDockerRuntime("my-assistant", deps)).toEqual({
health: "unhealthy",
paused: true,
running: true,
containerName: "openshell-my-assistant-live",
});
});
Expand All @@ -206,6 +208,7 @@ describe("getSandboxDockerRuntime (#4495)", () => {
expect(getSandboxDockerRuntime("my-assistant", deps)).toEqual({
health: "none",
paused: false,
running: false,
containerName: "openshell-my-assistant-12ab",
});
});
Expand All @@ -215,13 +218,23 @@ describe("getSandboxDockerRuntime (#4495)", () => {
expect(getSandboxDockerRuntime("my-assistant", deps)).toEqual({
health: "healthy",
paused: true,
running: true,
containerName: "openshell-my-assistant-12ab",
});
});

it("reports paused=false for a running container", () => {
const deps = fixture({ healthRaw: "healthy\n", pausedRaw: "false\n" });
expect(getSandboxDockerRuntime("my-assistant", deps).paused).toBe(false);
it("reports running state for the owned container", () => {
const running = getSandboxDockerRuntime("my-assistant", fixture());
const stopped = getSandboxDockerRuntime(
"my-assistant",
fixture({
psNames: "openshell-cluster-nemoclaw\n",
psAllNames: "openshell-cluster-nemoclaw\nopenshell-my-assistant-12ab\n",
}),
);

expect(running).toMatchObject({ running: true, paused: false });
expect(stopped).toMatchObject({ running: false, paused: false });
});

it("normalizes whitespace and case in the .State.Paused value", () => {
Expand Down Expand Up @@ -250,6 +263,7 @@ describe("getSandboxDockerRuntime (#4495)", () => {
expect(getSandboxDockerRuntime("my-assistant", deps)).toEqual({
health: "none",
paused: false,
running: false,
containerName: null,
});
expect(findLabeledSandboxContainers).not.toHaveBeenCalled();
Expand All @@ -260,6 +274,7 @@ describe("getSandboxDockerRuntime (#4495)", () => {
expect(getSandboxDockerRuntime("my-assistant", deps)).toEqual({
health: "none",
paused: false,
running: false,
containerName: null,
});
});
Expand Down
30 changes: 18 additions & 12 deletions src/lib/actions/sandbox/docker-health.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ export interface SandboxDockerHealth {

/**
* Combined Docker runtime view for a docker-driver sandbox container: the
* HEALTHCHECK signal plus whether the container is paused (`docker pause`).
* HEALTHCHECK signal plus whether the container is running or paused (`docker pause`).
* A paused container can surface upstream as `Phase: Error` even though the
* sandbox is intact, so `status` reads `paused` to print a recovery hint
* without rewriting the authoritative phase. See #4495.
*/
export interface SandboxDockerRuntime {
health: DockerHealthState;
paused: boolean;
running: boolean;
containerName: string | null;
}

Expand Down Expand Up @@ -110,12 +111,12 @@ function normalizePausedState(raw: string): boolean {

/**
* Resolve an OpenShell-labeled docker-driver sandbox container across all states
* and read both its HEALTHCHECK state and `.State.Paused` flag. Label-scoped
* discovery matches the ownership boundary enforced by `start`; preferring its
* running rows preserves paused-container guidance before falling back to an
* exited container that `start` can recover (#7222). Returns `health: "none",
* paused: false` when the sandbox is not on the docker driver or no owned
* container is found. See #4495.
* and read its HEALTHCHECK state, running state, and `.State.Paused` flag.
* Label-scoped discovery matches the ownership boundary enforced by `start`;
* preferring its running rows preserves paused-container guidance before
* falling back to an exited container that `start` can recover (#7222).
* Returns `health: "none"`, `paused: false`, and `running: false` when the
* sandbox is not on the docker driver or no owned container is found. See #4495.
*/
export function getSandboxDockerRuntime(
sandboxName: string,
Expand All @@ -124,16 +125,16 @@ export function getSandboxDockerRuntime(
const deps: ResolveDeps = { ...defaultDeps, ...depsOverride };
try {
if (deps.getSandbox(sandboxName)?.openshellDriver !== "docker") {
return { health: "none", paused: false, containerName: null };
return { health: "none", paused: false, running: false, containerName: null };
}
} catch {
return { health: "none", paused: false, containerName: null };
return { health: "none", paused: false, running: false, containerName: null };
}
let labeledContainers: ReturnType<typeof findLabeledSandboxContainers>;
try {
labeledContainers = deps.findLabeledSandboxContainers(sandboxName);
} catch {
return { health: "none", paused: false, containerName: null };
return { health: "none", paused: false, running: false, containerName: null };
}
const runningNames = labeledContainers
.filter((container) => container.running)
Expand All @@ -149,7 +150,12 @@ export function getSandboxDockerRuntime(
...deps,
dockerPsNames: () => allNames,
});
if (!containerName) return { health: "none", paused: false, containerName: null };
if (!containerName) {
return { health: "none", paused: false, running: false, containerName: null };
}
const running = labeledContainers.some(
(container) => container.name === containerName && container.running,
);
let health: DockerHealthState;
try {
health = normalizeHealthState(deps.dockerInspectHealth(containerName));
Expand All @@ -162,5 +168,5 @@ export function getSandboxDockerRuntime(
} catch {
paused = false;
}
return { health, paused, containerName };
return { health, paused, running, containerName };
}
Loading
Loading