Nginx docker 容器: 502错误网关响应

我有监听8080端口的服务,这个不是集装箱。

然后,我使用官方图片创建了一个 nginx 容器:

docker run --name nginx -d -v /root/nginx/conf:/etc/nginx/conf.d -p 443:443 -p 80:80 nginx

毕竟:

# netstat -tupln | grep 443
tcp6       0      0 :::443                  :::*                    LISTEN      3482/docker-proxy
# netstat -tupln | grep 80
tcp6       0      0 :::80                   :::*                    LISTEN      3489/docker-proxy
tcp6       0      0 :::8080                 :::*                    LISTEN      1009/java

Nginx 配置是:

upstream eighty {
server 127.0.0.1:8080;
}


server {
listen 80;
server_name eighty.domain.com;


location / {
proxy_pass                        http://eighty;
}
}

我已经检查我能够连接到这个服务器与 # curl http://127.0.0.1:8080

 <html><head><meta http-equiv='refresh'
content='1;url=/login?from=%2F'/><script>window.location.replace('/login?from=%2F');</script></head><body
style='background-color:white; color:white;'>
...

它似乎运行良好,但是,当我试图访问我的浏览器,nginx 告诉 bt 502糟糕的网关响应。

我发现这可能是一个与非容器化进程和容器之间的可见性有关的问题。我是否可以通过其他非集装箱过程建立与港口的连接?

剪辑

日志地点 upstream { server 127.0.0.1:8080; }:

2016/07/13 09:06:53 [error] 5#5: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 62.57.217.25, server: eighty.domain.com, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "eighty.domain.com"
62.57.217.25 - - [13/Jul/2016:09:06:53 +0000] "GET / HTTP/1.1" 502 173 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0" "-"

日志地点 upstream { server 0.0.0.0:8080; }:

62.57.217.25 - - [13/Jul/2016:09:00:30 +0000] "GET / HTTP/1.1" 502 173 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0" "-" 2016/07/13 09:00:30 [error] 5#5: *1 connect() failed (111: Connection refused) while connecting to upstream, client:
62.57.217.25, server: eighty.domain.com, request: "GET / HTTP/1.1", upstream: "http://0.0.0.0:8080/", host: "eighty.domain.com" 2016/07/13 09:00:32 [error] 5#5: *3 connect() failed (111: Connection refused) while connecting to upstream, client: 62.57.217.25, server: eighty.domain.com, request: "GET / HTTP/1.1", upstream: "http://0.0.0.0:8080/", host: "eighty.domain.com"
62.57.217.25 - - [13/Jul/2016:09:00:32 +0000] "GET / HTTP/1.1" 502 173 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0" "-"

有什么想法吗?

161389 次浏览

问题

涉及到容器时,Localhost 有点棘手。 这意味着,像这样的上游:

upstream foo{
server 127.0.0.1:8080;
}

或者

upstream foo{
server 0.0.0.0:8080;
}

您告诉 nginx 将请求传递给本地主机。 但是在 docker 容器的上下文中,localhost (以及相应的 ip 地址)指向容器本身:

enter image description here

通过寻址127.0.0.1,如果容器不在主机网络上,您将永远无法到达主机。

解决方案

主机网络

您可以选择在与您的主机相同的网络上运行 nginx:

docker run --name nginx -d -v /root/nginx/conf:/etc/nginx/conf.d --net=host nginx

注意,在这种情况下不需要公开任何端口。

虽然你失去了码头网络的好处,但这是有效的。如果您有多个应该通过 Docker 网络进行通信的容器,那么这种方法可能是一个问题。如果您只想使用 docker 部署 nginx,而不想使用任何高级的 docker 网络特性,那么这种方法是可行的。

访问主机远程 IP 地址

另一种方法是重新配置 nginx 上游指令,通过添加主机的远程 IP 地址直接连接到主机:

upstream foo{
//insert your hosts ip here
server 192.168.99.100:8080;
}

容器现在将遍历网络堆栈并正确解析主机:

enter image description here

您也可以使用您的 DNS 名称,如果您有一个。确保多克知道您的 DNS 服务器。

对于我帮助这行代码 proxy_set_header Host $http_host;

server {
listen            80;
server_name  localhost;
location / {
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;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;


proxy_redirect off;
proxy_pass http://myserver;
}

ip=$(ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | head -n 1)


docker run --name nginx --add-host="host:${ip}" -p 80:80 -d nginx

Nginx.conf

location / {
...
proxy_pass http://host:8080/;
}

对我来说很有用

您可以做的是配置 proxy_pass,从 container的角度来看,地址将指向您的实际主机。

要从容器的角度获取 host地址,你可以在 Windows 上使用 docker 18.03(或更新的)执行以下操作:

从图像名称为 nginx的主机上运行 bash 容器(在 Alpine Linux distribution上工作) :

 docker run -it nginx /bin/ash

然后在集装箱里面跑

/ # nslookup host.docker.internal


Name:      host.docker.internal
Address 1: 192.168.65.2

192.168.65.2是主机的 IP-而不是像 spinus那样的桥接 IP 接受的答案。

我在这里使用 主机,码头,内部:

主机有一个正在更改的 IP 地址(如果没有网络访问权限,则没有 IP 地址)。从18.03开始,我们的建议是连接到特殊的 DNS 名 host.docker.Internal,它解析为主机使用的内部 IP 地址。这是为了开发目的,不适用于 Docker for Windows 之外的生产环境。

然后您可以将 nginx配置更改为: proxy_pass http://192.168.65.2:{your_app_port};

应该没问题。

请记住提供与本地应用程序运行时相同的 port

我遇到了这个问题,原来是由于权限问题导致的 Docker 容器无法启动的问题。

对我来说是逃跑

docker-compose ps

显示容器没有以状态1启动和退出。原来在迁移到新机器时,权限丢失了。对父目录上的一个已知员工用户的权限进行了调整,为我解决了这个问题,然后我就可以像以前一样启动 Docker 服务了

nginx_1_c18a7f6f7d6d | chown: /var/www/html: Operation not permitted
# the upstream component nginx needs to connect to
upstream django {


# server unix:///path/to/your/mysite/mysite.sock; # for a file socket


server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}




location / {


uwsgi_pass  django;
include     /path/to/your/mysite/uwsgi_params; # the uwsgi_params file you installed
}

完整参考文献 : < a href = “ https://uwsgi-docs.readthedocs.io/en/best/Tutorials/Django _ and _ nginx.html”rel = “ nofollow noReferrer”> https://uwsgi-docs.readthedocs.io/en/latest/tutorials/django_and_nginx.html

只是为了完成其他的答案,我正在使用 mac 进行开发,直接在上游使用 host.docker.Internal 对我来说是可行的,不需要传递主机远程 IP 地址。下面是代理 nginx 的配置:

events { worker_connections 1024; }


http {
upstream app1 {
server host.docker.internal:81;
}


upstream app1 {
server host.docker.internal:82;
}
    

server {
listen 80;
server_name app1.com;
    

location / {
proxy_pass    http://app1;
}
}


server {
listen 80;
server_name app2.com;
    

location / {
proxy_pass    http://app2;
}
}
}

如您所见,我在 nginx 代理后面为不同的应用程序使用了不同的端口。我对 app1使用端口81,对 app2使用端口82,app1和 app2都有自己的 nginx 容器:

应用程序1:

docker run --name nginx -d -p 81:80 nginx

应用程序2:

docker run --name nginx -d -p 82:80 nginx

此外,详情请参阅以下连结: 码头医生找 Mac