3

I'm trying to setup a docker based system with the least amount of network abstraction/virtualization possible. This is why I avoided k8s and am trying docker-swarm instead.

I'd like haproxy to be started directly via systemd and listen to external traffic on ports 80/443 directly, i.e. without docker coming into the picture. However, when proxying traffing to backend servers, I'd like it to connect to docker-swarm services running in dnsrr mode.

How do I set this up? I've read this blog post multiple times, but in all three configurations it seems that haproxy itself is running as a docker-swarm service. I do not want any network "abstraction" to come between haproxy and customer-facing traffic.

Is a setup like this possible?

PS: A related question might be, how do I communicate between the host and a docker-swarm container running on the same host? I tried pinging 10.0.6.75 (the container's IP address) on the same host on which it was running, but it didn't work. Do I need to create some network route, or make some entry in iptables to get this to work?

Saurabh Nanda
  • 6,373
  • 5
  • 31
  • 60

1 Answers1

0

If you use docker, you can't avoid a layer of network abstraction, because it creates a virtual network with it's own routes and should be inaccesible to your host networks by default.

If all you want is to make docker services accessible without the hassle, I'd recommend you to use traefik to track docker services instead of haproxy. But, if you insist in using HAproxy, you can either:

Run haproxy inside a docker container

And expose it to the host network.

# add this service to your swarm configuration
version: "3.3"
services:
  proxy:
    image: haproxy
    configs:
      - source: haproxy
        target: /etc/haproxy/haproxy.cfg
    ports:
      # Add here all the ports you want managed by haproxy
      - '80:80'
      - '443:443'
# this is your current haproxy config
configs:
  haproxy:
    file: ./haproxy.conf

Use a host networking for your docker services

version: "3.3"
# add this network to your swarm configuration
networks:
  host:
    driver: host
services:
  app:
    image: whatever
    ...
    # add this network to your apps
    networks:
      host:

Manually bind the HAproxy service to the network interface(s)

Inspect the docker network for your services.

$ docker network ls
NETWORK ID     NAME                               DRIVER    SCOPE
4d992742292c   bridge                             bridge    local
$ docker network inspect ${ID_OR_NAME}
[
    {
       "Name": "bridge",
       "Id": "4d9927...",
       "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
       },
       ...
       "Options": {
            ...
            "com.docker.network.bridge.name": "docker0",
       }
...

Add to your haproxy configuration:

service network DEVICE # i.e. docker0
  auto off
  ip address 172.17.0.11 # ensure it's available
  ip route 172.17.0.1 172.17.0.1
xihh
  • 169
  • 2
  • 12
  • My understanding of docker networking might be wrong, but I noticed that even when I use host networking with docker-swarm, there is a `docker-proxy` process that is listening to the port in question on the host's network. Is this expected? And if it is, then is there _any_ way whatsoever to get haproxy to listen to on the port on the host's network? – Saurabh Nanda Apr 07 '22 at 07:18
  • Does `traefik` does this out-of-the-box, i.e. the external port is controlled directly by traefik and it proxies the traffic to docker's virtual network? Is traefik as stable and scalable as haproxy? I'm not hung-up on haproxy, but I'm concerned about having too many layers of abstraction/virtualization for a front-facing proxy component, which needs to be super-fast. – Saurabh Nanda Apr 07 '22 at 07:19
  • I can run a docker container via `--net host` where the port/socket is directly controlled by the underlying process and not `docker-proxy`. How do I achieve this in `docker compose`. That would be a first step, right? – Saurabh Nanda Apr 07 '22 at 08:01