Skip to content
Russ Goldin edited this page Feb 25, 2026 · 11 revisions

Pre-built Docker images

Image channels (important)

latest is channel-specific. It does not mean latest code across all registries.

  • ghcr.io/tagyoureit/njspc - official controller image published from upstream tagyoureit/nodejs-poolController.
  • ghcr.io/sam2kb/njspc - fork-maintained controller image (may lag upstream).
  • msmi/nodejs-poolcontroller - legacy Docker Hub controller image (may lag upstream).
  • ghcr.io/sam2kb/njspc-dash - dashPanel image currently published separately.

Canonical docs and examples

Use these files in the main repo as the source of truth:

This wiki page keeps quick-start examples, but repo files are authoritative.

Quick test (Linux host with /dev/ttyUSB0)

docker run --rm -it \
  --group-add dialout \
  -p 4200:4200 \
  --device /dev/ttyUSB0 \
  ghcr.io/tagyoureit/njspc:latest

Docker Compose examples

For a more permanent install, use Docker Compose.

Server-only minimal example

services:
  njspc:
    image: ${NJSPC_IMAGE:-ghcr.io/tagyoureit/njspc}
    container_name: njspc
    restart: unless-stopped
    group_add:
      - dialout
    devices:
      - /dev/ttyUSB0:/dev/ttyUSB0
    ports:
      - "4200:4200"

Server-only with persisted config/state

services:
  njspc:
    image: ${NJSPC_IMAGE:-ghcr.io/tagyoureit/njspc}
    container_name: njspc
    restart: unless-stopped
    group_add:
      - dialout
    devices:
      - /dev/ttyUSB0:/dev/ttyUSB0
    ports:
      - "4200:4200"
    volumes:
      - /data/poolcontroller/data:/app/data
      - /data/poolcontroller/logs:/app/logs
      - /data/poolcontroller/backups:/app/backups
      - type: bind
        source: /data/poolcontroller/config.json
        target: /app/config.json

Server plus optional dashPanel

services:
  njspc:
    image: ${NJSPC_IMAGE:-ghcr.io/tagyoureit/njspc}
    container_name: njspc
    restart: unless-stopped
    group_add:
      - dialout
    devices:
      - /dev/ttyUSB0:/dev/ttyUSB0
    ports:
      - "4200:4200"
    volumes:
      - /data/poolcontroller/data:/app/data
      - type: bind
        source: /data/poolcontroller/config.json
        target: /app/config.json

  njspc-dash:
    image: ${NJSPC_DASH_IMAGE:-ghcr.io/sam2kb/njspc-dash}
    container_name: njspc-dash
    restart: unless-stopped
    depends_on:
      - njspc
    ports:
      - "5150:5150"
    volumes:
      - type: bind
        source: /data/poolcontroller-dashpanel/config.json
        target: /app/config.json

Docker socat example (serial-to-TCP bridge)

services:
  njspc:
    image: ${NJSPC_IMAGE:-ghcr.io/tagyoureit/njspc}
    container_name: njspc
    restart: unless-stopped
    ports:
      - "4200:4200"
    environment:
      - POOL_NET_CONNECT=true
      - POOL_NET_HOST=socat
      - POOL_NET_PORT=9801
    volumes:
      - /data/poolcontroller/data:/app/data
      - type: bind
        source: /data/poolcontroller/config.json
        target: /app/config.json

  socat:
    image: alpine/socat
    command: tcp-listen:9801,fork,reuseaddr file:/dev/ttyUSB0,b9600,raw,echo=0
    container_name: socat
    restart: unless-stopped
    ports:
      - "9801:9801"
    devices:
      - /dev/ttyUSB0:/dev/ttyUSB0

Socat is useful when you want to run controller and serial access separately or remotely.

Docker serial port access

You must specify the serial device in Compose or with docker run.

For Linux hosts, adding the container user to dialout is usually safest:

group_add:
  - dialout

Avoid running as root unless needed. If using root, ensure /app/data mounts are writable or poolConfig.json/poolState.json updates may fail.

Example fix:

sudo chown -R 1000:1000 /data/poolcontroller/data
sudo chmod -R u+rw /data/poolcontroller/data

For Docker Desktop on macOS/Windows, raw /dev/tty* passthrough differs from native Linux and may not work the same way. Use a TCP bridge (socat) when direct mapping is unavailable.

Notes

Update to the latest tags in your selected channel:

docker compose pull && docker compose up -d

If running without mounted config and you need a copy:

docker cp njspc:/app/config.json ./config.json

Connect to a running container:

docker exec -it njspc sh

Verify the code revision in your image:

docker image inspect ghcr.io/tagyoureit/njspc:latest --format '{{ index .Config.Labels "org.opencontainers.image.revision" }}'
docker image inspect ghcr.io/sam2kb/njspc:latest --format '{{ index .Config.Labels "org.opencontainers.image.revision" }}'
docker image inspect msmi/nodejs-poolcontroller:latest --format '{{ index .Config.Labels "git-commit" }}'

Build a customized Docker image

If you want to add packages or build for a specific environment, use the repo Dockerfile as a template.

git clone https://github.com/tagyoureit/nodejs-poolController
cd nodejs-poolController
cp Dockerfile ../Dockerfile.mine

Example add-ons (alpine runtime):

FROM node:20-alpine AS build
RUN apk add --no-cache make gcc g++ python3 linux-headers udev tzdata
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
RUN npm prune --production

FROM node:20-alpine AS prod
RUN apk add --no-cache bash bash-completion
WORKDIR /app
COPY --from=build /app .
USER node
ENV NODE_ENV=production
ENTRYPOINT ["node", "dist/app.js"]

Build and run:

docker build --tag mynjspc --file ../Dockerfile.mine .
docker compose up -d

Clone this wiki locally