Как настроить прокси Nginx для перенаправления портов на контейнер Docker?

Вопрос или проблема

Я пытаюсь реализовать простой сервис потоковой передачи HLS, который работает на Docker-контейнерах. Вкратце, каждый сервис представляет собой контейнер Docker с узлом потоковой передачи Apache. Всё работает хорошо, за исключением того, что каждый контейнер работает на своем порту, и мне нужно обращаться к нему так:

http://localhost:Port/service_name/*m3u8. 

Что мне нужно сделать, так это настроить прокси для перенаправления портов, чтобы не было необходимости использовать номер порта в URL.

Изучая эту тему, я получил впечатление, что Nginx может справиться с этой задачей. Однако, похоже, что Proxy_Pass не удается перенаправить запрос на контейнер. В журнале ошибок Nginx я получаю ошибку (111: Соединение отклонено) или 404. Я пытался настроить это несколькими способами, но безуспешно. Я не эксперт в Nginx, и поэтому не уверен, делаю ли я всё правильно. Может, кто-то подскажет мне, в каком направлении двигаться?

Вот мой рабочий процесс:

Я создал образ для сервиса Apache и образ для прокси Nginx. Затем, используя Docker Compose, я создаю 3 контейнера (1 прокси Nginx и 2 потока Apache), все в одной сети по умолчанию.

Когда я обращаюсь к сервису без номера порта, я получаю ошибку 505.

Это мой Dockerfile для сервера Nginx:

