From 1ac9ef948b1d7c6a964cd517d3d7b4512a51b6a7 Mon Sep 17 00:00:00 2001 From: David Gwilliam Date: Wed, 1 Jul 2026 01:50:39 -0700 Subject: [PATCH] nodered: bake Dashboard 2.0 into Dockerfile for idempotent install NR's automatic package.json install at container start was slow and required internet. Move npm install to image build time, preserve the installed node_modules via an anonymous volume so the bind mount of ./nodered:/data doesn't clobber them. --- infra/compose.yaml | 7 ++++--- infra/nodered/Dockerfile | 27 +++++++++++++++++++++++++++ infra/nodered/package.json | 9 +++++++++ 3 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 infra/nodered/Dockerfile create mode 100644 infra/nodered/package.json diff --git a/infra/compose.yaml b/infra/compose.yaml index d552cf0..bbb290e 100644 --- a/infra/compose.yaml +++ b/infra/compose.yaml @@ -39,7 +39,7 @@ services: # TZ: America/Los_Angeles # nodered: - image: nodered/node-red:latest + build: ./nodered container_name: nodered restart: unless-stopped depends_on: @@ -48,11 +48,12 @@ services: ports: - "1880:1880" volumes: - - ./nodered:/data + - ./nodered:/data # bind: settings.js, flows.json, start.sh, package.json + - /data/node_modules # anonymous: preserves build-time npm install environment: TZ: America/Los_Angeles DASHBOARD_BASE_HREF: /dashboard/ - command: ["sh", "/data/start.sh"] + command: ["sh", "/data/start.sh"] # Listens to ntfy.sh for doorbell events and toggles a smart plug on each alert. # Topic: ALERT_klubhaus_topic_test (matches ESP32 firmware DEBUG_MODE suffix) diff --git a/infra/nodered/Dockerfile b/infra/nodered/Dockerfile new file mode 100644 index 0000000..42b3122 --- /dev/null +++ b/infra/nodered/Dockerfile @@ -0,0 +1,27 @@ +# Node-RED container with Dashboard 2.0 baked in +# Build once; restart containers freely. NR's automatic package.json install +# at boot is slow and requires internet; this Dockerfile install is cached +# and reproducible. +# +# Docker volume pattern: ./nodered:/data is a bind mount (settings.js, +# flows.json, start.sh, package.json are host-owned); /data/node_modules +# is an anonymous volume so the bind mount doesn't clobber the installed +# deps. Docker copies the image's node_modules into the volume on first start. + +FROM nodered/node-red:5.0.0 + +# Install Dashboard 2.0 (and any future deps) at image-build time. +# Versions are pinned in infra/nodered/package.json for reproducibility. +COPY package.json /data/package.json +WORKDIR /data +RUN npm install --omit=dev --no-audit --no-fund \ + && chown -R 1000:1000 /data/node_modules \ + && echo "[Dockerfile] installed @flowfuse/node-red-dashboard" + +# start.sh handles the SPA base-href patch (idempotent: grep guard). +# Chmod so the compose `user: 1000:1000` can run it. +COPY start.sh /data/start.sh +RUN chmod +x /data/start.sh + +# Reset to NR's working dir; userDir is /data via the compose volume mount. +WORKDIR /usr/src/node-red diff --git a/infra/nodered/package.json b/infra/nodered/package.json new file mode 100644 index 0000000..0c74c6f --- /dev/null +++ b/infra/nodered/package.json @@ -0,0 +1,9 @@ +{ + "name": "node-red-project", + "description": "Node-RED flows for Klubhaus zigbee-monitor", + "version": "0.0.1", + "private": true, + "dependencies": { + "@flowfuse/node-red-dashboard": "1.30.2" + } +}