Troubleshooting HAProxy Access Issue in Docker-Compose Setup

130 Views Asked by At

I'm new to Docker and have been trying to get a simple docker-compose setup working However, I'm facing an issue:
although I can directly access the web application on the exposed port 82, I can't seem to reach it via HAProxy on the exposed port 81. I'm currently using Docker version 25.0.3.
Can anyone help me figure out what I might be missing in my configuration?

version: '3'
services:
  webapp:
    image: httpd
    ports:
     - 82:80

   lb:
     image: 'dockercloud/haproxy:latest'
     volumes:
        - /var/run/docker.sock:/var/run/docker.sock
     links:
       - webapp
     ports:
      - 81:80
2

There are 2 best solutions below

3
VonC On

Your setup looks like this:

       Internet
           |
          [81]
       HAProxy
           |
          [80]
        Web App
           |
          [82]
  • Requests come in on port 81 (HAProxy), which should then forward them to the web application listening on port 80 inside its container.
  • The web app container maps port 80 internally to port 82 externally.

Try the following docker-compose.yml file for a proper networking and communication between the webapp and lb services:

version: '3'
services:
  webapp:
    image: httpd
    ports:
      - 82:80
    networks:
      - webnet

  lb:
    image: 'dockercloud/haproxy:latest'
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    ports:
      - 81:80
    depends_on:
      - webapp
    networks:
      - webnet

networks:
  webnet:

As suggested, the links: option is obsolete and not necessary for modern Docker networking. Containers in the same network can discover and communicate with each other by service names.

This defines a custom network webnet and assigned both services to it. That makes sure they can communicate using the service name as the hostname.
Make sure your HAProxy configuration within the dockercloud/haproxy container is correctly set up to route traffic to the webapp service. HAProxy needs to know the correct service name and port to forward requests appropriately.

docker exec -it [container_id_or_name] /bin/sh
cat /etc/haproxy/haproxy.cfg
...
# you should see a backend section like:
backend http_back
    balance roundrobin
    server webapp webapp:80 check

And check that HAProxy is configured to listen on 0.0.0.0:80 or *:80 to make sure it accepts connections from all IP addresses, at least for testing.


Still not working, but when I checked haproxy.cfg backend section, it looks like this:

backend app 
balance roundrobin 
server app1 127.0.0.1:5001 check 
server app2 127.0.0.1:5002 check 
server app3 127.0.0.1:5003 
check server app4 127.0.0.1:5004 check 

and no other containers are currently active

I tried to use port 5001 instead of 81, but still no luck

If auto-discovery is failing and you have specific routing needs, consider manually specifying your HAProxy configuration. You can mount a custom haproxy.cfg file into a standard HAProxy container, replacing dockercloud/haproxy for debugging purposes:

version: '3'
services:
  webapp:
    image: httpd
    networks:
      - webnet

  haproxy:
    image: haproxy:latest
    volumes:
      - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
    ports:
      - "81:80"
    networks:
      - webnet

networks:
  webnet:

In haproxy.cfg, explicitly define the backend to point to your webapp service, making sure it matches the service name and port within the Docker network:

backend webapp_backend
    balance roundrobin
    server webapp webapp:80 check

But this eliminates mounting /var/run/docker.sock:/var/run/docker.sock, which makes it possible for HAProxy to interact with the Docker daemon to inspect and list running containers, without it, I have to set every running container manually.

Then make sure all your containers (especially the webapp service) have the correct labels that dockercloud/haproxy expects for auto-discovery. And check the logs of the HAProxy container for any errors or warnings that might indicate why it is not correctly identifying and configuring backends based on the running containers. ()docker logs [haproxy-container-id] to check the logs).

If the auto-discovery feature is not working as expected with the dockercloud/haproxy image, consider two alternatives:

  • Extend the dockercloud/haproxy image with a custom Dockerfile, where you can adjust or replace the startup script to better handle your discovery requirements or fix issues with the current discovery mechanism.
  • Or, switch to another dynamic HAProxy docker image: there are other HAProxy Docker images or third-party solutions designed to work with Docker and provide dynamic backend discovery. These might offer more flexibility or compatibility with your specific Docker setup.

As a compromise between fully manual configuration and dynamic auto-discovery, you can use a simple automation script that updates the HAProxy configuration based on the current state of running containers. That would involve:

  • writing a script that uses Docker CLI commands (e.g., docker container ls) to discover running containers and generate an HAProxy configuration file based on this information.

  • scheduling the script at regular intervals or triggering it based on specific events (e.g., container start/stop) to keep the HAProxy configuration updated.

If you are running in a more complex environment and need robust service discovery and load balancing, consider Docker Swarm Mode, or even Kubernetes.

0
deep bajaj On

I think there are some issues with your docker file.

  1. links is no more used and is dropped by dockers now depends_on is to be used.
  2. Your docker should look something as below
services:
  webapp:
    image: httpd
    networks:
      - mynetwork

  lb:
    image: haproxy:latest
    volumes:
      - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
    ports:
      - "81:80"
    networks:
      - mynetwork

networks:
  mynetwork

Additionally you may be required to use a custom haproxy.cfg


backend webapp_backend
    balance roundrobin
    server webapp webapp:80 check