Map #Docker container ports to virtual IPs in Linux with docker-compose

By | February 15, 2018

Sometimes you need to export multiple instances of the same service with a specific IP using same port outside of a docker swarm environment.
Using docker swarm environment is easy to have several instances of the same service exporting some API on the same port. The swarm will take care of load balancing the services and ports will not clash. But what if we need to have several instances of the same service (running as a container) that we want to load balance from outside a docker swarm.
The solution is to use virtual IPs and map the service ports not to the local host but to the virtual IPs.

STEP 1: Define virtual interfaces under Linux

With the following we define 3 virtual interfaces.

ip link add virtual0 link enp2s0 type macvlan mode bridge
ip link add virtual1 link enp2s0 type macvlan mode bridge
ip link add virtual2 link enp2s0 type macvlan mode bridge

STEP 2: Add the virtual IPs

With the following we add 3 virtual IPs to the defined virtual interfaces.

ip address add 40.0.0.101/24 broadcast 40.0.0.255 dev virtual0
ip address add 40.0.0.102/24 broadcast 40.0.0.255 dev virtual1
ip address add 40.0.0.103/24 broadcast 40.0.0.255 dev virtual2

STEP 3: Bring them up

With the following we bring up the IPs

ip link set virtual0 up
ip link set virtual1 up
ip link set virtual2 up

STEP 4: Define services using the virtual IPs

The following is an example of how to define 3 jetty based services in a docker-compose that use the virtual IPs.

    node1:
       image: jetty
       volumes:
         - /home/docker-volumes/node1:/opt/jetty.base/node:Z
       env_file:
         - ./node.env
       ports:
         - "40.0.0.101:8080:8080"
         - "40.0.0.101:8443:8443"
         - "40.0.0.101:9101:9101"
       working_dir: /opt/jetty.base/node/
       command: ["./start.sh"]

    node2:
       image: jetty
       volumes:
         - /home/docker-volumes/node2:/opt/jetty.base/node:Z
       env_file:
         - ./node.env
       ports:
         - "40.0.0.102:8080:8080"
         - "40.0.0.102:8443:8443"
         - "40.0.0.102:9101:9101"
       working_dir: /opt/jetty.base/node/
       command: ["./start.sh"]

    node3:
       image: jetty
       volumes:
         - /home/docker-volumes/node3:/opt/jetty.base/node:Z
       env_file:
         - ./node.env
       ports:
         - "40.0.0.103:8080:8080"
         - "40.0.0.103:8443:8443"
         - "40.0.0.103:9101:9101"
       working_dir: /opt/jetty.base/node/
       command: ["./start.sh"]

With the above definition I can have now three instances of the same jetty based service exporting an API on the 8080 (http) and 8443 (https) ports but having different IPs.
A load balancing can be done now on this IPs outside a swarm.

Contribute to this site maintenance !

This is a self hosted site, on own hardware and Internet connection. The old, down to earth way 🙂. If you think that you found something useful here please contribute. Choose the form below (default 1 EUR) or donate using Bitcoin (default 0.0001 BTC) using the QR code. Thank you !

€1.00

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.