FROM ubuntu:14.04
RUN sudo apt-get update && sudo apt-get install -y nginx && sudo apt-get install nano && rm -rf /var/lib/apt/lists/* 
EXPOSE 80

Это Dockerfile для сервиса Apache:

FROM ubuntu:14.04
    
RUN apt-get update && apt-get install -y apt-transport-https && apt-get install -y apache2 && \
apt-get install -y software-properties-common && add-apt-repository ppa:mc3man/trusty-media -y && \
    
apt-get update && apt-get install -y ffmpeg && mkdir /var/www/html/hls && chmod 777 -R /var/www/html/hls && \
    
rm -rf /var/lib/apt/lists/* 
    
COPY apache2.conf /etc/apache2/apache2.conf 
    
COPY mime.conf /etc/apache2/mods-available/mime.conf
    
RUN /etc/init.d/apache2 start

Это файл docker-compose.yml:

version: '2'
   

services:
    worker:
      image: nginx
      
      stdin_open: true
      tty: true
      ports: 
         - "80:80"
    
      
      

    stream1:
      image: server
      ports: 
         - "8003:80"
     
      command: >
         sh -c "sudo /etc/init.d/apache2 start && cd /var/www/html/hls && ffmpeg -i http://b46785a2.iptvzone.me/iptv/GWXXRGQF9G38LU/828/index.m3u8 -c copy  -hls_list_size 10 -hls_flags delete_segments live.m3u8 "
      restart: always 
 
    stream2:
      image: server
      ports: 
         - "8004:80"
      
      command: >
         sh -c "sudo mkdir /var/www/html/stream && chmod 777 -R /var/www/html/stream && cd /var/www/html/stream && sudo /etc/init.d/apache2 start \
         && ffmpeg -i http://app.live.112.events/hls-ua/112hd_mid/index.m3u8 -c copy  -hls_list_size 10 -hls_flags delete_segments live.m3u8 "
      restart: always

Это файл конфигурации Nginx в /etc/nginx/sites-available/default:

server {
     listen 80;

    location /hls/ {
      proxy_pass http://172.20.0.2:8003/hls/; - это IP Docker-контейнера. localhost дает ошибку 404

    }
}

А это вывод из /var/log/nginx/error.log:

2019/04/29 16:16:43 [error] 116#0: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 172.20.0.1, server: , request: "GET /hls/live.m3u8 HTTP/1.1", upstream: "http://127.0.0.1:8003/hls/live.m3u8", host: "localhost"
2019/04/29 16:16:46 [error] 116#0: *1 no live upstreams while connecting to upstream, client: 172.20.0.1, server: , request: "GET /hls/live.m3u8 HTTP/1.1", upstream: "http://localhost/hls/live.m3u8", host: "localhost"

Обновление: Следующий код сработал:

server {
    listen 80;
    
    location /hls/ {
      allow all;
      proxy_pass http://muze.cf:8003/hls/;
      proxy_redirect        off;
      proxy_set_header        Host             $host;
      proxy_set_header        X-Real_IP        $remote_addr;
    }
}

Я могу открыть URL http://muze.cf/hls/ без номера порта. Однако, когда я добавляю другой серверный блок, например:

server {
    listen 80;
    
    

    location /stream/ {
      allow all;
      proxy_pass http://muze.cf:8004/stream/;
      proxy_redirect        off;
      proxy_set_header        Host             $host;
      proxy_set_header        X-Real_IP        $remote_addr;
    }
}

Я получаю ошибку конфликта имени сервера:

2019/05/13 09:43:13 [warn] 42#0: conflicting server name "" on 0.0.0.0:80, ignored
2019/05/13 09:43:19 [error] 47#0: *1 open() "/usr/share/nginx/html/stream/live.m3u8" failed (2: No such file or directory), client: 83.134.167.52, server: , request: "GET /stream/live.m3u8 HTTP/1.1", host: "muze.cf"
2019/05/13 09:43:51 [error] 47#0: *1 open() "/usr/share/nginx/html/stream/live.m3u8" failed (2: No such file or directory), client: 83.134.167.52, server: , request: "GET /stream/live.m3u8 HTTP/1.1", host: "muze.cf"
2019/05/13 09:46:00 [warn] 66#0: conflicting server name "" on 0.0.0.0:80, ignored
2019/05/13 09:46:06 [error] 72#0: *3 open() "/usr/share/nginx/html/stream/live.m3u8" failed (2: No such file or directory), client: 83.134.167.52, server: , request: "GET /stream/live.m3u8 HTTP/1.1", host: "muze.cf"
2019/05/13 09:46:32 [error] 72#0: *3 open() "/usr/share/nginx/html/stream/live.m3u8" failed (2: No such file or directory), client: 83.134.167.52, server: , request: "GET /stream/live.m3u8 HTTP/1.1", host: "muze.cf"
2019/05/13 09:52:13 [warn] 94#0: server name "http://muze.cf/hls/" has suspicious symbols in /etc/nginx/sites-enabled/default:3
2019/05/13 09:52:13 [warn] 94#0: server name "http://muze.cf/stream/" has suspicious symbols in /etc/nginx/sites-enabled/default:16
2019/05/13 09:52:49 [error] 100#0: *6 open() "/usr/share/nginx/html/stream/live.m3u8" failed (2: No such file or directory), client: 83.134.167.52, server: http://muze.cf/hls/, request: "GET /stream/live.m3u8 HTTP/1.1", host: "muze.cf"

Теоретически я должен иметь возможность создать много серверных блоков в одном и том же домене?

Есть несколько вещей, которые вы могли бы попробовать, поскольку я не знаю всех деталей вашей настройки.

Вариант 1:

Удалите порт :8003 из оператора proxy_pass в вашем конфигурационном файле nginx. Порт 8003 – это порт на хосте Docker, который связан с портом 80 вашего контейнера stream1. Поскольку вы используете IP контейнера Docker в операторе proxy_pass, контейнер, вероятно, не имеет открытого порта 8003, он ожидает подключения на порту 80.

server {
    listen 80;

    location /hls/ {
      proxy_pass http://172.20.0.2/hls/; - это IP Docker-контейнера.
    }
}

Вариант 2:

Другой вариант по той же причине, что и вариант 1, вы можете указать IP-адрес хоста в операторе proxy_pass. Это предполагает, что у вас есть фиксированный IP на хосте.

server {
    listen 80;

    location /hls/ {
      proxy_pass http://<hostip>:8003/hls/; - это IP хоста
    }
}

Ответ на обновление:

В вашем разделе обновления вы получаете ошибку, которая сообщает о конфликтующих именах серверов. Вы можете иметь несколько серверных блоков в конфигурации nginx, но у всех них должны быть разные имена. Если вы не укажете имя сервера, оно по умолчанию принимается за $host, как я полагаю. Поскольку вы используете location для определения различных серверов для перенаправления, я рекомендую иметь несколько блоков location внутри одного блока сервера по умолчанию. Обычно для различных поддоменов используются разные блоки серверов.

server {
    listen 80;


    location /hls/ {
       allow all;
       proxy_pass http://muze.cf:8003/hls/;
       proxy_redirect        off;
       proxy_set_header        Host             $host;
       proxy_set_header        X-Real_IP        $remote_addr;
    }

    location /stream/ {
      allow all;
      proxy_pass http://muze.cf:8004/stream/;
      proxy_redirect        off;
      proxy_set_header        Host             $host;
      proxy_set_header        X-Real_IP        $remote_addr;
    }
}

Общие рекомендации:

В вашем блоку сервера nginx есть несколько других опций, которые вы также можете настроить. Это гарантирует, что некоторая информация заголовка будет передана.

server {
    listen 80;

    location /hls/ {
      allow all;
      proxy_pass http://172.20.0.2/hls/; - это IP Docker-контейнера.
      proxy_redirect        off;
      proxy_set_header        Host             $host;
      proxy_set_header        X-Real_IP        $remote_addr;
    }
}

Ответ или решение

Настройка Nginx в качестве прокси для пересылки портов на контейнер Docker

Чтобы настроить Nginx как прокси-сервер для пересылки запросов к контейнерам Docker, вам нужно внести некоторые изменения как в конфигурацию Nginx, так и в docker-compose.yml. Давайте рассмотрим шаги, которые могут помочь вам облегчить доступ к вашим контейнерам без указания номеров портов в URL.

1. Корректировка конфигурации Nginx

В вашей текущей конфигурации Nginx используются разные блоки серверов, однако лучше всего использовать один блок сервера с различными секциями location. Это позволит избежать конфликта серверных имён и упростит маршрутизацию:

server {
    listen 80;

    location /hls/ {
        allow all;
        proxy_pass http://172.20.0.2/hls/; # IP-адрес контейнера stream1
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    location /stream/ {
        allow all;
        proxy_pass http://172.20.0.3/stream/; # IP-адрес контейнера stream2
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Обратите внимание, что здесь мы используем внутренние IP-адреса ваших контейнеров (172.20.0.2 и 172.20.0.3), полученные из вашей сети Docker. Убедитесь, что эти адреса актуальны и соответствуют вашим контейнерам.

2. Обновление docker-compose.yml

Обязательно исчерпайте порты, которые уже задействованы. Например, чтобы избежать конфликтов, лучше использовать внутреннюю сеть Docker, где у вас будут только контейнеры, и вам не нужно открывать их порты на хосте. Убедитесь, что в вашем docker-compose.yml файле контейнеры находятся в одной сети:

version: '2'

services:
    worker:
        image: nginx
        ports: 
            - "80:80"

    stream1:
        image: server
        expose:
            - "80" # Используйте expose вместо ports, если порты не должны быть открыты на хосте
        command: >
            sh -c "service apache2 start && cd /var/www/html/hls && ffmpeg -i http://b46785a2.iptvzone.me/iptv/GWXXRGQF9G38LU/828/index.m3u8 -c copy -hls_list_size 10 -hls_flags delete_segments live.m3u8"
        restart: always 

    stream2:
        image: server
        expose:
            - "80"
        command: >
            sh -c "service apache2 start && mkdir -p /var/www/html/stream && ffmpeg -i http://app.live.112.events/hls-ua/112hd_mid/index.m3u8 -c copy -hls_list_size 10 -hls_flags delete_segments live.m3u8"
        restart: always

3. Перезапустите контейнеры

После внесения изменений в конфигурацию Nginx и docker-compose.yml выполните:

docker-compose down
docker-compose up -d

4. Тестирование

Теперь вы сможете получить доступ к вашим HLS стримам через URL:

  • Для первого потока: http://muze.cf/hls/live.m3u8
  • Для второго потока: http://muze.cf/stream/live.m3u8

Убедитесь, что все конфигурации сохранились, и вы можете открывать эти ссылки в браузере без проблем с номерами портов.

Заключение

Эта конфигурация упрощает доступ к вашему HLS сервису, устраняет необходимость в указании портов в URL и упрощает управление сервисами. Если возникнут ошибки, проверьте логи Nginx и Docker для выявления возможных проблем.

Оцените материал
Добавить комментарий

Капча загружается...