我正在尝试实现运行 Docker 容器的简单 HLS 流媒体服务。简而言之,每个服务都是 dockerized Apache 流媒体节点。一切正常。但有一个问题是每个容器都在自己的端口上运行,我必须像这样解决它:
http://localhost:端口/服务名称/*m3u8。
我需要做的是设置一个代理来执行此端口转发,这样就不需要在 URL 中使用端口号。
搜索这个主题时,我感觉 NGINX 可以完成这项工作。但是 Proxy_Pass 似乎无法将请求路由到容器。在 NGINX 错误日志中,我收到 (111: Connection denied) 错误。或者 404。我尝试了不同的方法,但没有成功。我不是 NGINX 专家,所以我不确定我做的是否正确。有人能至少给我指出正确的方向吗?
以下是我的工作流程:
我已经为 Apache 服务和 NGINX 代理构建了一个映像。然后使用 Docker compose 创建了 3 个容器(1 个 NGINX 代理和 2 个 Apache 流),全部位于一个默认网络中。
当我处理没有端口号的服务时,出现 505 错误。
这是我的 NGINX 服务器的 Dockerfile:
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
这是 Apache 服务的 Dockerfile:
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/; - that is IP of Docker continer. localhost produces 404 error
}
}
这是 /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"
感谢您的任何提示!
更新2: 谢谢你的建议。
以下代码有效:
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;
}
}
我可以打开网址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
由于我不知道您设置的所有细节,因此您可以尝试几件事。
选项1:
从 nginx 配置文件中的 proxy_pass 语句中删除端口 :8003。端口 8003 是 docker 主机上的端口,该端口绑定到 stream1 容器的端口 80。由于您在 proxy_pass 语句中使用了 docker 容器 IP,因此容器可能没有打开端口 8003,它需要端口 80 上的连接。
server {
listen 80;
location /hls/ {
proxy_pass http://172.20.0.2/hls/; - that is IP of Docker continer.
}
}
选项 2:
出于与选项 1 相同的原因,另一个选项是您可以在 proxy_pass 语句中指定主机 IP 地址。这假设您在主机上有一个固定 IP。
server {
listen 80;
location /hls/ {
proxy_pass http://<hostip>:8003/hls/; - that is IP of the host
}
}
更新 2 的答案:
在更新 2 部分中,您收到一条错误,指出存在冲突的服务器名称。您可以在 nginx 配置中拥有多个服务器块,但它们必须都具有不同的名称。如果您未指定服务器名称,我相信它会默认为 $host。由于您使用位置来指定要重定向到的不同服务器,因此我建议在 1 个默认服务器块内使用多个位置块。通常,您会对不同的子域使用不同的服务器块。
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/; - that is IP of Docker continer.
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real_IP $remote_addr;
}
}