Search code examples
dockerdocker-composedocker-containerdocker-network

how to bring up containers with hostname and ip addresses such that they run serially?


Here is sample docker compose configuration for bringing up a simple directory listing service(dirlist):

version: "3"
services:
  dirlist:
    image: ubuntu-python
    networks:
      app_net:
        ipv4_address: "172.19.0.10"
    hostname: maca
    volumes:
      - /home/arun/misc:/misc
    working_dir: /misc

  curlcmd:
    image: ubuntu-curl
    command: curl -s http://maca:8000/readme1.txt
    extra_hosts:
      - "maca:172.19.0.10"
    depends_on:
      - web
    networks:
      app_net:

networks:
  app_net:
    ipam:
       driver: default
       config:
         - subnet: "172.19.0.0/24"

I want to create replicas of dirlist such that each containers spawned thereof have the following:

  1. ip addresses should be serial. For e.g. 1st container must have ip address 172.19.0.10, 2nd one - 172.19.0.11, 3rd - 172.19.0.12, and, so on...Ip addresses being selected randomly from a range is also okay, however, #3 requirement should also be met.
  2. Their hostnames should also appear to have serial pattern - say the 1st container has dirlist1 as hostname, 2nd one has dirlist2, etc...
  3. All such containers (of dirlist) should also appear as extra_hosts (with their corresponding names and ip addresses) for the service which depend on dirlist (i.e. curlcmd as per example).

Solution

  • All of the networking functionality you describe, Docker Compose does on its own: it can assign IPv4 addresses within some range (a unique CIDR block per Docker private network), and it provides an internal DNS system so that service names are directly usable as host names, without specifying extra_hosts. That is, with a single replica, this much shorter Compose file will work just fine:

    version: "3"
    services:
      dirlist:
        image: ubuntu-python
      curlcmd:
        image: ubuntu-curl
        command: curl -s http://dirlist:8000/readme1.txt
    

    I am relying on the default network provided by Compose out-of-the-box, assuming that the files you want to run are COPYed into your Docker image, and also assuming the Dockerfile has the correct WORKDIR already. I've skipped all of the networks: setup to use the defaults, and there's no particular need to set a per-container hostname: (it doesn't do anything visible outside the container itself).

    Compose on its own doesn't directly support replicated services. If you run this in combination with Docker's Swarm cluster service, you can specify replicas: for the dirlist service and I think that essentially meets your requirements, but for a single host you may not want to set up Swarm.

    The other thing you can do is use a text templating tool to create the docker-compose.yml file. For example, using Jinja, I might write:

    version: "3"
    services:
    {%- for i in range(1, 6) %}
      dirlist{{ i }}:
        image: ubuntu-python
    {%- endfor %}
      curlcmd:
        image: ubuntu-curl
        command: curl -s http://dirlist1:8000/readme1.txt
    

    In Compose there's no way for the curlcmd container to discover how many replicas there are, though if it knows they follow this specific pattern it can simply iterate through hostnames until it fails.