docker-compose一个应用程序背后的反向代理,也可以访问外部服务。

问题描述 投票:0回答:1

在本地服务器上,我启动了几个gunicorn实例,每个实例在一个独特的端口上运行一个不同的web应用,作为对内部网络其他部分的服务。现在,我想把每个gunicorn实例放在自己的nginx反向代理服务器后面,以便更好地进行负载平衡。

我决定尝试将每个(nginx、gunicorn)对部署在自己的Docker容器中,只将其唯一的端口暴露给外界。我知道这在端口转发上已经很容易了--例如 "5555:80"。然而,每个应用程序也会访问独立于Docker运行在同一主机上的外部服务,例如数据库。

通过试错,我发现只有当我以 "docker run --network=host ... "的方式运行时,Docker容器才能访问外部服务(如MySQL,或MongoDB)。这样做的效果是让容器共享主机网络,但同时也暴露了gunicorn打开的任何端口,这意味着它给客户端留下了绕过反向代理的途径。虽然这一切都运行在安全网络的本地服务器上,但这似乎不是一个好的安全做法,因为它让后端面临拒绝服务攻击。

所以我想我想两全其美--我想让每一对(代理,gunicorn)通过一个只有他们自己使用的私有网络相互对话,同时我将一个端口(例如 "5555")暴露在网络上,而运行在gunicorn下的web应用仍然可以访问同一主机上的其他服务。

我的nginx.conf看起来是这样的。

http {
    upstream app {
        server network1_app;
    }

    server {
        location / {
            proxy_pass  http://app;
        }
    }
}

而我的docker-compose.yml可能是这样的:

version: "3"
services:

  proxy:
    image: nginx:alpine
    networks:
      - host
      - network1
    volumes:
      ./nginx.conf:/etc/nginx/nginx.conf:ro

  app:
    build: ./app
    networks:
      - network1
    ports: "5555:80" # Do I have to associate this with the "host" network somehow?

  networks:
    network1:

然后用这个部署

docker stack deploy network1 -c docker-compose.yml

我是走在正确的道路上,还是我把它弄得太复杂了?如果完全不使用Docker来做这件事会不会更直接?相反,我可以为此创建命名的socket。

如果可以的话,我喜欢使用docker-compose,因为它封装了一些细节,让管理变得更容易(如果它有效的话)。它也为安全漏洞留下了更少的表面。

docker nginx docker-compose gunicorn nginx-reverse-proxy
1个回答
0
投票

在阅读了 这条 经过一番试错,我发现问题出在主机iptables除了22端口(ssh)之外,几乎所有的请求都会被删除。

比如说

$ docker run -it --rm --add-host host.docker.internal:xxx.xxx.xxx.xxx busybox telnet host.docker.internal 27017

超时了

但是

$ docker run -it --rm --add-host host.docker.internal:xxx.xxx.xxx.xxx busybox telnet host.docker.internal 22
Connected to host.docker.internal

我也许可以在iptables中用一个简单的规则来解决这个问题。

-A INPUT -i docker0 -j ACCEPT

然后在我的docker -compose.yaml中添加一个部分:

extra-hosts:
  - "host.docker.internal:xxx.xxx.xxx.xxx"

因为我的项目负责人让我等一下,所以我现在先不做了。

© www.soinside.com 2019 - 2024. All rights reserved.