Mixed Runtimes with Docker#
Run Node and Python tools reliably in one reproducible environment.
Why Docker?#
Some tools run on Node, others on Python—your agent may spawn both. A single Docker image avoids PATH drift and “interpreter not found” issues across laptops, CI, and prod.
- Hermetic: Node + Python versions are pinned in the image
- No PATH drama:
nodeandpythonare present & discoverable - Prod/CI parity: the same image runs everywhere
- Easy secrets: pass API keys via env at
docker run/ Compose time - Fewer surprises: consistent OS libs (SSL, libc, LLM deps, etc.)
When to use it#
- Your platform doesn’t let you install both runtimes
- Your agent uses tools with different interpreters (Node + Python)
- Local IDE/CI PATH differences cause flaky runs
- You want reproducible builds and easy rollback
How it works (pattern)#
The base idea: start from a Python image, vendor a specific Node binary (or vice-versa), and set env that tells the SDKs which interpreters to use.
Key moves#
- Copy Node (e.g., Node 20) from an official Node image into your runtime layer
- Set
AGENTPM_NODE(and optionallyAGENTPM_PYTHON) to absolute paths - Install your app + the AgentPM SDK
Minimal outline (explained, not a full copy):
# Stage 1: pull a known Node version
FROM node:20-bullseye AS node20
# Stage 2: Python app base
FROM python:3.11-slim AS runtime
# Vendor Node into the runtime and point SDK at it
COPY --from=node20 /usr/local/bin/node /opt/node20/bin/node
ENV AGENTPM_NODE=/opt/node20/bin/node
# Create user/workdir, install app and AgentPM SDK
# (pip install, copy source, etc.)
# Optional debugging / tuning
ENV AGENTPM_DEBUG=1
# ENV AGENTPM_NODE_JITLESS=1
# ENV AGENTPM_NODE_OLD_SPACE_MB=1024
CMD ["python", "run.py"]Why this pattern works#
- You control exact Node/Python versions
- SDKs see absolute interpreters (
AGENTPM_NODE,AGENTPM_PYTHON) so PATH is irrelevant - Reproducible, single artifact for dev/CI/prod
Compose for local dev#
Mount your source and pass secrets/env conveniently:
version: "3.9"
services:
agent:
build: ..
image: agent-app:latest
environment:
OPENAI_API_KEY: ${OPENAI_API_KEY:-}
AGENTPM_DEBUG: "1" # verbose SDK diagnostics
# Optional interpreter overrides (usually unnecessary if image pins them)
# AGENTPM_NODE: /usr/bin/node
# AGENTPM_PYTHON: /usr/local/bin/python3.11
volumes:
- ./:/app
command: ["python", "run.py"]Runtime knobs that pair well with Docker#
- Interpreter selection
AGENTPM_NODE=/opt/node20/bin/nodeAGENTPM_PYTHON=/usr/local/bin/python3.11
- Tool discovery
AGENTPM_TOOL_DIR=/opt/tools(if you copy tools to a custom path)
- Diagnostics
AGENTPM_DEBUG=1to print project root, search paths, mergedPATH, and resolved interpreters
- Node memory / JIT
AGENTPM_NODE_OLD_SPACE_MB=512(injects--max-old-space-size)AGENTPM_NODE_JITLESS=1to add--jitless
- (Python SDK, POSIX)
AGENTPM_RLIMIT_AS_MB=2048to cap address space (not applied on macOS)
Best practices#
- Prefer absolute interpreters for production (e.g.,
/usr/bin/node); SDKs still enforce Node/Python family. - Bake exact tool versions and commit
agent.lockand runagentpm install --frozenin the build to ensure deterministic installs. - Keep secrets out of the image; pass via env at run time or use a secrets manager/Compose overrides.
- Tune memory for Node tools with
AGENTPM_NODE_OLD_SPACE_MBor explicit--max-old-space-sizeinentrypoint.args.
Troubleshooting#
- Interpreter not found. Ensure
AGENTPM_NODE/AGENTPM_PYTHONpoint to real binaries in the image. Turn onAGENTPM_DEBUG=1to see PATH and which() checks. - Tool not discovered. Verify
.agentpm/toolsexists in the container, or setAGENTPM_TOOL_DIR(and confirm with debug logs). - OOM / slow runs. Increase
AGENTPM_NODE_OLD_SPACE_MB, adjust Python rlimits, or set per-tooltimeout/timeoutMs. - Different behavior in dev vs CI. Build once, re-use the exact image tag in both places; avoid installing interpreters/tools differently across environments.