I've been trying to run homebridge in a container on a raspberry pi, here is the docker-compose.yaml definition:
services:
homebridge:
image: homebridge/homebridge:latest
container_name: homebridge
restart: always
network_mode: host
environment:
- PGID=1099
- PUID=1099
- HOMEBRIDGE_CONFIG_UI=1
- HOMEBRIDGE_CONFIG_UI_PORT=8581
volumes:
- /raid/config/homebridge:/homebridge
The application starts successfully and I can see in the logs that the HTTP server is up and running:
[10/3/2024, 10:30:14 PM] [Homebridge UI] Homebridge UI v4.59.0 is listening on :: port 8581
Now if I curl the port I get a connection refused:
$ curl localhost:8581
curl: (7) Failed to connect to localhost port 8581: Connection refused
What doesn't make sense to me is that if I exec into the container and do the exact same thing, the call goes through:
$ docker exec -it 3783843255f7 /bin/bash
Note: This is a restricted shell, sudo cannot be used here.
Homebridge Terminal
Node.js Version: v20.17.0
Node.js Path: /opt/homebridge/bin/node
Plugin Path: /var/lib/homebridge/node_modules
Update Node.js: hb-service update-node
Install Plugin: hb-service add homebridge-plugin-name
Remove Plugin: hb-service remove homebridge-plugin-name
root@tardis:/homebridge $ curl localhost:8581
<!doctype html>
<html lang="en">
...
Why isn't the 8581 port accessible from the outside even though the container is running in host network mode?
It's running rootless
That's a different network namespace:
Host network (
docker run --net=host
) is also namespaced inside RootlessKit.
https://docs.docker.com/engine/security/rootless/#known-limitations
When docker is running rootless, inside of a container (docker-in-docker, snap), inside a VM (docker desktop, or accessing a remote docker engine), then localhost for the docker engine is not the same as localhost of the user executing the CLI.