Вопрос или проблема
Я думаю, что система Docker с nginx + ssl + nodered + grafana + mosquitto + influxdb достаточно распространена, надеюсь, это поможет другим.
У меня идеально работают nginx и ssl (certbot), и если я захожу на http://example.com:1880 или http://example.com:1880/ui или http://example.com:3000, я могу без проблем получить доступ к потокам nodered, ui и grafana.
Но мне нужно “больше”.
Я хочу иметь “подпапки”, как это:
- grafana будет перенаправляться на example.com/grafana
- редактирование потоков nodered должно идти на example.com/nodered
- ui nodered (dashboard или flowfuse, что угодно) должно идти на example.com
Я пробовал сотни конфигураций, редактируя docker-compose.yml, nginx.conf, settings.js и grafana.ini, но… без успеха.
Надеюсь, что кто-то мог бы иметь что-то подобное и поделиться с нами своими конфигурационными файлами.
Это мои на данный момент (я удалил свои “неудачные попытки конфигураций”)
server {
listen 80;
listen [::]:80;
server_name example.com;
location /.well-known/acme-challenge {
allow all;
root /var/www/certbot;
}
location / {
# rewrite ^ https://$host$request_uri? permanent;
return 301 https://$server_name$request_uri;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
#STATIC index index.php index.html index.htm;
#STATIC root /var/www/html;
server_tokens off; #Отключение версии Nginx в заголовках для безопасности
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
#linuxserver.io
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # около 40000 сессий
ssl_session_tickets off;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
# Логи доступа и ошибок Nginx
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location ~ /\.ht { deny all; }
location = /favicon.ico { log_not_found off; access_log off; }
location = /robots.txt { log_not_found off; access_log off; allow all; }
location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ { expires max; log_not_found off; }
}
Docker-compose.yml
services:
mosquitto:
image: eclipse-mosquitto:2
container_name: mosquitto
ports:
- "1883:1883"
#- "8883:8883"
#- "9001:9001" # Websocket опционально
volumes:
- ./mosquitto-data:/mosquitto
restart: unless-stopped
#environment:
# - 'TZ='Europe/Brussels'
influxdb:
image: influxdb:2.7
container_name: influxdb
ports:
- "8086:8086"
volumes:
- ./influxdb-data:/var/lib/influxdb2
- ./influxdb-config:/etc/influxdb2
environment:
- DOCKER_INFLUXDB_INIT_MODE=setup
- DOCKER_INFLUXDB_INIT_USERNAME=user
- DOCKER_INFLUXDB_INIT_PASSWORD=password
- DOCKER_INFLUXDB_INIT_ORG=org
- DOCKER_INFLUXDB_INIT_BUCKET=buck
- DOCKER_INFLUXDB_INIT_RETENTION=0
restart: unless-stopped
grafana:
image: grafana/grafana:11.4.0
container_name: grafana
ports:
- "3000:3000"
volumes:
- ./grafana-data:/var/lib/grafana
- ./grafana-config:/etc/grafana
#user: "0"
environment:
- GF_SECURITY_ADMIN_USER=user
- GF_SECURITY_ADMIN_PASSWORD=password
#- GF_SERVER_ROOT_URL=https://example.com/grafana
#- GF_SERVER_DOMAIN=https://example.com/
#- GF_INSTALL_PLUGINS
restart: unless-stopped
nodered:
image: nodered/node-red:4.0
container_name: nodered
ports:
- "1880:1880"
volumes:
- ./nodered-data:/data
restart: unless-stopped
nginx:
image: nginx:1.27.3-bookworm
container_name: nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx-data:/etc/nginx/conf.d
- ./nginx-logs:/var/log/nginx
- ./letsencrypt-data:/etc/letsencrypt
- ./certbot-data:/var/www/certbot
depends_on:
- nodered
- grafana
- influxdb
restart: unless-stopped
certbot:
image: certbot/certbot
container_name: certbot
depends_on:
- nginx
volumes:
- ./letsencrypt-data:/etc/letsencrypt
- ./certbot-data:/var/www/certbot
#restart: unless-stopped
# command: certonly --webroot --webroot-path=/var/www/certbot/ --email [email protected] --agree-tos --no-eff-email --staging -d example.com
#command: certonly --webroot --webroot-path=/var/www/certbot/ --email [email protected] --agree-tos --no-eff-email --force-renewal -d example.com
volumes:
mosquitto-data:
influxdb-data:
influxdb-config:
grafana-data:
grafana-config:
nodered-data:
letsencrypt-data:
nginx-data:
certbot-data:
Что мне нужно изменить/добавить в эти файлы?:
- nodered: docker-compose, nginx и settings.js
- grafana: docker-compose, nginx и grafana.ini
Большое спасибо.
Ответ или решение
Чтобы реализовать требуемую конфигурацию с использованием Nginx в качестве реверс-прокси для маршрутизации доступа к различным сервисам (Node-RED, Grafana и другим) с поддержкой SSL через Docker-Compose, необходимо учесть несколько ключевых моментов. Давайте подробно разберем, как можно это организовать.
Теория
-
Реверс-прокси через Nginx:
Реверс-прокси используется для распределения запросов между различными сервисами, работающими в одном домене, но на разных виртуальных путях (например,/grafana
,/nodered
). -
Docker Compose:
Позволяет легко конфигурировать и управлять многоконтейнерной средой Docker. Вы можете описать все ваши сервисы и зависимости между ними в одном YAML файле. -
SSL/TLS:
Использование Certbot для получения и управления SSL сертификатами от Let’s Encrypt. Это позволяет зашифровать трафик между пользователем и вашим сервером.
Пример
-
Конфигурация Nginx:
Добавьте в
nginx.conf
секции для маршрутизации на поддиректории сервиса:server { listen 443 ssl http2; server_name example.com; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; location /grafana/ { proxy_pass http://grafana:3000/; rewrite ^/grafana(/.*)$ $1 break; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location /nodered/ { proxy_pass http://nodered:1880/; rewrite ^/nodered(/.*)$ $1 break; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
-
Docker Compose и Сервисы:
Убедитесь, что каждый сервис настроен на правильную работу с реверс-прокси. Добавьте переменные окружения в
docker-compose.yml
.services: grafana: image: grafana/grafana:11.4.0 container_name: grafana environment: - GF_SERVER_ROOT_URL=https://example.com/grafana/ - GF_SERVER_SERVE_FROM_SUB_PATH=true volumes: - ./grafana-data:/var/lib/grafana restart: unless-stopped nodered: image: nodered/node-red:4.0 container_name: nodered environment: - NODE_RED_EDITOR_URL=https://example.com/nodered/ volumes: - ./nodered-data:/data restart: unless-stopped
-
Настройки Grafana и Node-RED:
Для Grafana добавьте в
grafana.ini
:[server] root_url = https://example.com/grafana/ serve_from_sub_path = true
Для Node-RED настройте
settings.js
, если необходимо изменить путь к редактору или другим ресурсам.
Применение
Чтобы проверить работоспособность конфигурации, перезапустите ваши контейнеры с помощью docker-compose up -d
и убедитесь, что каждый сервис доступен по своему пути (/grafana
, /nodered
). Следует изучать логи как Nginx, так и каждого сервиса для выявления проблем. Применение этих настроек должно привести к корректной маршрутизации и защищенному доступу к вашим приложениям.
Таким образом, обеспечивается централизованный доступ к различным сервисам в рамках одного домена с использованием Docker и Nginx, что упрощает развертывание и дальнейшее управление архитектурой в вашем проекте.