You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 07:45:37