Node.js Runtime¶
This reference summarizes practical runtime defaults for Node.js workloads on Azure Container Apps so you can keep startup behavior, probe health, and logging predictable across revisions.
Runtime Execution Model¶
flowchart TD
IMG[Container Image] --> BOOT[Node.js Startup]
BOOT --> PORT[Bind 0.0.0.0:8000]
PORT --> PROBE[Health Probes]
PROBE --> TRAFFIC[Ingress Traffic]
TRAFFIC --> LOGS[stdout/stderr to Log Analytics] Treat runtime settings as deployment contracts
Keep port binding, process model, and logging behavior stable between revisions. Changing all three at once makes incident triage much harder.
Runtime Baseline (This Repo)¶
| Item | Value |
|---|---|
| Base image | node:20-slim |
| Web framework | Express |
| Process manager | Node.js (native) |
| Exposed/listen port | 8000 |
| Start command | node src/app.js |
Node.js Memory Management¶
When running Node.js in containers, it's important to align the V8 heap size with the container memory limit.
| Setting | Example | When to change |
|---|---|---|
| Max Heap Size | --max-old-space-size=1536 | Set to ~75% of container memory (e.g., 1.5GB for 2GB container) |
| HTTP Keep-Alive | server.keepAliveTimeout = 65000 | Increase to match or exceed Azure Ingress timeouts (60s) |
| Graceful Shutdown | server.close() | Ensure SIGTERM is handled to finish in-flight requests |
Recommended Start Command Pattern¶
Container Apps Alignment Checklist¶
| Check | Expected |
|---|---|
Azure Container Apps targetPort | 8000 |
| Express bind | 0.0.0.0:8000 |
| Health endpoint | GET /health returns 200 |
| Logs | stdout/stderr JSON format |
| Secrets/config | Read from process.env |
Quick Diagnostics¶
RG="rg-nodejs-guide"
# For CLI-deployed apps, set directly:
# APP_NAME="ca-nodejs-guide"
# For Bicep-deployed apps, capture from outputs:
DEPLOYMENT_NAME="main"
APP_NAME=$(az deployment group show \
--name "$DEPLOYMENT_NAME" \
--resource-group "$RG" \
--query "properties.outputs.containerAppName.value" \
--output tsv)
az containerapp logs show \
--name "$APP_NAME" \
--resource-group "$RG" \
--type console --follow
az containerapp exec \
--name "$APP_NAME" \
--resource-group "$RG" \
--command "/bin/sh"
# Inside container
node --version
npm list --depth=0
ps aux
| Command | Purpose |
|---|---|
APP_NAME=$(az deployment group show --name "$DEPLOYMENT_NAME" --resource-group "$RG" --query "properties.outputs.containerAppName.value" --output tsv) | Pulls the deployed Node.js app name from the Bicep outputs so the runtime checks target the exact app created by the guide. |
az containerapp logs show --name "$APP_NAME" --resource-group "$RG" --type console --follow | Streams the app's console logs so you can inspect Express startup and request logs in real time. |
az containerapp exec --name "$APP_NAME" --resource-group "$RG" --command "/bin/sh" | Opens a shell inside the running container so you can verify the Node.js runtime, installed packages, and active processes from the replica itself. |
Frequent Runtime Failures¶
| Symptom | Root cause | Action |
|---|---|---|
| Container healthy locally, failing in Container Apps | Port/ingress mismatch | Align Express bind and Container Apps targetPort |
| Memory leaks or OOM kills | V8 heap exceeds container limit | Set --max-old-space-size and check for leaks |
| Requests dropped during rollout | Missing SIGTERM handler | Implement graceful shutdown in src/app.js |
| Missing logs in Log Analytics | Console output not captured | Ensure logs are written to stdout/stderr, not files |
Avoid hardcoding runtime assumptions
If your app assumes a fixed port, writable local filesystem, or shell-only startup dependencies, revisions may pass locally but fail in Container Apps. Validate behavior with environment-driven configuration and health probes.
See Also¶
- Node.js Language Guide Index
- 01 - Run Locally with Docker
- 03 - Configuration, Secrets, and Dapr
- Container Design Best Practices