Skip to content
Open
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
8 changes: 8 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ WORKDIR /opt/nemoclaw
RUN npm ci && npm run build

# Stage 2: Runtime image — pull cached base from GHCR
# hadolint ignore=DL3006
FROM ${BASE_IMAGE}

# Harden: remove unnecessary build tools and network probes from base image (#830)
Expand Down Expand Up @@ -161,6 +162,7 @@ json.dump(config, open(path, 'w'), indent=2); \
os.chmod(path, 0o600)"

# Install NemoClaw plugin into OpenClaw
# hadolint ignore=SC2015
RUN openclaw doctor --fix > /dev/null 2>&1 || true \
&& openclaw plugins install /opt/nemoclaw > /dev/null 2>&1 || true

Expand Down Expand Up @@ -189,6 +191,12 @@ RUN sha256sum /sandbox/.openclaw/openclaw.json > /sandbox/.openclaw/.config-hash
&& chmod 444 /sandbox/.openclaw/.config-hash \
&& chown root:root /sandbox/.openclaw/.config-hash

# Health check: poll the gateway's /health endpoint so Docker (and Compose)
# can detect and restart unhealthy containers in standalone deployments.
# Ref: https://github.com/NVIDIA/NemoClaw/issues/1430
HEALTHCHECK --interval=30s --timeout=5s --start-period=45s --retries=3 \
CMD curl -sf http://127.0.0.1:18789/health || exit 1

# Entrypoint runs as root to start the gateway as the gateway user,
# then drops to sandbox for agent commands. See nemoclaw-start.sh.
ENTRYPOINT ["/usr/local/bin/nemoclaw-start"]
Expand Down
9 changes: 9 additions & 0 deletions Dockerfile.base
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,12 @@ RUN mkdir -p /sandbox/.openclaw-data/agents/main/agent \
# When bumping the openclaw version, rebuild this base image.
RUN npm install -g openclaw@2026.3.11 \
&& pip3 install --no-cache-dir --break-system-packages "pyyaml==6.0.3"

# Baseline health check — validates the Node.js runtime only.
# The base image doesn't run services, so a process-level check is the
# best we can do here. **Child images that expose services MUST override
# this** with a service-specific probe (e.g., curl the gateway /health
# endpoint). The production Dockerfile already does so; any new child
# Dockerfile should add its own HEALTHCHECK instruction as well.
HEALTHCHECK --interval=30s --timeout=5s --start-period=45s --retries=3 \
CMD node -e "process.exit(0)"
5 changes: 5 additions & 0 deletions test/Dockerfile.sandbox
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,9 @@ RUN mkdir -p /sandbox/openclaw-state/extensions /sandbox/openclaw-state/skills /
&& printf '%s\n' '---' 'name: override-hook' 'description: Override hook fixture' '---' > /sandbox/openclaw-state/hooks/demo-hook/HOOK.md \
&& printf '%s\n' 'export default async function overrideHook() {}' > /sandbox/openclaw-state/hooks/demo-hook/handler.js

# Test image: no long-running service, so just verify the runtime works.
# Overrides any inherited HEALTHCHECK to avoid false-positive probes.
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD node -e "process.exit(0)" || exit 1

ENTRYPOINT ["/bin/bash"]