skip to Main Content

I have multiple private ipv4 addresses on my machine (each one bound to a separate public IP address)

10.0.0.4
10.0.0.5
10.0.0.6
10.0.0.7
10.0.0.8

When I run my application which uses each IP address to perform some requests everything works fine and as expected. However, when I try to run it in docker my application claims that it failed to bind to the IP address. I believe this is because docker networking is isolated.

I’m wondering how I can "expose" these ipv4 addresses to my service via a docker-compose.yml file.

2

Answers


  1. You’re right that Docker’s network isolation is involved: your application will see a single unpredictable IP address, and Docker provides a NAT layer that translates the host’s network addresses to this.

    The most common way to set this up is to set your application to bind to 0.0.0.0, "all interfaces". The Compose ports: setting takes an optional IP address part, which also defaults to 0.0.0.0. You can have multiple ports: targeting the same container port, so long as the host IP and port pairs don’t conflict with other bound ports or non-Docker services.

    As a hypothetical example:

    version: '3.8'
    services:
      app:
        image: registry.example.com/app
        environment:
          # Tell the application to listen on all interfaces, port 8080
          BIND_ADDR: '0.0.0.0:8080'
        ports:
          # As the default HTTP service on the first IP address
          - '10.0.0.4:80:8080'
          # On its own port on the last IP address
          - '10.0.0.8:8080:8080'
          # And not on any of the other IP addresses at all
    

    An alternative is to disable Docker’s networking stack with network_mode: host. In this mode your application will see all of the host interfaces directly, and if it has specific logic to selectively bind to them, that will work just as if the program wasn’t running in a container. However, this also disables all other Docker networking functionality: you cannot hide or remap ports, and you cannot communicate with other containers by hostname, only via their published ports. I’d generally discourage host networking, but it might be a reasonable approach to this particular scenario.

    Login or Signup to reply.
  2. You can configure your docker container to use multiple IP addresses, at least in two ways:

    1. Add additional IP addresses inside the container manually:

      container # ip address add 172.17.1.4/32 dev eth0
      container # ip address add 172.17.1.5/32 dev eth0
      ...
      

      Note: These addresses probably need to belong to the container’s subnet, not sure. docker network inspect bridge prints the default bridge network’s subnet, 172.17.0.0/16 for me.

      (source: Multiple ip on same interface in Docker container)

    or

    1. Create multiple bridge networks, each with a different subnet (IP range), then attach your container to these multiple networks.

      For details, see

    Then you can configure your docker host to route (packets from) these different container IP addresses via your different host IP addresses:

    host # iptables -t nat -I POSTROUTING -p all -s 172.17.1.4/32 -j SNAT --to-source 10.0.0.4
    host # iptables -t nat -I POSTROUTING -p all -s 172.17.1.5/32 -j SNAT --to-source 10.0.0.5
    ...
    

    (source: https://serverfault.com/a/686107)

    The end result is, traffic outgoing from your container via the different container IPs is routed via the different host IPs. You can confirm this eg. with:

    container # curl -v --interface 172.17.1.4 <some destination that will show which host IP is used>
    

    Regarding docker compose, I don’t know enough about it to answer that part of your question.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search