SK
Signal K•6mo ago
Mastiff

Unable to connect to GPSD on another Pi in Bridge mode

I have GPSD on a Pi with the IP 192.168.3.2, while SignalK is running on 192.168.3.1 in a Docker containr. If I run in bridge mode, it can't connect to the other Pi's GPSD, but in host mote I see that it connects in the logs flying past in the bash window when I start the container without the -d switch. Only then it won't accept connections on port 80, for some reason. I know I don't have anything else running on port 80. I have these ports in bridge mode: ports: - 80:80 - 1884:1884 - 2947:2947 network_mode: bridge The 1884 is the internal MQTT broker in "Signal K MQTT Gateway". So theoretically that should have no problems connecting to 2947, which is the port of GPSD. It just won't. It's stuck on "connecting to 192.168.3.2:2947". Any idea what this can be?
34 Replies
Teppo Kurki
Teppo Kurki•6mo ago
the ports configuration is all about accessing services running in the container from outside the container, it has nothing to do with accessing services outside the container for example 80:80 means "make the service that is running inside the container on port 80 accessible on the host computer's port 80". if you are using the standard sk image there is nothing running on port 80 inside the container, the sk server is on port 3000 so if you want it on port 80 of the host it should be 80:3000
Mastiff
MastiffOP•6mo ago
Thanks, but no. I am running that on 80. I have set it to 80 in HTTP port. So I should be able to access port 80 inside the container no matter what.
Teppo Kurki
Teppo Kurki•6mo ago
when sk server starts it outputs the port it is listening on in the log, you can verify there if you have configured it as you think anyway, that is kinda besides the point here
Mastiff
MastiffOP•6mo ago
Yeah, you're right. That doesn't explain why it can't connect o the GPSD in bridge mode, but can in host mode.
Teppo Kurki
Teppo Kurki•6mo ago
there is something blocking access to 192.168.3.2:2947. are you on windows? is there a firewall? can you access it from the host?
Mastiff
MastiffOP•6mo ago
First, to clear that up, from the log: SignalK | signalk-server running at 0.0.0.0:80 Second, no, a Pi, as the first message states. And every time I start in host mode, I can access GPSD on 192.168.3.2:2947, but not the server on port 80 from outside, and every time I start in Bridge mode that reverses. Maybe the installation is damaged, and I should try to set it up from the ground again. I moved the Docker stuff to an SSD a few days ago, since they were starting to take up a lot of space, using instructions from the Docker forum. Perhaps it has messed up some symbolic links or something. No, a new installation didn't change anything. But now I see that I get an error on host mode with 80 as the port, even though "sudo ss" does not show anything else using that port: Error: listen EACCES: permission denied 0.0.0.0:80 SignalK | at Server.setupListenHandle [as _listen2] (node:net:1881:21) SignalK | at listenInCluster (node:net:1946:12) SignalK | at Server.listen (node:net:2044:7) SignalK | at Server.<anonymous> (/usr/lib/node_modules/signalk-server/lib/index.js:333:24) SignalK | at Generator.next (<anonymous>) SignalK | at fulfilled (/usr/lib/node_modules/signalk-server/lib/index.js:23:58) SignalK | at process.processTicksAndRejections (node:internal/process/task_queues:95:5) { SignalK | code: 'EACCES', SignalK | errno: -13, SignalK | syscall: 'listen', SignalK | address: '0.0.0.0', SignalK | port: 80 SignalK | } But with 3000 as the GUI port and host mode, GUI works and GPSD works. Very strange, isn't it?
Teppo Kurki
Teppo Kurki•6mo ago
ah, sk docker image is using user node that is not privileged and can not bind to ports <1024. so that is not related to host/bridge network driver you can fire up a generic linux machine docker run -it --rm busybox and then do telnet 192.168.3.2 2947 to verify that you can connect to GPSD from a generic docker container with the default bridge network
Mastiff
MastiffOP•6mo ago
Thanks for answering! I know I can connect from another container, because I am connecting from Node-RED in Docker to the very same GPSD. So the solution is to change the port of GPSD on the secondary Pi, then? There is not much running there, so I'm sure I can find a port that's not i use. Like 666... (Finnish metal rules! 🤘 )
Teppo Kurki
Teppo Kurki•6mo ago
the gpsd port should not make a difference
Mastiff
MastiffOP•6mo ago
OK, I see. Is this something that I maybe should go to the Docker forum with, to find out why the SignalK can't connect to GPSD port 2947 on host mode?
Teppo Kurki
Teppo Kurki•6mo ago
you just said that host mode, GUI works and GPSD works?
Mastiff
MastiffOP•6mo ago
Yeah, but only with the GUI on 3000, and I would like to have it on the regular HTTP port 80, I have a bunch of devices that use it. So if I can either get GPSD working on bridge mode or port 80 for the GUI working on host mode, either way is good.
Teppo Kurki
Teppo Kurki•6mo ago
i am not aware of a way to get port 80 with the standard sk server image in host mode. you'd need to build your own image with user as root but i have a hard time understanding why gpsd is not accessible in bridge mode
Mastiff
MastiffOP•6mo ago
I was just going to ask if you thought it was possible to connet to GPSD on 2947 on bridge mode... Will my full Docker Compose file help any? services: signalk-server: image: cr.signalk.io/signalk/signalk-server:latest container_name: SignalK restart: no group_add: - "20" ports: - 80:80 - 1884:1884 network_mode: bridge devices: - /dev/ttyUSB0:/dev/ttyUSB0 #Sailor Hat - /dev/ttyUSB1:/dev/ttyUSB1 #Garmin volumes: - /dev:/dev - /media/pi/Docker/Docker-Compose/SignalK/SignalK-data:/home/node/.signalk entrypoint: sh /home/node/signalk/startup.sh privileged: true logging: options: max-size: 10m (I don't know how to make the file format look normal here on Discord, sorry...)
Teppo Kurki
Teppo Kurki•6mo ago
put triple backticks around it
code here
code here
Teppo Kurki
Teppo Kurki•6mo ago
No description
Teppo Kurki
Teppo Kurki•6mo ago
but i don't think the problem is there what does you .signalk/settings.json look like?
Mastiff
MastiffOP•6mo ago
The whole file?
Teppo Kurki
Teppo Kurki•6mo ago
hmmm how do you know that the connection to gpsd is not working with that docker compose configuration, as sk server is probably not starting properly as you are using port 80?
Mastiff
MastiffOP•6mo ago
The server starts up fine with port 80 in Bridge mode with port 80:80. Everything else shows up, like the input from the plotter and Sailor Hat.
Teppo Kurki
Teppo Kurki•6mo ago
i am really confused now
Mastiff
MastiffOP•6mo ago
The Docker Compose file I uploaded, was with bridge mode. Port 80 mapped to 80 internal. With that setup I can't connect to GPSD, but the GUI works on port 80 without a hitch. If I change networking mode to host mode, I need to use port 3000 for the GUI, which I really didn't want to, but GPSD works perfectly.
Teppo Kurki
Teppo Kurki•6mo ago
ok. how do you detect that you can't connect to GPSD?
Mastiff
MastiffOP•6mo ago
No messages coming in to the log what so ever, and it says "connecting" in the SignalK Dashboard. GPSD on the other Pi is running 24/7, and it's received by Node-RED all the time. I use the Garmin plotter when that is in use, since that's a bit more precise than the USB GPS that's on GPSD.
Teppo Kurki
Teppo Kurki•6mo ago
one way to test GPSD connectivity with hopefully an explicit error message if it does not work: - launch sk server image, but just nodejs instead of the server with docker run -it --rm --entrypoint /usr/bin/node signalk/signalk-server - paste the following to the prompt and hit enter
const socket = require('net').connect(2947, '192.168.3.2', function () {
console.log('Connected')
socket.write("R\r\n")

socket.on("data", function (data) {
console.log("received data")
console.log(data.toString())
socket.end()
})
})
socket.on("error", function (err) {
console.log('Error', err)
})
const socket = require('net').connect(2947, '192.168.3.2', function () {
console.log('Connected')
socket.write("R\r\n")

socket.on("data", function (data) {
console.log("received data")
console.log(data.toString())
socket.end()
})
})
socket.on("error", function (err) {
console.log('Error', err)
})
it spits out first a bit of garbage looking like [Symbol(kBytesWritten etc but then either Connected or eventually an error
Mastiff
MastiffOP•6mo ago
<ref *1> Error: connect ECONNREFUSED 192.168.3.2:2947
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1606:16)
at TCPConnectWrap.callbackTrampoline (node:internal/async_hooks:130:17) {
errno: -111,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '192.168.3.2',
port: 2947,
domainEmitter: Socket {
connecting: false,
_hadError: false,
_parent: null,
_host: null,
_closeAfterHandlingError: false,
_events: {
close: undefined,
error: undefined,
prefinish: undefined,
finish: undefined,
drain: undefined,
data: undefined,
end: [Function: onReadableStreamEnd],
readable: undefined,
connect: [Function]
},
_readableState: ReadableState {
highWaterMark: 16384,
buffer: [],
bufferIndex: 0,
length: 0,
pipes: [],
awaitDrainWriters: null,
[Symbol(kState)]: 1053110,
[Symbol(kErroredValue)]: [Circular *1]
},
_writableState: WritableState {
highWaterMark: 16384,
length: 0,
corked: 0,
onwrite: [Function: bound onwrite],
writelen: 0,
bufferedIndex: 0,
pendingcb: 0,
[Symbol(kState)]: 17564598,
[Symbol(kBufferedValue)]: null,
[Symbol(kErroredValue)]: [Circular *1]
},
allowHalfOpen: false,
_maxListeners: undefined,
_eventsCount: 2,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: null,
_server: null,
[Symbol(async_id_symbol)]: 31,
[Symbol(kHandle)]: null,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(shapeMode)]: true,
[Symbol(kCapture)]: false,
[Symbol(kSetNoDelay)]: false,
[Symbol(kSetKeepAlive)]: false,
[Symbol(kSetKeepAliveInitialDelay)]: 0,
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0
},
domainThrown: false
<ref *1> Error: connect ECONNREFUSED 192.168.3.2:2947
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1606:16)
at TCPConnectWrap.callbackTrampoline (node:internal/async_hooks:130:17) {
errno: -111,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '192.168.3.2',
port: 2947,
domainEmitter: Socket {
connecting: false,
_hadError: false,
_parent: null,
_host: null,
_closeAfterHandlingError: false,
_events: {
close: undefined,
error: undefined,
prefinish: undefined,
finish: undefined,
drain: undefined,
data: undefined,
end: [Function: onReadableStreamEnd],
readable: undefined,
connect: [Function]
},
_readableState: ReadableState {
highWaterMark: 16384,
buffer: [],
bufferIndex: 0,
length: 0,
pipes: [],
awaitDrainWriters: null,
[Symbol(kState)]: 1053110,
[Symbol(kErroredValue)]: [Circular *1]
},
_writableState: WritableState {
highWaterMark: 16384,
length: 0,
corked: 0,
onwrite: [Function: bound onwrite],
writelen: 0,
bufferedIndex: 0,
pendingcb: 0,
[Symbol(kState)]: 17564598,
[Symbol(kBufferedValue)]: null,
[Symbol(kErroredValue)]: [Circular *1]
},
allowHalfOpen: false,
_maxListeners: undefined,
_eventsCount: 2,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: null,
_server: null,
[Symbol(async_id_symbol)]: 31,
[Symbol(kHandle)]: null,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(shapeMode)]: true,
[Symbol(kCapture)]: false,
[Symbol(kSetNoDelay)]: false,
[Symbol(kSetKeepAlive)]: false,
[Symbol(kSetKeepAliveInitialDelay)]: 0,
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0
},
domainThrown: false
Teppo Kurki
Teppo Kurki•6mo ago
and does it work if you launch with docker run -it --rm --entrypoint /usr/bin/node --network host signalk/signalk-server ?
Mastiff
MastiffOP•6mo ago
I belive so. This is way over my head, but I don't see the long error list. This is all I get:
Welcome to Node.js v20.15.0.
Type ".help" for more information.
> const socket = require('net').connect(2947, '192.168.3.2', function () {
... console.log('Connected')
... socket.write("R\r\n")
...
... socket.on("data", function (data) {
... console.log("received data")
... console.log(data.toString())
... socket.end()
... })
... })
undefined
> socket.on("error", function (err) {
... console.log('Error', err)
... })Connected
received data
{"class":"VERSION","release":"3.22","rev":"3.22","proto_major":3,"proto_minor":14}
Welcome to Node.js v20.15.0.
Type ".help" for more information.
> const socket = require('net').connect(2947, '192.168.3.2', function () {
... console.log('Connected')
... socket.write("R\r\n")
...
... socket.on("data", function (data) {
... console.log("received data")
... console.log(data.toString())
... socket.end()
... })
... })
undefined
> socket.on("error", function (err) {
... console.log('Error', err)
... })Connected
received data
{"class":"VERSION","release":"3.22","rev":"3.22","proto_major":3,"proto_minor":14}
Teppo Kurki
Teppo Kurki•6mo ago
huh. i am running out of ideas here
Mastiff
MastiffOP•6mo ago
Well, thanks a lot for trying! I can ask in the Docker forum if somebody knows why I can't access the port in Bridge mode.
Teppo Kurki
Teppo Kurki•6mo ago
and you have rebooted all the involved machines?
Mastiff
MastiffOP•6mo ago
Every night at 04, automatically. But I can try again now. Nothing changed, GPSD still works on host but not on bridge. I mentioned this at the Docker forum, and I got an answer from one of the guys in the know there: "This used to be true, and is still true when your system uses a Linux Kernel < 4.11. For Kernel 4.11 and later docker takes care of lifting that restriction. See: Non-root user able to bind to port 80; why? - #6 by meyay" https://forums.docker.com/t/non-root-user-able-to-bind-to-port-80-why/140524/5
Teppo Kurki
Teppo Kurki•6mo ago
Yep, i had it wrong in my earlier message
Mastiff
MastiffOP•5mo ago
So I should really be able to use port 80 in Host mode? Any idea why it isn't working? In case anybody stumbles over this by some weird coincidence, @Teppo Kurki's right. Normally it doesn't work. But with his help with commands and some help from the Docker forum converting it to a Docker Compose file, I have it working now. Full file here: https://github.com/SignalK/signalk-server/issues/1773#issuecomment-2288435679

Did you find this page helpful?