Categories
DevOps

How to ensure that HAProxy keep up with Docker name resolution

Ensure that HAProxy keep up with Docker name resolution.

HAProxy works great as a docker container.

$ docker exec haproxy cat /usr/local/etc/haproxy/haproxy.cfg
global
  stats socket /var/run/api.sock user haproxy group haproxy mode 660 level admin expose-fd listeners
  log stdout format raw local0 info

defaults
  mode http
  timeout client 25s
  timeout connect 5s
  timeout server 10000s
  timeout http-request 10s
  timeout tunnel        3600s
  timeout http-keep-alive  1s
  timeout http-request    15s
  timeout queue           30s
  timeout tarpit          60s
  log global

frontend frontend_https
  mode http
  bind :80
  bind *:443 ssl crt /certs/octocat.cloud.pem

  http-request redirect scheme https unless { ssl_fc }

  http-request set-header X-Forwarded-Proto https if { ssl_fc }
  option forwardfor

  acl is_draw hdr(host) -i draw.octocat.cloud
  use_backend draw_backend if is_draw

backend draw_backend
  server draw draw:8080

There is a caveat though as by default backend will not update its servers when you alter these containers.

$ curl https://docs.octocat.cloud/
<html><body><h1>503 Service Unavailable</h1>
No server is available to handle this request.
</body></html>

The solution is to directly define docker resolver and use for every backend server.

$ docker exec haproxy cat /usr/local/etc/haproxy/haproxy.cfg
global
  stats socket /var/run/api.sock user haproxy group haproxy mode 660 level admin expose-fd listeners
  log stdout format raw local0 info

defaults
  mode http
  timeout client 25s
  timeout connect 5s
  timeout server 10000s
  timeout http-request 10s
  timeout tunnel        3600s
  timeout http-keep-alive  1s
  timeout http-request    15s
  timeout queue           30s
  timeout tarpit          60s
  log global

resolvers docker_resolver
  nameserver dns 127.0.0.11:53

frontend frontend_https
  mode http
  bind :80
  bind *:443 ssl crt /certs/octocat.cloud.pem

  http-request redirect scheme https unless { ssl_fc }

  http-request set-header X-Forwarded-Proto https if { ssl_fc }
  option forwardfor

  acl is_draw hdr(host) -i draw.octocat.cloud
  use_backend draw_backend if is_draw

backend draw_backend
  server draw draw:8080 resolvers docker_resolver resolve-prefer ipv4

This will ensure that backend server address will stay up to date whenever you update the target container.