Modbus Server with node-red Docker - Port forwarding required?

I've got a Modbus TCP server running in node-red, which is running via Docker. Unfortunately, this server is unreachable, so I'm thinking it needs port forwarding to outside the Docker container - can anyone confirm this?

I also have other issues (see also) with the Modbus server, so any help or advice is appreciated! Thank you!

It will depend on the network model used for the container (Networking overview | Docker Docs) and where the modbus-tcp client is located on the network/infrastructure, whether you will need some additional actions in order to enable client & server connect.
As you already can access the Node-Red Docker Container while running, networking as such is working.
To overcome the need for separate port-mapping in the Container, I suggest to use either ipvlan or macvlan networking model, giving the Docker a static IP in the connected network range.
However, if the container will then be reachable from outside of that ip-adress range from that network lies outside of the docker configuration and you might need to adjust rules in your firewall/router.

1 Like

Wouldn't mapping another port like -p 1880:1880 -p 10502:10502 be enough?
I'm currently trying to follow this info to add the port without recreating the container.

Both ipvlan and macvlan look a bit overly complicated...?

Port 1880 ist the default for Node-red Dashbord-UI...when the other mapping is not in use, depending on the network model (like when host-model is used, all containers are using the Host-IP of the machine where the docker engine runs on and hence all port mappings must not overlap, including services on the host itself), then yes, this can work.

Nevertheless, it also depends in which network the modbus-tcp clients resides.
When in the same network as the Docker Host, then this should suffice. When in different sites, networks, IP-segments or VLANs, other actions need to be taken as well.

That depends on the platform/tools you have in use to fetch Dockers and manage Containers.
I am using a NAS with native Docker support (and all network models are build into the docker engine), where switching between network models is an easy config step for each Container instance. I can also confirm, that this works for the standard Node-Red Docker out of the box.
Another, similar tool is portainer.io, which can also be deployed locally.

Edit: linking the Portainer Community Edition as Docker, here

1 Like

Thank you very much for your advice!

I'm running node-red docker on more or less bare metal; ended up running a new container (docker doesn't really support adding ports to existing containers), and found that the node-red data was shared between the containers, so quite happy I didn't need to fully recreate it.

The network model is a self-hosted VPN placing the Docker host on the same VLAN as my client, so the simple port configuration seems to work (though currently still reading zeroes instead of data, need to figure out how to specify holding registers)

A container is the active instance of a Docker(-Image), like a tiny Virtual-Machine, only containing/running a single App and not a full OS). You can start/run many containers from the same Docker-Image concurrently. In order to change settings/parameters for a container, you normally would need to stop tht instance, then adjust the "run" parameters, like adding port-mappings, and then (re-)start it.

As said, using portainer might help managing that with a nice web-UI, when running many dockers.

glad it works for you now. The other problem is a matter on how to setup the config for the specific modbus-RTU on the other side, I believe. Cannot help you with that, I am afraid.
Best would be to open another specific topic for that, wouldn't it.

1 Like

Just a quick note for posterity:

Docker only supports adjusting ports when using the run and create commands; unfortunately, I had to use docker start for the already created container. The only way to adjust the ports is to edit /var/lib/docker/containers/[hash_of_the_container]/hostconfig.json (didn't work for me), or make a new container and access the same data partition (what I did in the end).

I'll link back here if/when I've opened a new topic to solve the issues with modbus TCP sending apparent garbage (despite displaying correct broadcast data within the node-red instance).

Many thanks for the assistance, @hominidae

Here's the link: Modbus TCP previews correct output, but receiving end gets garbage

If you want to more easily update configuration of containers you can use docker-compose. It accepts configuration in a yml file and allows you to keep and edit your configuration.

An example of a node-red docker-compose file:

---
version: "2.1"
services:
  nodered:
    network_mode: lsio #self created network in docker with docker network create
    image: nodered/node-red:latest
    container_name: nodered
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Amsterdam
    volumes:
      - /media/dockervolumes/nodered/noderedData:/data
    ports:
      - 1880:1880
    restart: unless-stopped

You can create the container using the docker-compose up command

3 Likes

That looks like a really good idea! I've found this further example - wondering, do you know of any good tutorials or forum threads that go over docker compose for node-red?

If you forget the application building part then this might be interesting (start at step 5)

In my example, the volume points to a location where the nodered data is stored, so it survives destroying and re-creating a container. The network you can set to host to keep things simple. I think that should be enough to get you started.

Modbus TCP garbage was single-number arrays getting broadcast to modbus rather than just numbers, e.g.

{"value": 0: 12345,"register":"holding","address":8,"disableMsgOutput":0}

rather than the desired

{"value": 12345,"register":"holding","address":8,"disableMsgOutput":0}

I picked out the values from those weird little arrays via:

var temp1 = msg.payload[0]

msg.payload = {
   'value': temp1,
   'register': 'holding',
   'address': 2,
   'disableMsgOutput': 0
};

return msg;

My colleague is still getting dynamic byte swapping, but I at least am reading back expected numbers now.

Lesson: beware of single-number arrays.

2 Likes

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