# /usr/src/node-red/node\_modules vs /data/node\_modules with Docker

**URL:** https://discourse.nodered.org/t/usr-src-node-red-node-modules-vs-data-node-modules-with-docker/65200
**Category:** General
**Tags:** docker
**Created:** [17 July 2022 04:31 UTC](https://discourse.nodered.org/t/usr-src-node-red-node-modules-vs-data-node-modules-with-docker/65200 "2022-07-17T04:31:02Z")
**Posts on this page:** 14
**Page:** 1

<div class="post-metadata">

### Author: ![SewShulMeedeeUh](https://avatars.discourse-cdn.com/v4/letter/s/f1d935/32.png) [@SewShulMeedeeUh](https://discourse.nodered.org/u/SewShulMeedeeUh)
#### Post date: [17 July 2022 04:31 UTC](https://discourse.nodered.org/t/usr-src-node-red-node-modules-vs-data-node-modules-with-docker/65200/1 "2022-07-17T04:31:02Z")

</div>

**TLDR:** If Node-Red installs npm packages auto-magically into `/data/`, what is the point of a custom docker image as base image/layer?

  

**Details:**  
Firstly, congrats on the [3.x release](https://discourse.nodered.org/t/node-red-3-0-released/65082)!

I am trying to update/adapt my NR image to use the new [Docker image base](https://hub.docker.com/layers/node-red/nodered/node-red/3.0.0-16-minimal/images/sha256-eae3c009a2daddbb4e580e08629654cb427693a5d2a7785e42006863282beece?context=explore), but am running into some challenges (let me know if there is a more appropriate place to ask this).

As per the [Docker Quick Start](https://nodered.org/docs/getting-started/docker), I have a `package.json` (also tried manually `npm install` the needed packages). In the example Dockerfile provided, it uses...

`COPY package.json .`

Am I understanding correctly that this places that `package.json` in the already-defined/default `WORKDIR` (`/usr/src/node-red`)? This is where/how I was adding my extra npm packages (debugger, db libraries, etc).

When I `docker compose ... up` the image container, I see...

> (snipped)...  
> [info] Installing module: pg, version: latest  
> [info] Installed module: pg  
> (snipped)...

So, even though the package/module was already installed and available, it gets installed again? The `flows.json` I am including does define this library (`pg`, for Postgresql) in a function's modules section (which is correct, yes?) This is at least in part why I see the output above, correct?

I extracted the default `settings.js` to enable the new `runtime` [feature](https://nodered.org/blog/2022/07/14/version-3-0-released#editing-stopped-flows) (which is disabled by default). I also plan to include auth info (which is also why I am not relying on the default baked-in version of `settings.js`). I mention this to explain there shouldn't be anything problematic in there.

If I `docker exec -it mynodered sh` into the running container...

> ~ $ pwd  
> /usr/src/node-red  
> ~ $ npm ls --depth=0  
> node-red-docker@3.0.0 /usr/src/node-red  
> +-- @azure/cosmos@3.10.5  
> +-- node-red-contrib-actionflows@2.1.2  
> +-- node-red-contrib-friendly-id@0.2.1  
> +-- node-red-debugger@1.1.1  
> +-- node-red@3.0.0  
> `-- pg@8.6.0
> 
> ~ $ cd /data/  
> /data $ npm ls --depth=0  
> node-red-project@0.0.1 /data  
> +-- @azure/cosmos@3.16.3  
> `-- pg@8.7.3

So, if despite my custom image built off `nodered/node-red:3.0.0-16-minimal` as the base, NR still populates a `node_modules` folder in the `/data/` directory (which I am trying to avoid, as I am not wanting to use a volume map for the whole `/data/` folder (nothing should change during runtime, once I get this straightened out).

This in part seems to be related to a new feature which automatically installs packages in NR 2.x or 3.x... but I am not certain I am understanding the distinction between the two paths (mentioned in title).

I am hoping to just need `flows.json` and `settings.js` need to be volume mapped onto the image into a running container.

---

<div class="post-metadata">

### Author: ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)
#### Post date: [17 July 2022 09:26 UTC](https://discourse.nodered.org/t/usr-src-node-red-node-modules-vs-data-node-modules-with-docker/65200/2 "2022-07-17T09:26:32Z")

</div>

> [@SewShulMeedeeUh](#):
>
> If Node-Red installs npm packages auto-magically into `/data/`, what is the point of a custom docker image as base image/layer?

Generally, I think that the `/data/` folder will be user accessible. The docker image will not be. So if you want to have custom nodes installed and don't want users of nr to be able to mess with them, that would be a good way.

---

<div class="post-metadata">

### Author: ![lu4t](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/lu4t/32/32276_2.png) [@lu4t](https://discourse.nodered.org/u/lu4t)
#### Post date: [17 July 2022 18:29 UTC](https://discourse.nodered.org/t/usr-src-node-red-node-modules-vs-data-node-modules-with-docker/65200/3 "2022-07-17T18:29:38Z")

</div>

long story short:  
`/usr/src/node-red` contains what they call "core modules"; these modules come as a bundle on the regular node-red installation. A base image is following also this pattern.  
While `/data/node-modules` is the standard path that will contain any module not included on the node-red standard installation. You can adjust this path on the settings.js, using the `userDir` key.

Now: can you use the `/usr/src/node-red` for installing "your" modules and build a custom image?, I guess you can... BUT, if you decide to take that path for whatever reason, it means you will have to go through this process every-time the node-red core team updates the base image.

In my humble opinion, the way it's designed is way more effective and manageable.

---

<div class="post-metadata">

### Author: ![SewShulMeedeeUh](https://avatars.discourse-cdn.com/v4/letter/s/f1d935/32.png) [@SewShulMeedeeUh](https://discourse.nodered.org/u/SewShulMeedeeUh)
#### Post date: [19 July 2022 00:45 UTC](https://discourse.nodered.org/t/usr-src-node-red-node-modules-vs-data-node-modules-with-docker/65200/4 "2022-07-19T00:45:28Z")

</div>

The challenge is, this will be used on systems with little/no connectivity. Relying on a local `/data/` volume mount seems less "portable" as well (including updates and changes in a build system is a relatively easy lift so I am much less concerned about that). Additionally, I have a local path that must be accessible to the flows (currently mapped to something like `/data/subdir`). I suppose I could map elsewhere (or make a location in a Dockerfile)?

The goal is to have an image with all the needed pieces "baked in" so to speak (such that, upon start, nothing further needs downloaded and is already present).

Maybe this will help explain the alternatives (as I understand them) and the challenges I am seeing with them...

## Inputs

> **docker-compose.yaml**
>
> ```auto
> services:
> 
> not-baked-in:
> container_name: not-baked-in
> image: nodered/node-red:3.0.0-16-minimal
> volumes:
> - ./:/data/
> ports:
> - "1880:1880" # web ui
> 
> baked-in-workdir:
> container_name: baked-in-workdir
> build:
> context: .
> dockerfile: Dockerfile.baked-in-workdir
> ports:
> - "1880:1880" # web ui
> 
> baked-in-userdir:
> container_name: baked-in-userdir
> build:
> context: .
> dockerfile: Dockerfile.baked-in-userdir
> ports:
> - "1880:1880" # web ui
> 
> ```

> **Dockerfile.baked-in-workdir**
>
> ```auto
> FROM nodered/node-red:3.0.0-16-minimal
> RUN npm i \
> node-red-debugger@1.1.1 \
> pg@8.6.0 \
> --unsafe-perm --no-update-notifier --no-fund --omit=dev
> 
> ```

> **Dockerfile.baked-in-userdir**
>
> ```auto
> FROM nodered/node-red:3.0.0-16-minimal
> RUN cd /data/
> COPY package.json flows.json settings.js ./
> RUN npm i \
> --unsafe-perm --no-update-notifier --no-fund --omit=dev
> 
> ```

> **package.json**
>
> ```auto
> {
> "name": "my-node-red",
> "version": "0.0.1",
> "dependencies": {
> "node-red-debugger": "1.1.1",
> "pg": "8.6.0"
> }
> }
> 
> ```

> **flows.json**
>
> `[{"id":"0219bb93a4e9f932","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"c3aaf3a15f27e455","type":"inject","z":"0219bb93a4e9f932","name":"init","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":90,"y":60,"wires":[["a2c53a9c97709bfc"]]},{"id":"a2c53a9c97709bfc","type":"function","z":"0219bb93a4e9f932","name":"try pg lib","func":"let PgPool = pg.Pool;\nlet pool = new PgPool();\n\npool.query(\"SELECT 'Test' as [TestMsg]\", (err, res) => {\n if (err) {\n msg.result = err;\n }\n \n msg.result = res.rows[0];\n})\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"pg","module":"pg@8.6.0"}],"x":240,"y":60,"wires":[["6fbe3d1f1df9f9da"]]},{"id":"6fbe3d1f1df9f9da","type":"debug","z":"0219bb93a4e9f932","name":"dbg","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":390,"y":60,"wires":[]}]`

> **settings.js**
>
> As per [original](https://github.com/node-red/node-red/blob/3.0.0/packages/node_modules/node-red/settings.js), except...
> 
> - [runtimeState.enabled](https://github.com/node-red/node-red/blob/1b94cc3ac027bfc38a300867a0b0fd635bf273b8/packages/node_modules/node-red/settings.js#L280) = true
> - [runtimeState.ui](https://github.com/node-red/node-red/blob/1b94cc3ac027bfc38a300867a0b0fd635bf273b8/packages/node_modules/node-red/settings.js#L282) = true

## Outputs

> **not-baked-in**
>
> `> docker compose up not-baked-in`
> 
> **TLDR/Results:**  
> no pg/lib install  
> no error message  
> flow debug installed  
> flow stop feature enabled  
> baked-in/portable image  
> inject output in debug panel
> 
> **Details:**
> 
> ```auto
> not-baked-in |
> not-baked-in | > node-red-docker@3.0.0 start
> not-baked-in | > node $NODE_OPTIONS node_modules/node-red/red.js $FLOWS "--userDir" "/data"
> not-baked-in |
> not-baked-in | 18 Jul 22:00:11 - [info]
> not-baked-in |
> not-baked-in | Welcome to Node-RED
> not-baked-in | ===================
> not-baked-in |
> not-baked-in | 18 Jul 22:00:11 - [info] Node-RED version: v3.0.0
> not-baked-in | 18 Jul 22:00:11 - [info] Node.js version: v16.16.0
> not-baked-in | 18 Jul 22:00:11 - [info] Linux 5.4.72-microsoft-standard-WSL2 x64 LE
> not-baked-in | 18 Jul 22:00:13 - [info] Loading palette nodes
> not-baked-in | 18 Jul 22:00:16 - [info] Settings file : /data/settings.js
> not-baked-in | 18 Jul 22:00:16 - [info] Context store : 'default' [module=memory]
> not-baked-in | 18 Jul 22:00:16 - [info] User directory : /data
> not-baked-in | 18 Jul 22:00:16 - [warn] Projects disabled : editorTheme.projects.enabled=false
> not-baked-in | 18 Jul 22:00:16 - [info] Flows file : /data/flows.json
> not-baked-in | 18 Jul 22:00:16 - [info] Server now running at http://127.0.0.1:1880/
> not-baked-in | 18 Jul 22:00:16 - [warn]
> not-baked-in |
> not-baked-in | ---------------------------------------------------------------------
> not-baked-in | Your flow credentials file is encrypted using a system-generated key.
> not-baked-in |
> not-baked-in | If the system-generated key is lost for any reason, your credentials
> not-baked-in | file will not be recoverable, you will have to delete it and re-enter
> not-baked-in | your credentials.
> not-baked-in |
> not-baked-in | You should set your own key using the 'credentialSecret' option in
> not-baked-in | your settings file. Node-RED will then re-encrypt your credentials
> not-baked-in | file using your chosen key the next time you deploy a change.
> not-baked-in | ---------------------------------------------------------------------
> not-baked-in |
> not-baked-in | 18 Jul 22:00:16 - [warn] Encrypted credentials not found
> not-baked-in | 18 Jul 22:00:16 - [info] Starting flows
> not-baked-in | 18 Jul 22:00:16 - [error] [function:a2c53a9c97709bfc] Error: Cannot find module 'pg@8.6.0'
> not-baked-in | Require stack:
> not-baked-in | - /data/node_modules/pg@8.6.0
> not-baked-in | 18 Jul 22:00:16 - [info] Started flows
> 
> ```
> 
> **Cleanup:** `> docker compose down not-baked-in`

> **baked-in-workdir**
>
> `> docker compose up baked-in-workdir`
> 
> **TLDR/Results:**  
> no pg/lib install  
> no error message  
> flow debug installed  
> flow stop feature enabled  
> baked-in/portable image  
> inject output in debug panel
> 
> **Details:**
> 
> ```auto
> baked-in-workdir |
> baked-in-workdir | > node-red-docker@3.0.0 start
> baked-in-workdir | > node $NODE_OPTIONS node_modules/node-red/red.js $FLOWS "--userDir" "/data"
> baked-in-workdir |
> baked-in-workdir | 18 Jul 22:44:38 - [info]
> baked-in-workdir |
> baked-in-workdir | Welcome to Node-RED
> baked-in-workdir | ===================
> baked-in-workdir |
> baked-in-workdir | 18 Jul 22:44:38 - [info] Node-RED version: v3.0.0
> baked-in-workdir | 18 Jul 22:44:38 - [info] Node.js version: v16.16.0
> baked-in-workdir | 18 Jul 22:44:38 - [info] Linux 5.4.72-microsoft-standard-WSL2 x64 LE
> baked-in-workdir | 18 Jul 22:44:40 - [info] Loading palette nodes
> baked-in-workdir | 18 Jul 22:44:42 - [info] Settings file : /data/settings.js
> baked-in-workdir | 18 Jul 22:44:42 - [info] Context store : 'default' [module=memory]
> baked-in-workdir | 18 Jul 22:44:42 - [info] User directory : /data
> baked-in-workdir | 18 Jul 22:44:42 - [warn] Projects disabled : editorTheme.projects.enabled=false
> baked-in-workdir | 18 Jul 22:44:42 - [info] Flows file : /data/flows.json
> baked-in-workdir | 18 Jul 22:44:42 - [warn]
> baked-in-workdir |
> baked-in-workdir | ---------------------------------------------------------------------
> baked-in-workdir | Your flow credentials file is encrypted using a system-generated key.
> baked-in-workdir |
> baked-in-workdir | If the system-generated key is lost for any reason, your credentials
> baked-in-workdir | file will not be recoverable, you will have to delete it and re-enter
> baked-in-workdir | your credentials.
> baked-in-workdir |
> baked-in-workdir | You should set your own key using the 'credentialSecret' option in
> baked-in-workdir | your settings file. Node-RED will then re-encrypt your credentials
> baked-in-workdir | file using your chosen key the next time you deploy a change.
> baked-in-workdir | ---------------------------------------------------------------------
> baked-in-workdir |
> baked-in-workdir | 18 Jul 22:44:42 - [info] Server now running at http://127.0.0.1:1880/
> baked-in-workdir | 18 Jul 22:44:42 - [warn] Encrypted credentials not found
> baked-in-workdir | 18 Jul 22:44:42 - [info] Installing module: pg, version: 8.6.0
> baked-in-workdir | 18 Jul 22:44:49 - [info] Installed module: pg@8.6.0
> baked-in-workdir | 18 Jul 22:44:49 - [info] Starting flows
> baked-in-workdir | 18 Jul 22:44:49 - [error] [function:a2c53a9c97709bfc] Error: Cannot find module 'pg@8.6.0'
> baked-in-workdir | Require stack:
> baked-in-workdir | - /data/node_modules/pg@8.6.0
> baked-in-workdir | 18 Jul 22:44:49 - [info] Started flows
> 
> ```
> 
> **Note:** despite "installed" message, and lib being in both workDir and userDir, a "Cannot find" error is returned
> 
> ```auto
> > docker exec -it baked-in-workdir sh
> ~ $ pwd
> /usr/src/node-red
> ~ $ npm ls --depth=0
> node-red-docker@3.0.0 /usr/src/node-red
> +-- node-red-debugger@1.1.1
> +-- node-red@3.0.0
> `-- pg@8.6.0
> 
> ~ $ cd /data
> /data $ npm ls --depth=0
> node-red-project@0.0.1 /data
> `-- pg@8.6.0
> 
> ```
> 
> **Cleanup:** `> docker compose down baked-in-workdir`

> **baked-in-userdir**
>
> `> docker compose up baked-in-userdir`
> 
> **TLDR/Results:**  
> no pg/lib install  
> no error message  
> flow debug installed  
> flow stop feature enabled  
> baked-in/portable image  
> inject output in debug panel
> 
> **Details:**
> 
> ```auto
> aked-in-userdir | npm ERR! Missing script: "start"
> baked-in-userdir | npm ERR!
> baked-in-userdir | npm ERR! Did you mean one of these?
> baked-in-userdir | npm ERR! npm star # Mark your favorite packages
> baked-in-userdir | npm ERR! npm stars # View packages marked as favorites
> baked-in-userdir | npm ERR!
> baked-in-userdir | npm ERR! To see a list of scripts, run:
> baked-in-userdir | npm ERR! npm run
> baked-in-userdir |
> baked-in-userdir | npm ERR! A complete log of this run can be found in:
> baked-in-userdir | npm ERR! /data/.npm/_logs/2022-07-18T22_55_00_980Z-debug-0.log
> baked-in-userdir exited with code 1
> 
> ```
> 
> **Cleanup:** `> docker compose down baked-in-userdir`

I imagine if I added `node-red@3.0.0` to the `package.json` to the `baked-in-userdir` service, it would work... but then why use `FROM nodered/node-red:3.0.0-16-minimal` in dockerfile/etc? Changing [functionExternalModules](https://github.com/node-red/node-red/blob/1b94cc3ac027bfc38a300867a0b0fd635bf273b8/packages/node_modules/node-red/settings.js#L455) to `false` might prevent installation of packages, but it is unclear why it thinks it needs to install them to begin with?

What am I missing?

**PS:** [functionExternalModules](https://github.com/node-red/node-red/blob/1b94cc3ac027bfc38a300867a0b0fd635bf273b8/packages/node_modules/node-red/settings.js#L455) `= false` for `baked-in-workdir` gives...

> 19 Jul 02:01:31 - [error] [function:7313a330f49cc770] Error: Function node not allowed to load external modules

---

<div class="post-metadata">

### Author: ![SewShulMeedeeUh](https://avatars.discourse-cdn.com/v4/letter/s/f1d935/32.png) [@SewShulMeedeeUh](https://discourse.nodered.org/u/SewShulMeedeeUh)
#### Post date: [19 July 2022 00:47 UTC](https://discourse.nodered.org/t/usr-src-node-red-node-modules-vs-data-node-modules-with-docker/65200/5 "2022-07-19T00:47:52Z")

</div>

The warning I got from the system when I tried posting my first draft... 😆

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/d/b/db6cd5f6f33ac1a04a71097ac2f92898a0da402a.png)

Thank goodness I found the source for `settings.js` to link to

---

<div class="post-metadata">

### Author: ![SewShulMeedeeUh](https://avatars.discourse-cdn.com/v4/letter/s/f1d935/32.png) [@SewShulMeedeeUh](https://discourse.nodered.org/u/SewShulMeedeeUh)
#### Post date: [20 July 2022 06:33 UTC](https://discourse.nodered.org/t/usr-src-node-red-node-modules-vs-data-node-modules-with-docker/65200/6 "2022-07-20T06:33:38Z")

</div>

[Using](https://github.com/node-red/node-red-docker/tree/v3.0.0/docker-custom) the [docker-alpine.sh](https://github.com/node-red/node-red-docker/blob/v3.0.0/docker-custom/docker-alpine.sh) script, which [puts the package.json](https://github.com/node-red/node-red-docker/blob/33a03c513bd543d4016d667ab29501c3eda45018/docker-custom/Dockerfile.custom#L39) in [workDir](https://github.com/node-red/node-red-docker/blob/33a03c513bd543d4016d667ab29501c3eda45018/docker-custom/Dockerfile.custom#L32) and `flows.json` [in](https://github.com/node-red/node-red-docker/blob/33a03c513bd543d4016d667ab29501c3eda45018/docker-custom/Dockerfile.custom#L40) `userDir`, and then `docker run -it --rm -p 1880:1880 --name nr30 testing:node-red-build`

no pg/lib install  
 no error message  
 flow debug installed  
 flow stop feature enabled  
 baked-in/portable image  
 inject output in debug panel

`> docker exec -it nr30 sh` does show that the packages matching the `package.json` expected are in the `workDir/node_modules` path. There are also the same (and a number more) packages in the `userDir/node_modules` path. Why does it install them again, what is the point of installing them via the `package.json` beforehand?

I did notice (which makes sense) that the `package.json` copied into the `workDir` must include the `start` script as per the [docs](https://github.com/node-red/node-red-docker/wiki/Quick-Custom-Image).

---

<div class="post-metadata">

### Author: ![SewShulMeedeeUh](https://avatars.discourse-cdn.com/v4/letter/s/f1d935/32.png) [@SewShulMeedeeUh](https://discourse.nodered.org/u/SewShulMeedeeUh)
#### Post date: [22 July 2022 21:10 UTC](https://discourse.nodered.org/t/usr-src-node-red-node-modules-vs-data-node-modules-with-docker/65200/7 "2022-07-22T21:10:05Z")

</div>

With a minor adaptation I think I can use [the example in getting-started/docker](https://nodered.org/docs/getting-started/docker#dockerfile-which-copies-in-local-resources)

---

<div class="post-metadata">

### Author: ![SewShulMeedeeUh](https://avatars.discourse-cdn.com/v4/letter/s/f1d935/32.png) [@SewShulMeedeeUh](https://discourse.nodered.org/u/SewShulMeedeeUh)
#### Post date: [24 July 2022 04:05 UTC](https://discourse.nodered.org/t/usr-src-node-red-node-modules-vs-data-node-modules-with-docker/65200/8 "2022-07-24T04:05:29Z")

</div>

Hmm... no luck with the getting-started guide, as follows...

# Inputs

> **docker-compose.yaml**
>
> ```auto
> services:
> getting-started:
> container_name: getting-started
> build:
> context: .
> dockerfile: Dockerfile.getting-started
> ports:
> - "1880:1880"
> 
> ```

> **Dockerfile.getting-started**
>
> Should closely resemble the [example from docs](https://nodered.org/docs/getting-started/docker#dockerfile-which-copies-in-local-resources). There was no discernible difference in error messages if file copies were `CHOWNd` or not (all it accomplishes currently is changes group from `root` to `node-red` for things copied in, vs unmodified).
> 
> ```auto
> FROM nodered/node-red:3.0.0-16-minimal
> COPY --chown=node-red:node-red package.full.json ./package.json
> RUN npm install --unsafe-perm --no-update-notifier --no-fund --omit=dev
> COPY --chown=node-red:node-red flows.json settings.js /data/
> 
> ```

> **package.full.json**
>
> Includes node-red itself (otherwise it gets removed during `npm install`), and the default start script
> 
> ```auto
> {
> "name": "node-red-project",
> "description": "A Node-RED Project",
> "version": "0.0.1",
> "private": true,
> "dependencies": {
> "node-red": "3.0.0",
> "node-red-debugger": "1.1.1",
> "pg": "8.6.0"
> },
> "scripts": {
> "start": "node $NODE_OPTIONS node_modules/node-red/red.js $FLOWS"
> }
> }
> 
> ```

> **flows.json**
>
> `[{"id":"0219bb93a4e9f932","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"c3aaf3a15f27e455","type":"inject","z":"0219bb93a4e9f932","name":"init","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":90,"y":60,"wires":[["a2c53a9c97709bfc"]]},{"id":"a2c53a9c97709bfc","type":"function","z":"0219bb93a4e9f932","name":"try pg lib","func":"try {\nlet PgPool = pg.Pool;\nlet pool = new PgPool();\n\npool.query(\"SELECT 'Test' as [TestMsg]\", (err, res) => {\n if (err) {\n msg.result = err;\n }\n \n msg.result = res.rows[0];\n})\n} catch (ex) {\n return msg.ex = ex;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"pg","module":"pg@8.6.0"}],"x":240,"y":60,"wires":[["6fbe3d1f1df9f9da"]]},{"id":"6fbe3d1f1df9f9da","type":"debug","z":"0219bb93a4e9f932","name":"dbg","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":390,"y":60,"wires":[]}]`

> **settings.js**
>
> As per [original](https://github.com/node-red/node-red/blob/3.0.0/packages/node_modules/node-red/settings.js), except...
> 
> - [runtimeState.enabled](https://github.com/node-red/node-red/blob/1b94cc3ac027bfc38a300867a0b0fd635bf273b8/packages/node_modules/node-red/settings.js#L280) = true
> - [runtimeState.ui](https://github.com/node-red/node-red/blob/1b94cc3ac027bfc38a300867a0b0fd635bf273b8/packages/node_modules/node-red/settings.js#L282) = true

# Outputs

**TLDR/Results:**  
 no pg/lib install  
 no error message  
 flow debug installed  
 flow stop feature enabled  
 baked-in/portable image  
 inject output in debug panel

**Details:**

`docker compose up getting-started`

> **log**
>
> > getting-started |  
> > getting-started | \> node-red-project@0.0.1 start  
> > getting-started | \> node $NODE\_OPTIONS node\_modules/node-red/red.js $FLOWS "--userDir" "/data"  
> > getting-started |  
> > getting-started | 24 Jul 03:47:00 - [info]  
> > getting-started |  
> > getting-started | Welcome to Node-RED  
> > getting-started | ===================  
> > getting-started |  
> > getting-started | 24 Jul 03:47:00 - [info] Node-RED version: v3.0.0  
> > getting-started | 24 Jul 03:47:00 - [info] Node.js version: v16.16.0  
> > getting-started | 24 Jul 03:47:00 - [info] Linux 5.4.72-microsoft-standard-WSL2 x64 LE  
> > getting-started | 24 Jul 03:47:02 - [info] Loading palette nodes  
> > getting-started | 24 Jul 03:47:04 - [info] Settings file : /data/settings.js  
> > getting-started | 24 Jul 03:47:04 - [info] Context store : 'default' [module=memory]  
> > getting-started | 24 Jul 03:47:04 - [info] User directory : /data  
> > getting-started | 24 Jul 03:47:04 - [warn] Projects disabled : editorTheme.projects.enabled=false  
> > getting-started | 24 Jul 03:47:04 - [info] Flows file : /data/flows.json  
> > getting-started | 24 Jul 03:47:05 - [warn]  
> > getting-started |  
> > getting-started | ---------------------------------------------------------------------  
> > getting-started | Your flow credentials file is encrypted using a system-generated key.  
> > getting-started |  
> > getting-started | If the system-generated key is lost for any reason, your credentials  
> > getting-started | file will not be recoverable, you will have to delete it and re-enter  
> > getting-started | your credentials.  
> > getting-started |  
> > getting-started | You should set your own key using the 'credentialSecret' option in  
> > getting-started | your settings file. Node-RED will then re-encrypt your credentials  
> > getting-started | file using your chosen key the next time you deploy a change.  
> > getting-started | ---------------------------------------------------------------------  
> > getting-started |  
> > getting-started | 24 Jul 03:47:05 - [info] Server now running at [http://127.0.0.1:1880/](http://127.0.0.1:1880/)  
> > getting-started | 24 Jul 03:47:05 - [warn] Encrypted credentials not found  
> > getting-started | 24 Jul 03:47:05 - [info] Installing module: pg, version: 8.6.0  
> > getting-started | 24 Jul 03:47:11 - [info] Installed module: pg@8.6.0  
> > getting-started | 24 Jul 03:47:11 - [info] Starting flows  
> > getting-started | 24 Jul 03:47:11 - [error] [function:a2c53a9c97709bfc] Error: Cannot find module 'pg@8.6.0'  
> > getting-started | Require stack:  
> > getting-started | - /data/node\_modules/pg@8.6.0  
> > getting-started | 24 Jul 03:47:11 - [info] Started flows

Maybe at this point a bug report of some sort would be appropriate?

---

<div class="post-metadata">

### Author: ![UnborN](https://avatars.discourse-cdn.com/v4/letter/u/4491bb/32.png) [@UnborN](https://discourse.nodered.org/u/UnborN)
#### Post date: [24 July 2022 11:05 UTC](https://discourse.nodered.org/t/usr-src-node-red-node-modules-vs-data-node-modules-with-docker/65200/9 "2022-07-24T11:05:27Z")

</div>

> [@SewShulMeedeeUh](#):
>
> getting-started | 24 Jul 03:47:11 - [error] [function:a2c53a9c97709bfc] Error: Cannot find module 'pg@8.6.0'

I have to start by saying that my docker skills are not so advanced like what you are trying to do.  
As a workaround try using the **functionGlobalContext** instead

```auto
 functionGlobalContext: {
         pg:require('pg'),
    },

```

and set `functionExternalModules: false,` in your settings.js (as you had at some point)

also re-adjust your flow to not use `functionExternalModules` but `let pg = global.get("pg")`

> **flow.json**
>
> ```auto
> [
> {
> "id": "c3aaf3a15f27e455",
> "type": "inject",
> "z": "0defad76537bdd90",
> "name": "init",
> "props": [
> {
> "p": "payload"
> }
> ],
> "repeat": "",
> "crontab": "",
> "once": false,
> "onceDelay": 0.1,
> "topic": "",
> "payload": "",
> "payloadType": "date",
> "x": 370,
> "y": 120,
> "wires": [
> [
> "a2c53a9c97709bfc"
> ]
> ]
> },
> {
> "id": "a2c53a9c97709bfc",
> "type": "function",
> "z": "0defad76537bdd90",
> "name": "try pg lib",
> "func": "let pg = global.get(\"pg\")\nnode.warn(pg)\n\n// try {\n// let PgPool = pg.Pool;\n// let pool = new PgPool();\n\n// pool.query(\"SELECT 'Test' as [TestMsg]\", (err, res) => {\n// if (err) {\n// msg.result = err;\n// }\n \n// msg.result = res.rows[0];\n// })\n// } catch (ex) {\n// return msg.ex = ex;\n// }",
> "outputs": 1,
> "noerr": 0,
> "initialize": "",
> "finalize": "",
> "libs": [],
> "x": 520,
> "y": 120,
> "wires": [
> [
> "6fbe3d1f1df9f9da"
> ]
> ]
> },
> {
> "id": "6fbe3d1f1df9f9da",
> "type": "debug",
> "z": "0defad76537bdd90",
> "name": "dbg",
> "active": true,
> "tosidebar": true,
> "console": false,
> "tostatus": false,
> "complete": "true",
> "targetType": "full",
> "statusVal": "",
> "statusType": "auto",
> "x": 710,
> "y": 120,
> "wires": []
> }
> ]
> 
> ```

---

<div class="post-metadata">

### Author: ![SewShulMeedeeUh](https://avatars.discourse-cdn.com/v4/letter/s/f1d935/32.png) [@SewShulMeedeeUh](https://discourse.nodered.org/u/SewShulMeedeeUh)
#### Post date: [25 July 2022 22:39 UTC](https://discourse.nodered.org/t/usr-src-node-red-node-modules-vs-data-node-modules-with-docker/65200/10 "2022-07-25T22:39:12Z")

</div>

Thank you so much!

I thought with the newer versions of Node-RED the `functionGlobalContext` was deprecated (or marked for it?)... but reverting `settings.js`, [functionExternalModules](https://github.com/node-red/node-red/blob/1b94cc3ac027bfc38a300867a0b0fd635bf273b8/packages/node_modules/node-red/settings.js#L455) and [functionGlobalContext](https://github.com/node-red/node-red/blob/1b94cc3ac027bfc38a300867a0b0fd635bf273b8/packages/node_modules/node-red/settings.js#L464) certainly addressed the libraries being installed and the error message about being unable to find them anyway.

I am still getting some unexpected behavior, but I think it is related to my current use/config of the Postgres client library (`pg'). I'll keep poking.

Updated flows.json...

```auto
[{"id":"0219bb93a4e9f932","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"c3aaf3a15f27e455","type":"inject","z":"0219bb93a4e9f932","name":"init","props":[{"p":"ts","v":"","vt":"date"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":90,"y":60,"wires":[["a2c53a9c97709bfc"]]},{"id":"a2c53a9c97709bfc","type":"function","z":"0219bb93a4e9f932","name":"try pg lib","func":"try {\n let pg = global.get(\"pg\");\n let PgPool = pg.Pool;\n let pool = new PgPool();\n msg.pool = pool; // debug\n\n pool.query(\"SELECT 'Test' as [TestMsg]\", (err, res) => {\n if (err) {\n msg.result = err;\n } else {\n msg.result = res;\n }\n })\n} catch (ex) {\n msg.ex = ex;\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":240,"y":60,"wires":[["6fbe3d1f1df9f9da"]]},{"id":"6fbe3d1f1df9f9da","type":"debug","z":"0219bb93a4e9f932","name":"dbg","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":390,"y":60,"wires":[]}]

```

---

<div class="post-metadata">

### Author: ![UnborN](https://avatars.discourse-cdn.com/v4/letter/u/4491bb/32.png) [@UnborN](https://discourse.nodered.org/u/UnborN)
#### Post date: [25 July 2022 23:09 UTC](https://discourse.nodered.org/t/usr-src-node-red-node-modules-vs-data-node-modules-with-docker/65200/11 "2022-07-25T23:09:57Z")

</div>

cool .. im glad it worked

> [@SewShulMeedeeUh](#):
>
> I am still getting some unexpected behavior, but I think it is related to my current use/config of the Postgres client library (`pg'). I'll keep poking.

yea .. i noticed some errors too when running the Function with pg library .. but the main thing is that it loads.

Why dont you pre-install a postgres node instead of using the pg library ? .. we are in Nodered after all 😉

---

<div class="post-metadata">

### Author: ![SewShulMeedeeUh](https://avatars.discourse-cdn.com/v4/letter/s/f1d935/32.png) [@SewShulMeedeeUh](https://discourse.nodered.org/u/SewShulMeedeeUh)
#### Post date: [25 July 2022 23:57 UTC](https://discourse.nodered.org/t/usr-src-node-red-node-modules-vs-data-node-modules-with-docker/65200/12 "2022-07-25T23:57:15Z")

</div>

> [@UnborN](#):
>
> Why dont you pre-install a postgres node instead of using the pg library ? .. we are in Nodered after all 😉

An excellent question 😀 ...I evaluated the options once upon a time, and I dont recall now what the reasoning was for going this route (some feature gap at the time, IIRC). I'll look into it again.

---

<div class="post-metadata">

### Author: ![SewShulMeedeeUh](https://avatars.discourse-cdn.com/v4/letter/s/f1d935/32.png) [@SewShulMeedeeUh](https://discourse.nodered.org/u/SewShulMeedeeUh)
#### Post date: [1 August 2022 08:51 UTC](https://discourse.nodered.org/t/usr-src-node-red-node-modules-vs-data-node-modules-with-docker/65200/13 "2022-08-01T08:51:04Z")

</div>

FWIW, the winning combo for me was...

- `FROM nodered/node-red:3.0.1-16-minimal`
- copy a package.json that included a dependency for node-red itself (and debugger) in the `workDir` ('/usr/src/node-red`), and run `npm install` from there.
- `package.json` (in `workDir`) and `flows.json` and `settings.js` (in `userDir`, aka: `/data/`) "baked in"
- [externalModules](https://github.com/node-red/node-red/blob/master/packages/node_modules/node-red/settings.js#L334) default/commented-out
- [functionExternalModules](https://github.com/node-red/node-red/blob/dc7fef63952548277d7759c327ce2909fdce0a3c/packages/node_modules/node-red/settings.js#L455) false
- added one lib to [functionGlobalContext](https://github.com/node-red/node-red/blob/dc7fef63952548277d7759c327ce2909fdce0a3c/packages/node_modules/node-red/settings.js#L464)
- [runtimeState](https://github.com/node-red/node-red/blob/dc7fef63952548277d7759c327ce2909fdce0a3c/packages/node_modules/node-red/settings.js#L278) enabled
- created my own `/organization/settings` (with proper permissions) for the data I do need to volume map into and read from in my flows (from a known location). this way it doesnt interfere with the expected contents of /data

---

<div class="post-metadata">

### Author: ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)
#### Post date: [15 August 2022 08:51 UTC](https://discourse.nodered.org/t/usr-src-node-red-node-modules-vs-data-node-modules-with-docker/65200/14 "2022-08-15T08:51:39Z")

</div>

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.
