Sign inSign up

lettore/haproxy

By lettore

Updated 3 days ago

Multi architecture version of haproxytech/haproxy with keepalived builtin

Image
0

10K+

lettore/haproxy repository overview

Docker Swarm HAproxy with Keepalived builtin


Purpose

I use HAproxy as loadbalancer in my home cluster running on Docker Swarm, as I need to point my clients to a single IP address I added two functions to the HAproxy base image. If you just run a single container you can set a fixed static IP so every clients on your network can connect to the proxy container. In my setup I prefer to run multiple instances of HAproxy and set a virtual IP that points to the container on the preferred machine. To do this I have multiple services running a single instance on a specific machine, and every machine have it's priority so I'm sure that all traffic is flowing on the most powerful machine. This is a master/backup setup, and is not load balancing the load on the HAproxy service. I'm using this with macvlan network setup in docker.

Configuration

Docker

Setting the IP address require the container to be started with cap-add NET_ADMIN at least. Starting from Docker 20.10 you can run Swarm services with added capabilities, so you should have at least Docker 20.10 running on every machine.

Just run the following command to enable NET_ADMIN

docker service update --cap-add NET_ADMIN HAproxy_server

Beaware that using the macvlan network will espose every ports of the container on the selected IP, declaring the ports will only affect the host networking. Using host mode is required if you want to run multiple services with the same exposed ports, obviously Docker will not let you run multiple containers on the same machine as the ports will be already used.

HAProxy

HAProxy is configured by a configuration file, haproxy.cfg, please map the folder that contains haproxy.cfg to docker container volume /etc/haproxy, a simple sample haproxy.cfg is listed below:

global
    daemon
    maxconn 256

defaults
    mode http
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms

frontend http-in
    bind *:80
    default_backend servers

backend servers
    server tomcat1 192.168.1.52:8888 maxconn 32
    server tomcat2 192.168.1.53:8888 maxconn 32
keepalived

Keepalived is configured by environment variables as below

  • INTERFACE: interface to set virtual IP
  • VIRTUAL_IP: vip
  • VIRTUAL_MASK: vip mask
  • STATE: master or backup
  • VIRTUAL_ROUTER_ID: must be the same in all nodes
  • PRIORITY: 101 on master, 100 on backups

Use this combination of entrypoint and command: entrypoint: /keepalived-entrypoint.sh command: "haproxy -f /usr/local/etc/haproxy/haproxy.cfg"

static ip

Static IP is configured by environment variables as below

  • INTERFACE: interface to set virtual IP
  • STATIC_IP: static ip

Use this combination of entrypoint and command: entrypoint: /ip-entrypoint.sh command: "haproxy -f /usr/local/etc/haproxy/haproxy.cfg"

normal usage

If you don't set the entrypoint the container will start as a HAproxy standard image.

Usage with Docker Swarm

Swarm stack for Keepalived

