From 818b66503bf7da280ca530d2ad17a4ef4e252d6a Mon Sep 17 00:00:00 2001 From: Alex J Lennon Date: Thu, 24 Aug 2023 15:54:05 +0100 Subject: [PATCH] Add Traefik reverse-proxy support This allows us to access MING containers such as Node-Red and Grafana without needing to open different ports - Port :8080 is used for the Traefik admin web UI - Port :80 is use for everything else http://foo:80/node-red is mapped to the node-red container http://foo:80/grafana is mapped to the grafana container http://foo:80/ is also mapped to the grafana container This also serves as an example of how to configure Traefik to access containers remotely via port :80 Signed-off-by: Alex J Lennon --- README.md | 17 ++++++---- balena.yml | 4 +-- docker-compose.yml | 85 +++++++++++++++++++++++++++++++++++++++------- 3 files changed, 84 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index fddde79..378e76e 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,13 @@ This is an educative project called *MING* based on MQTT, InfluxDB, [balena Node Each of these applications is built and runs in its own container on an embedded Linux target supporting balena.io or Docker: -* Mosquitto MQTT broker listening on port 1883 for MQtt message publications. -* InfluxDB listening on port 8086 providing a time series database for sensor data storage. -* NodeRed listening on port 80 to provide an easy to use graphical environment for parsing, analysing, storing, and forwarding sensor data messages. -* Grafana listening on port 8080 providing a data visualisation environment for sensor data. +* Traefik reverse proxy allows remote access via a mapped HTTP path rather than needing to expose container ports publically +* Traefik configured in debug mode to expose its admin WebUI on port :8080 +* Traefik configured to listen on port :80 forwarding configured paths to internal ports in containers +* Mosquitto MQTT broker listening on local port 1883 for MQtt message publications. +* InfluxDB listening on local port 8086 providing a time series database for sensor data storage. +* NodeRed listening on http://foo/node-red to provide an easy to use graphical environment for parsing, analysing, storing, and forwarding sensor data messages. +* Grafana listening on http://foo/grafana providing a data visualisation environment for sensor data. * WiFi Connect listening on the port 80 in case there is not WiFi connectivity available. @@ -67,14 +70,14 @@ Variable Name | Default | Description PORT | `80` | the port that exposes the Node-RED UI USERNAME | `balena` | the Node-RED admin username PASSWORD | `balena` | the Node-RED admin password -ENCRIPTION_KEY | `balena` | the encription key used to store your credentials files +ENCRYPTION_KEY | `balena` | the encription key used to store your credentials files -You **must** set the `USERNAME` and `PASSWORD` environment variables to be able to save or run programs in Node-RED. +You **must** set the `USERNAME` and `PASSWORD` environment variables to be able to save or run programs in Node-RED. ## Node-RED -For running Node-RED, use the local IP address on port 80, if you are on the same network than your device. You also can use the `Publick Device URL` by balena to access to the Node-RED UI. +For running Node-RED, use the local IP address on port 80 with path /node-red, if you are on the same network than your device. You also can use the `Public Device URL` by balena to access to the Node-RED UI. ### Add new Node-RED nodes diff --git a/balena.yml b/balena.yml index 74693db..7f2c4b1 100644 --- a/balena.yml +++ b/balena.yml @@ -1,7 +1,7 @@ name: MING - MQTT InfluxDB NodeRED Grafana type: sw.application description: >- - Deploys MING Stak (MQTT, InfluxDB, NodeRED and Grafana). An Open-Source LAMP-like stack for the Internet of Things + Deploys MING Stack (MQtt, InfluxDB, NodeRED and Grafana). An Open-Source LAMP-like stack for the Internet of Things joinable: false assets: repository: @@ -21,4 +21,4 @@ data: - raspberrypi4-64 - raspberrypi400-64 - raspberrypicm4-ioboard - - fincm3 \ No newline at end of file + - fincm3 diff --git a/docker-compose.yml b/docker-compose.yml index b36c2a5..fa49ab7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -27,31 +27,45 @@ services: # Node-RED # ------------------------------------------------------------------------------------ node-red: - image: bh.cr/balenalabs/balena-node-red-aarch64 +# image: bh.cr/balenalabs/balena-node-red-aarch64 + image: bh.cr/gh_ajlennon/balena-node-red container_name: node-red privileged: true restart: unless-stopped volumes: - 'node-red-data:/data' labels: - io.balena.features.dbus: '1' - io.balena.features.sysfs: '1' - io.balena.features.supervisor-api: '1' - io.balena.features.balena-api: '1' - ports: - - 80:80 + # Enable traefik support for this container + - "traefik.enable=true" + # Set service port + - "traefik.http.services.node-red.loadbalancer.server.port=80" + # Make it available on the "web" entrypoint which is defined below as :80 + - "traefik.http.routers.node-red.entrypoints=web" + # Add a specific path prefix that will be expected on the URL suffix + - "traefik.http.routers.node-red.rule=PathPrefix(`/node-red`)" + - "traefik.http.middlewares.strip-node-red-prefix.stripprefix.forceSlash=false" + - "traefik.http.routers.node-red.middlewares=strip-node-red-prefix" + - "io.balena.features.dbus=true" + - "io.balena.features.sysfs=true" + - "io.balena.features.supervisor-api=true" + - "io.balena.features.balena-api=true" environment: PORT: 80 + HTTP_ROOT: "node-red" USERNAME: "balena" PASSWORD: "balena" - ENCRIPTION_KEY: "balena" + ENCRIPTION_KEY: "balena" cap_add: - SYS_RAWIO devices: - "/dev/mem:/dev/mem" - "/dev/gpiomem:/dev/gpiomem" - "/dev/i2c-1:/dev/i2c-1" - + depends_on: + influxdb: + condition: service_started + reverse-proxy: + condition: service_started # ------------------------------------------------------------------------------------ # MQTT @@ -81,9 +95,54 @@ services: image: bh.cr/balenalabs/dashboard container_name: grafana restart: unless-stopped - ports: - - "8080:80" volumes: - - "grafana-data:/data" - + - "grafana-data:/data" + environment: + - "PORT=80" + - "GF_SERVER_ROOT_URL=/grafana" + - "GF_SERVER_SERVE_FROM_SUB_PATH=true" + labels: + # Enable traefik support for this container + - "traefik.enable=true" + # Set service port + - "traefik.http.services.grafana.loadbalancer.server.port=80" + # Make it available on the "web" entrypoint which is defined below as :80 + - "traefik.http.routers.grafana.entrypoints=web" + # Add a specific path prefix that will be expected on the URL suffix + - "traefik.http.routers.grafana.rule=PathPrefix(`/grafana`)" + # Redirect a request to root page to grafana service + - "traefik.http.routers.grafana-main.rule=( Path(`/`) )" + - "traefik.http.middlewares.redirect-root.redirectregex.regex=^/" + - "traefik.http.middlewares.redirect-root.redirectregex.replacement=/grafana" + - "traefik.http.routers.grafana-main.middlewares=redirect-root" + depends_on: + influxdb: + condition: service_started + reverse-proxy: + condition: service_started + # ------------------------------------------------------------------------------------ + # Traefik Reverse Proxy + # ------------------------------------------------------------------------------------ + reverse-proxy: + image: bh.cr/gh_ajlennon/reverse-proxy + command: + - "--log.level=DEBUG" + - "--accesslog=true" + - "--accesslog.filepath=/var/log/traefik.log" + - "--api.dashboard=true" + # Uncomment this to enable the Traefik WebUI on port :8080 + - "--api.insecure" + - "--providers.docker=true" + - "--providers.docker.endpoint=unix:///var/run/balena-engine.sock" + #- "--providers.docker.exposedbydefault=true" + - "--entrypoints.web.address=:80" + ports: + # The HTTP port + - "80:80" + # The Dashboard port + - "8080:8080" + labels: + # So that Traefik can listen to the Docker events + io.balena.features.balena-socket: '1' + restart: always