Containerize the monitor with production and dev compose stacks, fix healthchecks and port handling, and make the dashboard base path configurable for direct or proxied access. Co-authored-by: Cursor <cursoragent@cursor.com>
5.1 KiB
Docker Deployment Guide for wxcc-monitor
This document explains how to run the application using Docker and Docker Compose.
Important Architectural Note: The /test Prefix
The container always serves the application at the root path (/, /api, /socket.io, etc.).
The paths containing /test that you see in src/views/dashboard.html and the client-side JavaScript are intentional for the current deployment model. An external reverse proxy (managed centrally by your team) adds the /test prefix for the dev instance and strips it before forwarding to the container.
Do not try to make the container aware of the /test prefix. The image and compose files are deliberately prefix-agnostic.
See the excellent comment at the top of src/server.js for the original explanation.
Quick Start
1. Production (Recommended)
# 1. Create your production env file (never commit it)
cp .env.example .env.prod
# Edit .env.prod with real values
# 2. Start the production stack
docker compose -f docker-compose.yml --env-file .env.prod up -d
# 3. Check health
docker compose -f docker-compose.yml ps
docker compose -f docker-compose.yml logs -f
Required bind mounts (defined in docker-compose.yml):
./data→/app/data./logs→/app/logs
2. Native Development (Primary Workflow)
npm run dev
This remains the recommended way to do day-to-day development.
3. Containerized Development Testing (Occasional Use)
# Use a separate env file or the regular .env
docker compose -f docker-compose.dev.yml --env-file .env up
# Or with a dedicated dev env:
# docker compose -f docker-compose.dev.yml --env-file .env.dev up
This starts the app inside Docker with:
- Your local source code mounted (live editing)
nodemonrunning inside the container (hot reload on file changes)- Separate container name (
wxcc-monitor-dev) and recommended host port3001
You can run the dev compose and production compose at the same time because they use different service names and files.
File Overview
| File | Purpose | When to Use |
|---|---|---|
Dockerfile |
Single multi-stage production image | Always (builds both) |
docker-compose.yml |
Production deployment | Production containers |
docker-compose.dev.yml |
Containerized dev testing with live reload | Occasional container testing |
.env.example |
Template for all required variables | Starting point for all envs |
Environment Files Strategy
Because you often want to run dev (native) and prod (container) at the same time, we recommend:
.envor.env.dev→ Native dev + dev container testing.env.prod→ Production container
Pass the correct file using --env-file when starting Compose.
Required Bind Mounts
The application writes many files at runtime:
data/tokens.jsondata/agentStates.jsondata/activeThresholdAlerts.jsondata/*.json(reference data refreshes)logs/*.log(Winston daily rotation + activity logs)
You must bind-mount the host ./data and ./logs directories when running containers. The compose files do this for you.
On first run the app will create any missing files and directories inside those mounts.
Health Checks
Both the Dockerfile and production compose file include health checks against the existing endpoints:
GET /healthGET /api/healthCheck
These are lightweight and safe to call frequently.
Common Operations
# View logs
docker compose -f docker-compose.yml logs -f app
# Restart after env change
docker compose -f docker-compose.yml --env-file .env.prod down
docker compose -f docker-compose.yml --env-file .env.prod up -d
# Rebuild image
docker compose -f docker-compose.yml build --no-cache
# Clean shutdown (triggers graceful save of agent state + alerts)
docker compose -f docker-compose.yml down
Security Notes
- The production image runs as the non-root
nodeuser. - Never put real secrets in any file tracked by git.
WEBHOOK_SECRETshould be a strong random value (minimum 32 bytes).
Troubleshooting
Dashboard or WebSocket not working when accessing the container directly?
This is expected if you are not going through the reverse proxy that adds the /test prefix. The client-side code in the dashboard expects the proxied paths.
Files disappearing on container restart?
You are not mounting ./data and ./logs. Add the bind mounts.
Webhook not being delivered?
WXCC_WEBHOOK_URL must be publicly reachable and must route through your reverse proxy down to the container. This is the #1 issue when moving to Docker.
Further Reading
src/server.js(Socket.IO path + proxy comments)src/views/dashboard.html(client-side paths)- The health endpoints in
src/app.jsandsrc/routes/api.js
Maintained as part of the wxcc-monitor project. Update this file when Docker usage patterns change.