dockerdocker-composehaproxy

How to access docker-compose created replicas in haproxy config


I have a simple haproxy.cfg that looks like this:

frontend http
    bind *:8080
    mode http
    use_backend all

backend all
    mode http
    server s1 ws:8080

Now I have a docker-compose file that looks like this:

version : '3.9'

services:
    lb:
        image: haproxy
        ports:
            - "8080:8080"
        volumes:
            - ./haproxy:/usr/local/etc/haproxy
    ws:
        image: myserver

This works fine, but now I want to use replica to scale my server (ws) instance up to 4. I can do this, providing this docker-compose file:

version : '3.9'

services:
    lb:
        image: haproxy
        ports:
            - "8080:8080"
        volumes:
            - ./haproxy:/usr/local/etc/haproxy
    ws:
        image: myserver
        deploy:
            mode: replicated
            replicas: 4

Calling docker-compose up gives me this:

Recreating test_server_ws_1 ... done
Recreating test_server_ws_2 ... done
Recreating test_server_ws_3 ... done
Recreating test_server_ws_4 ... done
Recreating test_lb_1 ... done

But how can I reference now in my haproxy.cfg those 4 replicas? Using anything else than ws:8080 will give me

lb_1  | [ALERT]    (1) : parsing [/usr/local/etc/haproxy/haproxy.cfg:11] : 'server s1' : could not resolve address 'ws_1'.

Just using ws as address in the config (like before) will always forward to ws_4.

How can I configure haproxy correctly to forward to ws_1, ws_2, ws_3 and ws_4 ?


Solution

  • To accomplish this using docker-compose there are two things you should consider:

    1. Set your resolver in HAProxy to use Docker's internal DNS at 127.0.0.11.
    2. Use a server-template in your HAProxy configuration.

    Using Docker's DNS in the configuration will allow HAProxy to use it as a service discovery mechanism when we define the server template in the backend. You can create the resolver in HAProxy like so:

    resolvers docker
        nameserver dns1 127.0.0.11:53
    

    Server templates are a really powerful feature in HAProxy that allows the configuration to update (add/remove) servers based on the DNS response from the resolver. You can create a server-template with the following:

    backend all
        mode http
        server-template nginx- 4 ws:80 check resolvers docker init-addr libc,none
    

    You can read about each flag used in the server-template but I'll walk you through the relevant ones in your configuration. The first item is the server name prefix nginx-, you can set this to any string you want, HAProxy will append it with a number based on the total number of responses from the resolver. The next item 4 is the max servers you want HAProxy to configure, you can adjust this higher or lower as you need. Next is the server:port you have configured for your backend service. And finally setting the resolver for this backend to docker.