version: "3.7"
services:
  server:
    image: lettore/haproxy:2.4-master
    cap_add:
      - NET_ADMIN    
    environment:
      - STATIC_IP=192.168.3.11
      - INTERFACE=eth0
      - STATE=MASTER
      - VIRTUAL_ROUTER_ID=51
      - PRIORITY=100
      - VIRTUAL_IP=192.168.3.11
      - VIRTUAL_MASK=24
    hostname: '{{.Node.Hostname}}'
    restart: always
    volumes:
      - /storage/shared/docker/haproxy:/etc/haproxy  
    deploy:
      mode: replicated
      replicas: 1    
      restart_policy:
        delay: 10s
        max_attempts: 10
        window: 60s
      placement:
        constraints:
          - node.hostname==server
    ports:
      - target: 80
        published: 80
        mode: host   
      - target: 443
        published: 443   
        mode: host          
    networks:
      prod:
      macvlan-3:
        aliases:
          - server.haproxy.docker
          
    entrypoint: /keepalived-entrypoint.sh
    
    command: "haproxy -f /usr/local/etc/haproxy/haproxy.cfg"

  nas:
    image: lettore/haproxy:2.4-master
    cap_add:
      - NET_ADMIN    
    environment:
      - STATIC_IP=192.168.3.11
      - INTERFACE=eth0
      - STATE=BACKUP
      - VIRTUAL_ROUTER_ID=51
      - PRIORITY=90
      - VIRTUAL_IP=192.168.3.11
      - VIRTUAL_MASK=24
    hostname: '{{.Node.Hostname}}'
    restart: always
    volumes:
      - /storage/shared/docker/haproxy:/etc/haproxy  
    deploy:
      mode: replicated
      replicas: 1    
      restart_policy:
        delay: 10s
        max_attempts: 10
        window: 60s
      placement:
        constraints:
          - node.hostname==NAS
    ports:
      - target: 80
        published: 80
        mode: host   
      - target: 443
        published: 443   
        mode: host          
    networks:
      prod:
      macvlan-3:
        aliases:
          - nas.haproxy.docker
          
    entrypoint: /keepalived-entrypoint.sh
    
    command: "haproxy -f /usr/local/etc/haproxy/haproxy.cfg"

  rpi:
    image: lettore/haproxy:2.4-master
    cap_add:
      - NET_ADMIN    
    environment:
      - STATIC_IP=192.168.3.11
      - INTERFACE=eth0
      - STATE=BACKUP
      - VIRTUAL_ROUTER_ID=51
      - PRIORITY=80
      - VIRTUAL_IP=192.168.3.11
      - VIRTUAL_MASK=24
    hostname: '{{.Node.Hostname}}'
    restart: always
    volumes:
      - /storage/shared/docker/haproxy:/etc/haproxy  
    deploy:
      mode: replicated
      replicas: 1    
      restart_policy:
        delay: 10s
        max_attempts: 10
        window: 60s
      placement:
        constraints:
          - node.hostname==RPI-SERVER
    ports:
      - target: 80
        published: 80
        mode: host   
      - target: 443
        published: 443   
        mode: host          
    networks:
      prod:
      macvlan-3:
        aliases:
          - rpi.haproxy.docker
          
    entrypoint: /keepalived-entrypoint.sh
    
    command: "haproxy -f /usr/local/etc/haproxy/haproxy.cfg"
        
networks:
  prod:
    external: true       
  macvlan-3:
    external: true       

Swarm stack for Static IP

version: "3.7"
services:
  haproxy:
    image: lettore/haproxy:2.4-master
    cap_add:
      - NET_ADMIN    
    environment:
      - STATIC_IP=192.168.3.11
      - INTERFACE=eth0
    hostname: '{{.Node.Hostname}}'
    restart: always
    volumes:
      - /storage/shared/docker/haproxy:/etc/haproxy  
    deploy:
      mode: replicated
      replicas: 1    
      restart_policy:
        delay: 10s
        max_attempts: 10
        window: 60s
      placement:
        constraints:
          - node.hostname==server
    ports:
      - target: 80
        published: 80
        mode: host   
      - target: 443
        published: 443   
        mode: host          
    networks:
      prod:
      macvlan-3:
        aliases:
          - haproxy.docker
          
    entrypoint: /ip-entrypoint.sh
    
    command: "haproxy -f /usr/local/etc/haproxy/haproxy.cfg"
        
networks:
  prod:
    external: true       
  macvlan-3:
    external: true       

Swarm stack for normal HAproxy usage

version: "3.7"
services:
  haproxy:
    image: lettore/haproxy:2.4-master
    cap_add:
      - NET_ADMIN    
    hostname: '{{.Node.Hostname}}'
    restart: always
    volumes:
      - /storage/shared/docker/haproxy:/etc/haproxy  
    deploy:
      mode: replicated
      replicas: 1    
      restart_policy:
        delay: 10s
        max_attempts: 10
        window: 60s
      placement:
        constraints:
          - node.hostname==server
    ports:
      - target: 80
        published: 80
      - target: 443
        published: 443            
    networks:
      prod:
        
networks:
  prod:
    external: true             

Disclaimer


This image is built for my personal use, I'm not an IT specialist so use it only if you know what you're doing.

Tag summary

Content type

Image

Digest

sha256:5507fb7af

Size

330.1 MB

Last updated

3 days ago

docker pull lettore/haproxy