docker -составьте приложение за обратным прокси, которое также может получить доступ к внешним сервисам - PullRequest
0 голосов
/ 05 мая 2020

На локальном сервере я запустил несколько экземпляров gunicorn, каждый из которых запускал разные веб-приложения на уникальном порте в качестве службы для остальной части внутренней сети. Теперь я хочу разместить каждый экземпляр Gunicorn за собственным обратным прокси-сервером nginx для лучшей балансировки нагрузки.

Я решил попробовать развернуть каждую пару (nginx, gunicorn) в собственном контейнере Docker, открывая для внешнего мира только ее уникальный порт. Я знаю, что с переадресацией портов это достаточно просто - например, «5555: 80». Однако каждое приложение также обращается к внешним службам, таким как базы данных, которые работают на одном узле независимо от Docker.

Путем проб и ошибок я обнаружил, что контейнер Docker может получить доступ к внешней службе (например, MySQL или MongoDB), только если я запускаю его как «docker run --network = host. .. ». Это дает возможность контейнеру совместно использовать хост-сеть, но также предоставляет доступ к любым открытым портам, что означает, что он оставляет возможность клиенту обойти обратный прокси-сервер. Хотя все это выполняется на локальном сервере в защищенной сети, это не кажется хорошей практикой безопасности, поскольку оставляет внутреннюю часть открытой для атак типа «отказ в обслуживании».

Итак, я думаю, мне нужно лучшее из обоих миров - я хочу, чтобы каждая пара (прокси, пулеметчик) разговаривала друг с другом по частной сети, которую используют только они, в то время как я открываю один порт (например, «5555» ) в сеть, а веб-приложение, работающее под управлением Gunicorn, по-прежнему может получать доступ к другим службам на том же хосте.

Мой 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? Вместо этого я мог бы создать для этого именованные сокеты.

Мне нравится использовать docker -compose, если я могу, потому что он инкапсулирует некоторые детали и упрощает управление (если это работает). Это также оставляет меньше места для нарушения безопасности.

1 Ответ

0 голосов
/ 05 мая 2020

Прочитав этот поток и немного проб и ошибок, я понял, что проблема в том, что хост iptables отбрасывает запросы практически на все, кроме порта 22 (s sh).

Например:

$ 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"

Я пока откладываюсь, потому что руководитель проекта попросил меня подождать.

...