Docker Swarm配置:让同节点HAProxy路由至本地httpd容器
解决Swarm集群中HAProxy优先连接同节点httpd的方案
你需要让全局部署的HAProxy只转发请求到同一节点的httpd容器,同时不暴露httpd端口到外部网络,以下是三种可行方案:
方案一:HAProxy动态发现同节点Swarm任务(推荐)
利用HAProxy原生的Docker Swarm服务发现能力,自动过滤出当前节点的httpd实例:
1. 修改Compose文件
给HAProxy容器挂载Docker socket,用于获取Swarm元数据:
version: "3.9" services: web_ingress: image: haproxy:alpine ports: - target: 80 published: 80 protocol: tcp mode: host - target: 443 published: 443 protocol: tcp mode: host - target: 8000 published: 8000 protocol: tcp mode: host volumes: - type: bind source: /home/haproxy-ingress target: /usr/local/etc/haproxy read_only: true - type: bind source: /etc/letsencrypt/archive target: /etc/letsencrypt/archive read_only: true - type: bind source: /etc/letsencrypt/live target: /etc/letsencrypt/live read_only: true # 挂载Docker socket用于服务发现 - /var/run/docker.sock:/var/run/docker.sock:ro user: root deploy: mode: global frontpage: image: httpd:alpine expose: - 80 volumes: - /home/httpd-frontpage/public-html:/usr/local/apache2/htdocs/ deploy: mode: global
2. 修改HAProxy配置
在global段添加Swarm连接,后端配置过滤同节点任务:
global ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 ssl-default-bind-options prefer-client-ciphers no-sslv3 no-tlsv10 no-tlsv11 no-tlsv12 no-tls-tickets ssl-default-server-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tlsv12 no-tls-tickets user root group root # 连接Docker Swarm socket获取服务元数据 docker /var/run/docker.sock swarm defaults timeout connect 10s timeout client 30s timeout server 10s log global mode http option httplog maxconn 3000 frontend http-ingress bind *:80 bind *:443 ssl crt /usr/local/etc/haproxy/fullchain.pem alpn h2,http/1.1 redirect scheme https code 301 if !{ ssl_fc } default_backend frontpage frontend stats bind *:8404 stats enable stats uri / stats refresh 10s backend frontpage # 仅选择当前节点的frontpage任务,自动动态更新 server-template s 1-10 tasks.frontpage:80 check docker-server-node {{ local_node_name }}
{{ local_node_name }}是HAProxy内置变量,自动匹配当前节点名称,确保只路由到本地httpd容器。
方案二:启动脚本动态获取本地httpd容器IP
通过自定义启动脚本,在HAProxy启动时查询本地节点的httpd容器IP并替换配置:
1. 修改Compose文件
添加Docker socket挂载和自定义启动命令:
web_ingress: # ... 原有配置 ... volumes: # ... 原有挂载 ... - /var/run/docker.sock:/var/run/docker.sock:ro # 自定义启动脚本,替换后端地址为本地httpd的IP command: ["/bin/sh", "-c", "LOCAL_WEB_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -q -f name=frontpage -f node=$(hostname))); sed -i 's/frontpage:80/$LOCAL_WEB_IP:80/g' /usr/local/etc/haproxy/haproxy.cfg; haproxy -f /usr/local/etc/haproxy/haproxy.cfg"]
2. 保持原有HAProxy配置
只需确保后端配置初始为frontpage:80,启动脚本会自动替换为本地IP。
方案三:绑定回环地址的主机网络模式
让httpd仅绑定本地回环地址(127.0.0.1),避免端口暴露到外部,HAProxy直接通过回环访问:
1. 修改frontpage的Compose配置
frontpage: image: httpd:alpine # 让httpd仅监听127.0.0.1,不对外暴露 command: ["httpd", "-D", "FOREGROUND", "-c", "Listen 127.0.0.1:80"] volumes: - /home/httpd-frontpage/public-html:/usr/local/apache2/htdocs/ deploy: mode: global network_mode: host
2. 修改HAProxy后端配置
backend frontpage server s0 127.0.0.1:80 check
这种方法无需额外服务发现配置,httpd端口仅在节点本地回环可用,不会被外部访问。
内容的提问来源于stack exchange,提问作者user80551
相关产品推荐
相关产品推荐

