Multiple Instance in docker compose and DNS

Continuing from the previous article.

Problem: how do you run multiple instances of a container and still use the same dns lookup mechanism.

Assumptions:

given the following docker-compose.yml with the addition of adding the traefik configuration.

services:
  container1:
    container_name: container1
    image: ...  
    ports:
      - "100:100"
      
  container2:
    container_name: containerA 
    image: containerA
    ports:
      - "200:200"
    
  container2A:
    container_name: containerA
    image: containerA
    ports:
      - "200:200"
      
  traefik:
    container_name: traefiklb
    image: ...
    ports:
      - "8180:8080"
      - "200:200"
    command:
      - "--entrypoints.web.address=:200"
      

Details

Our goal is to try to get multiple containers (container2 and container2a) to run at the same time.  Our command will be docker compose up container1 container2 container2a traefik.    Any guesses what will happen?

As hinted in the previous posts, you will get a conflict - something like:

services.deploy.replicas: can't set container_name ... as container name must be unique: invalid compose project.

So, lets fix this part - a modified docker compose file looks like this:

services:
  container1:
    container_name: container1
    image: ...  
    ports:
      - "100:100"
      
  container2:
    container_name: containerA 
    image: containerA
    ports:
      - "200:200"
    
  container2A:
    image: containerA
    ports:
      - "200:200"
      
  traefik:
    container_name: traefiklb
    image: ...
    ports:
      - "8180:8080"
      - "200:200"
    command:
      - "--entrypoints.web.address=:200"

the only change here is to remove container_name parameter from container2A.

ok, lets try our docker compose up command again.  While we get further, there is still a problem - this time with the ports.  You will get an error something like:

Error response from daemon: driver failed programming external connectivity on endpoint ...: bind for 0.0.0.0:200 failed: port is already allocated

Essentially our container2 and container2A do not conflict from a dns perspective, but do conflict on ports.

Ok, one more change:

services:
  container1:
    container_name: container1
    image: ...  
    ports:
      - "100:100"
      
  container2:
    container_name: containerA 
    image: containerA
    ports:
      - "200"
    
  container2A:
    image: containerA
    ports:
      - "200"
      
  traefik:
    container_name: traefiklb
    image: ...
    ports:
      - "8180:8080"
      - "200:200"
    command:
      - "--entrypoints.web.address=:200"

the change is the ports from "200:200" to just "200".  Docker compose has the concept of internal and external port exposure.  In the case of container1, port 100 is exposed outside of the docker compose network.  It is _also_ used inside the docker compose network.  When we changed the port configuration in container2 to just "200", we configured docker compose to use port 200 for just the internal network, not the external network.  And since each container gets its own IP address, then we do not have a port conflict anymore. 

Now lets look at how the network looks when we run our docker compose up command.

  • Windows ip: 172.168.0.1 or some such
  • container1 ip: 172.18.0.2, external port: 100, internal port: 100
  • container2 ip: 172.18.0.3, external port: none, internal port: 200
  • container2a ip: 172.18.0.4 external port: none, internal port: 200
  • docker compose dns: 172.18.0.1

So, how does this allow us to run multiple instances of container2 while still using the same DNS lookup mechanism? A bit my hook and crook - there are multiple instances of container2 (image=containerA), and container1 can use the same container lookup mechanism.  The details are that container1 will only ever find container2 (image: containerA) using this mechanism.  That is, while we are running multiple instances of _image_ containerA, we are only ever using connecting to one of them. 

In the next post, we hit how we can load balance externally to all instances.

references:

Comments

Popular Posts