node-red / node-red-docker

Repository for all things Node-RED and Docker related

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

can not pass through /dev/tty* to docker image

spants opened this issue · comments

using --device=/dev/ttyACM0 on docker commandline....
the "serial in" node cannot connect due to Permisson error - from the log in th edocker:

[error] serial port /dev/ttyACM0 error: Error: Error: Permission denied, cannot open /dev/ttyACM0

It may be due to user node-red not having access to /dev/
I have tried editing the Dockerfile to remove USER node-red (to run Node-Red as root but serial then produces these errors (on LATEST docker - not RPI):

[warn] [serialport] Error: Could not locate the bindings file. Tried:
→ /usr/src/node-red/node_modules/node-red/node_modules/node-red-node-serialport/node_modules/serialport/build/serialport.node
→ /usr/src/node-red/node_modules/node-red/node_modules/node-red-node-serialport/node_modules/serialport/build/Debug/serialport.node
→ /usr/src/node-red/node_modules/node-red/node_modules/node-red-node-serialport/node_modules/serialport/build/Release/serialport.node
→ /usr/src/node-red/node_modules/node-red/node_modules/node-red-node-serialport/node_modules/serialport/out/Debug/serialport.node
→ /usr/src/node-red/node_modules/node-red/node_modules/node-red-node-serialport/node_modules/serialport/Debug/serialport.node
→ /usr/src/node-red/node_modules/node-red/node_modules/node-red-node-serialport/node_modules/serialport/out/Release/serialport.node
→ /usr/src/node-red/node_modules/node-red/node_modules/node-red-node-serialport/node_modules/serialport/Release/serialport.node
→ /usr/src/node-red/node_modules/node-red/node_modules/node-red-node-serialport/node_modules/serialport/build/default/serialport.node
→ /usr/src/node-red/node_modules/node-red/node_modules/node-red-node-serialport/node_modules/serialport/compiled/4.6.0/linux/x64/serialport.node

Any idea how I can get a serial pass through to work on the official Docker image (it works on my unofficial version)

Thanks for reporting this. If you could me with the following information, it'll help me investigate.

Can you tell me exactly what platform you are running on?
What Docker command you're using to start it?
What's the output of ls -l /dev/ttyACM0?
What user are you running as on the host system, i.e. that user running the docker command?

Thanks for looking into it. I was talk with DCJ via email but it is probably best to do it here...
I am using unRAID https://lime-technology.com/application-server/ which is a linux storage server which has built in support for Docker. The version of docker it supports is currently 1.10.3.

The command that I use is:-
docker run -d --name="NodeRed-OfficialDocker" --net="host" -e TZ="Europe/London" -e HOST_OS="unRAID" -e "TCP_PORT_1880"="1880" -e "TCP_PORT_55000-55010"="55000-55010" -v "/mnt/user/appdata/nodered-official/":"/data":rw --device=/dev/ttyACM0:/dev/ttyACM0 nodered/node-red-docker

I have a usb-serial interface on ttyACM0 (ciseco/wireless things adapter).

I can see that the port is passed through to docker:
'docker exec NodeRed-OfficialDocker ls /dev/ttyA*' shows:
/dev/ttyACM0

The docker containers are started as root.

(The errors shown in my first post are logs from inside the container, not the host)

Some time ago I built a docker for Node Red, this one works well (currently v0.14.6):
https://hub.docker.com/r/spants/nodered/

  • but it runs Node Red as root inside the container. If I try to do the same by removing the USER command for the official docker, I get the errors shown in original post.

Wondering if it is the combination of USER not root and support for serial in Alpine linux base docker?

Thanks for the above information, I'll dig into this over the next week and get back to you.

Can you do a ls -l on the /dev/ttyACM0 on BOTH the host and inside the container?

root@Tower:# ls -l /dev/ttyACM0
crw-rw---- 1 root dialout 166, 0 Oct 14 18:12 /dev/ttyACM0
root@Tower:
# docker exec NodeRed-OfficialDocker ls -l /dev/ttyACM0
crw-rw---- 1 root 16 166, 0 Oct 16 19:04 /dev/ttyACM0
root@Tower:~#

Re-reading the first comment, we can fix the "user not running as root" issue using the "--user" command-line flag which leads us to the second issue...

Where are those binding files? The mystery continues...

Looking at the Travis build logs, I can see that the bindings files are installed to here:
/usr/src/node-red/node_modules/node-red/node_modules/node-red-node-serialport/node_modules/serialport/build/Release/serialport.node

Can you check this file is available inside the container?
I see the logs are saying it's not there but I can see it in my instance locally.

seems to be there!
root@Tower:# docker exec NodeRed-OfficialDocker ls -l /usr/src/node-red/node_modules/node-red/node_modules/node-red-node-serialport/node_modules/serialport/build/Release/serialport.node
-rwxrwxr-x 1 node-red node-red 69228 May 15 02:24 /usr/src/node-red/node_modules/node-red/node_modules/node-red-node-serialport/node_modules/serialport/build/Release/serialport.node
root@Tower:
#

How do I use the --user flag?

It looks like the "user not running as root" also has to be in the "dialout" group to give it access to the tty.

agree, I think node-red user needs to be in the dialout group. I couldnt add it in the running docker, so I tried a rebuild with nodered starting as root. I then had the problem with serialport.node not found. Maybe there is a specific version for alpine linux (that the docker is built from)?

Notes from DCJ
"serial ports are often access by a group called dialout - so maybe we can add the user to that group
usermod -a -G dialout MY_USER_NAME

or maybe do the udev rules thing... - (not sure how to do that inside docker)

"You could use UDEV. It's a system that triggers every time plug or unplug a device (amongst other stuff). With it, you script various things to happen, including setting permissions.
Run sudoedit /etc/udev/rules.d/50-ttyusb.rules and stick this in there:
KERNEL=="ttyUSB[0-9]*",NAME="tts/USB%n",SYMLINK+="%k",GROUP="uucp",MODE="0666"

Save, exit and replug and you should be up and running. Setting the permission to 666 allows anybody to write to the device.
I'm basing this off this page which is from a few years ago but something like this should work if Jeremy's solution doesn't."

Copied for reference ......
The problem is that I couldn't sudo usermod inside the docker....

can you add RUN usermod -a -G dialout node-red
somewhere around line 15 of the Dockerfile ?
IE after the USER has been added but before we switch to it ?

Dave, that didnt work:

  • edited Dockerfile to add just before USER node-red
  • built docker:
    Sending build context to Docker daemon 145.9 kB

Step 1 : FROM node:4
---> e8428963b85a
Step 2 : RUN mkdir -p /usr/src/node-red
---> Running in bdd910de5012
---> d1c7a73b08f3
Removing intermediate container bdd910de5012
Step 3 : RUN mkdir /data
---> Running in f3148a856b32
---> ed691590fe91
Removing intermediate container f3148a856b32
Step 4 : WORKDIR /usr/src/node-red
---> Running in 47468ace7c48
---> 52e1e6c43bc1
Removing intermediate container 47468ace7c48
Step 5 : RUN useradd --home-dir /usr/src/node-red --no-create-home node-red && chown -R node-red:node-red /data && chown -R node-red:node-red /usr/src/node-red
---> Running in c557bd2f7e97
---> 6a5e74ec54dd
Removing intermediate container c557bd2f7e97
Step 6 : RUN usermod -a -G dialout node-red
---> Running in d5c47b102daf
---> e49f98ba1900
Removing intermediate container d5c47b102daf
Step 7 : USER node-red
---> Running in a9eaaeacc1ec
---> fac6a4df2d55
Removing intermediate container a9eaaeacc1ec
Step 8 : COPY package.json /usr/src/node-red/
---> 35ca220a3804
Removing intermediate container ae0d6f15977a
Step 9 : RUN npm install
---> Running in 4a14ca300a9c
----- snip -----

docker built ok but got the same:
[error] serial port /dev/ttyACM0 error: Error: Error: Permission denied, cannot open /dev/ttyACM0

docker exec nodered ls -l /dev/ttyACM0

crw-rw---- 1 root 16 166, 0 Oct 17 22:01 /dev/ttyACM0

ls -l /dev/ttyACM0

crw-rw---- 1 root dialout 166, 0 Oct 16 23:06 /dev/ttyACM0

Can you also check if node-red user did get added to the group ?
(Alternative is to add -G dialogue to the add user line (just before node-red))

this was my dockerfile:
FROM node:4

Home directory for Node-RED application source code.

RUN mkdir -p /usr/src/node-red

User data directory, contains flows, config and nodes.

RUN mkdir /data

WORKDIR /usr/src/node-red

Add node-red user so we aren't running as root.

RUN useradd --home-dir /usr/src/node-red --no-create-home node-red
&& chown -R node-red:node-red /data
&& chown -R node-red:node-red /usr/src/node-red

RUN usermod -a -G dialout node-red

USER node-red
----snip----

Interestingly:
#docker exec nodered getent group dialout
dialout:x:20:node-red

dialout : x : 20 : node-red

spaces added to stop auto emoji thingy

It works!... Using the following as parameters... Thanks Team - I can now update the template for the Node Red users on unRaid.

--device=/dev/ttyACM0 --user=root

🎉🎉🎉
Great news!

Ok, that "user thing" works, but wasn't this a workaround?
Isn't putting node-red user in the dialout group the correct solutions? (in the official node-red Dockerfile)
...am I missing some caveat that suggest not to go this way?

Just as a heads up, this works until your device resets and becomes ttyACM1 while the container is running. If that happens, you won't be able to talk to it. There is a workaround that isn't --privileged though, details here: http://marc.merlins.org/perso/linux/post_2018-12-20_Accessing-USB-Devices-In-Docker-_ttyUSB0_-dev-bus-usb-_-for-fastboot_-adb_-without-using-privileged.html

Is there any way to get this line:

RUN usermod -a -G dialout node-red

into the official dockerfile?

I tried it on different systems and with different devices. It is the only command i have to rerun everytime I pull nodered. After this command the serial connection works without a problem.
(It would be much easier if this was incoperated into the dockerfile)

I solve this permission issue by adding --group-add dialout option when running the container. That is:

docker run -dit \
    --restart unless-stopped \
    --device=/dev/ttyUSB0 \
    --user node-red \
    --group-add dialout \
    --name nodered \
    -p 1880:1880 \
    -v /home/pi/node-red-data:/data \
    nodered/node-red-docker:rpi-v8

I solve this permission issue by adding --group-add dialout option when running the container. That is:

docker run -dit \
    --restart unless-stopped \
    --device=/dev/ttyUSB0 \
    --user node-red \
    --group-add dialout \
    --name nodered \
    -p 1880:1880 \
    -v /home/pi/node-red-data:/data \
    nodered/node-red-docker:rpi-v8

That works great for docker run, and works for docker-compose if your compose file is in v2 format. It was removed for v3, but it's back if you install docker-compose 1.27.0+ and are running Docker Engine 19.03.0+.

group_add:
  - dialout