在 nginx 和/或防火墙后面运行 docker 容器时出现问题



我在nginx后面运行Docker,注册表容器和我自己的容器运行一个gunicorn django webapp。

django webapp 在 docker 容器之外运行良好。但是,一旦我尝试从容器内运行 django 网络应用程序,网络应用程序就会失败,并显示来自 nginx 的以下消息:

2018/03/20 15:39:30 [error] 14767#0: *360 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 10.38.181.123, server: app.ukrdc.nhs.uk, request: "POST /convert/pv-to-rda/ HTTP/1.1", upstream: "http://127.0.0.1:9300/convert/pv-to-rda/", host: "app.ukrdc.nhs.uk"

当我在网络应用程序上做一个。

注册表容器工作正常。

  1. 我已经在 Dockerfile 中公开了正确的端口

  2. 运行命令为:

    docker run -ti -p 9300:9300 ukrdc/ukrdc-webapi

  3. 已将端口添加到 iptables。

(输出自 iptables -S

-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N DOCKER
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 5000 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 9300 -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER -d 172.17.0.1/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 5000 -j ACCEPT
-A DOCKER -d 172.17.0.20/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 9300 -j ACCEPT)

这些迹象表明我的容器和/或防火墙规则有问题,但我不确定是什么。我想我正在做与注册表容器相同的操作。

运行在 Centos 6.9 和 Docker 版本 1.7.1,内部版本 786b29d/1.7.1

答案是:

运行 Django 应用程序

exec gunicorn mysite.wsgi 
-    -b 127.0.0.1:9300 
+    -b 0.0.0.0:9300 
--name ukrdc_django 
--workers 3 
--log-level=info 

我已将其绑定到本地环回地址。它现在绑定到所有地址,现在可以工作了。

尝试将-P添加到 run 命令中:

docker run -P <container>

这将自动发布公开的端口。请注意区别:公开端口使其可用于 docker 网络上的其他容器,而发布端口使其可供主机以及网络上的其他容器使用。

我认为当您真的想要在docker run命令上使用-P-p标志时,您正在使用EXPOSE,其中"P"代表"发布"。根据docker docs,EXPOSE仅用于链接容器之间的端口,其中docker run -P <container>docker run -p 1234:1234/tcp <container>实际上会在容器外部提供一个或多个端口,以便nginx可以从主机访问它。另一种选择是你可以在同一网络上的容器中运行nginx(那里有一个易于使用的标准nginx容器),然后nginx可以访问网络上所有暴露的端口,但在这种情况下,你需要至少发布一个nginx容器的端口。

这是另一篇SO帖子,它在曝光与发布方面对我有很大帮助:

docker 中"公开"和"发布"的区别