На данный момент я реализовал фляжное приложение, связанное с базой данных mysql, и вся реализация работает на одном веб-сервере.
Чтобы не раскрывать свое приложение публично, я запускаю его на локальном интерфейсе сервера и открываю только общедоступный интерфейс (порт 443) через haproxy, который перенаправляет трафик на интерфейс localhost.
Конфигурацию docker-compose и haproxy можно найти ниже
докер-составить:
version: '3.1'
services:
db:
image: mysql:latest
volumes:
- mysql-volume:/var/lib/mysql
container_name: mysql
ports:
- 127.0.0.1:3306:3306
environment:
MYSQL_ROOT_PASSWORD: xxxxxx
app:
#environment:
# - ENVIRONMENT=stage
# - BUILD_DATETIME=$(date +'%Y-%m-%d %H:%M:%S')
build:
context: .
dockerfile: Dockerfile
#labels:
# - "build_datetime=${BUILD_DATETIME}"
container_name: stage_backend
ports:
- 127.0.0.1:5000:5000
volumes:
mysql-volume:
driver: local
пример конфигурации haproxy:
global
log /dev/log local0
log /dev/log local1 notice
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 10s
timeout client 30s
timeout server 30s
frontend test
bind *:80
bind *:443 ssl crt /etc/letsencrypt/live/testdomain.com/haproxy.pem alpn h2,http/1.1
redirect scheme https if !{ ssl_fc }
mode http
acl domain_testdomain hdr_beg(host) -i testdomain.com
use_backend web_servers if domain_testdomain
backend web_servers
timeout connect 10s
timeout server 100s
balance roundrobin
mode http
server test_server 127.0.0.1:5000 check
Таким образом, haproxy работает на общедоступном интерфейсе как служба через systemd (не в контейнерах), а контейнеры работают на локальном хосте.
Вскоре это станет производственной установкой, поэтому я хочу развернуть кластер Docker Swarm с одним узлом только на этом сервере, поскольку реализация Docker Swarm более безопасна в производственной среде.
Мой вопрос в том, как я могу развернуть это на рое докеров.
Есть ли смысл оставить haproxy в качестве службы systemd и как-то заставить его перенаправлять запросы в кластер docker swarm?
Является ли более простой/лучшей реализацией также контейнеризация haproxy и размещение ее внутри кластера в качестве службы создания докеров?
Если я буду следовать второму подходу, как мне заставить его работать на интерфейсе, отличном от интерфейса приложения (haproxy --> public, flask & db --> localhost)
Опять же, я говорю здесь об одном сервере, поэтому я пытаюсь разделить сетевые интерфейсы и выставлять haproxy только на 443 на общедоступном интерфейсе.
В идеале я не хотел переходить с haproxy на обратный прокси-сервер nginx, так как я знаком с ним и с тем, как именно там работает завершение ssl, но я открыт для любой другой реализации, которая имеет больше смысла.


Кажется, вы слишком много думаете о вещах и в процессе отбрасываете функции безопасности, которые предлагает докер.
во-первых, Docker предоставляет вам частную сеть из коробки как в режиме создания, так и в режиме роя. создается неявная сеть с именем <stack>_default, и к ней присоединяются службы, а разрешение DNS настраивается в каждом контейнере для разрешения каждого имени службы.
Итак, если ваше приложение и база данных не объявляют явно какие-либо сети, тогда применяются следующие неявные объявления, и ваше приложение может напрямую подключаться к базе данных, используя строку подключения mysql://db:3306.
Контейнеру db не нужно ни публиковать, ни пытаться защитить доступ к этому порту, доступ будут иметь только другие контейнеры, подключенные к сети [stack_]default.
networks:
default: # implicit
services:
app:
networks:
default: # implicit
environment:
MYSQL: mysql://db:3306 #
db:
networks:
default: # implicit
На данный момент вам решать, запускать HAProxy как службу или нет. Лично я бы (сделал). В рое удобно иметь единую службу, которая обрабатывает вход :80 и :443, выполняет разгрузку, а затем использует сети докеров для направления трафика к другим службам на любом сервисе: порты обрабатывают эти соединения.
Я использую Traefik, а не HAProxy, так как он может использовать сервисные метки для динамической маршрутизации трафика, но в любом случае наличие HAProxy в качестве сервиса означает, что если вы продолжите его использовать, вам будет проще развертывать обновления конфигурации HAProxy.
Если он работает как служба докеров И подключен к тем же сетям докеров, то он может использовать разрешение DNS докеров для разрешения имен служб.
Спасибо за быстрый ответ. Дело в том, что я хочу запустить haproxy на другом сетевом интерфейсе, чем будут работать контейнеры. Как я уже упоминал, у меня есть только 1 сервер, и я хочу запустить haproxy на общедоступном интерфейсе (чтобы быть доступным из Интернета) и контейнеры на локальном хосте (чтобы не открывать их общедоступному Интернету). Как это можно сделать?
Как я уже сказал - вы слишком много думаете об этом. Docker обеспечивает такую безопасность за счет виртуализации сетевых интерфейсов, и вы просто вообще не привязываете серверные службы к физическому интерфейсу. Если вы войдете в контейнер, вы увидите, что сеть по умолчанию соответствует устройству «eth0», имеющему частный IP-адрес. Docker создает эти vxlan с использованием правил iptables и может создавать многие из них, позволяя стекам сервисов, совместно размещенным на одном физическом хосте, иметь изолированные сети, которые другие стеки не могут перехватывать, не говоря уже о других сетевых хостах.
Большое спасибо за ответ, немного прояснил ситуацию. Если я использую haproxy в качестве службы, и она не является частью кластера, сможет ли он разрешить каждый запущенный экземпляр контейнера приложения, просто указав имя контейнера в конфигурации haproxy?