Multi-container docker on AWS - Nginx use host machine /etc/hosts resolver

I have a multi-container docker environment on Amazon Elastic Beanstalk with the following Dockerrun.aws.json file:

{ 
    "AWSEBDockerrunVersion": 2, 
    "containerDefinitions": [ 
      { 
        "name": "web", 
        "memoryReservation": 256, 
        "image": "my/nginx/repo/image",  
        "portMappings": [ 
          { 
            "hostPort": 80, 
            "containerPort": 80 
          } 
        ], 
        "links": [ 
          "api" 
        ], 
        "essential": true 
      }, 
      { 
        "name": "api", 
        "memoryReservation": 256, 
        "image": "my-api/repo", 
        "essential": true, 
        "portMappings": [ 
          { 
            "hostPort": 3000, 
            "containerPort": 80 
          } 
        ]
      } 
    ] 
  }

Ultimately I want the node app served by nginx to resolve requests to named addresses from linked containers, so in my web image (node app) I'd like to make a request to http://api/some/resource and let nginx resolve that to the api container.

Now, since docker adds a host entry for the api container due to the specified link, I want the nginx server to resolve addresses from the hosts etc/hosts file, however as I found out, nginx uses it's own resolver. After researching the issue a bit I found out that in non-Elastic Beanstalk multi-container solutions and with user-defined networks, the resolver would be provided by docker on 127.0.0.11, however since it is currently not possible to define user-defined networks in the Dockerrun.aws.json, I keep looking for a different solution. The links can be resolved inside the container, pinging api does work, however, nginx does it's own thing there.

I have read about dnsmasq as well, however, I wanted to get this running without installing this package, do I even have a choice here ?


There is no way to force nginx to use the entries from /etc/hosts.

You can however use a map { } in your nginx config to tell nginx how to convert hostnames to IPs. You would need a script to convert your /etc/hosts to a format that can be used in a map, i.e. hostname ip vs ip hostname.

Here is an example map:

map $container_hostname $container_ip {
    default 127.0.0.1;
    containerA X.X.X.X;
    containerB Y.Y.Y.Y;
}

Later in the config file you can do:

server_name   ~^(www\.)?(?<container_hostname>.+)$;

location / {
    proxy_pass http://$container_ip:80;
}

nginx will match the requested server_name and store it in $container_hostname:

http://nginx.org/en/docs/http/server_names.html#regex_names

Then it will look up the hostname in the map, obtain the corresponding IP and pass it to proxy_pass.

More info on map: http://nginx.org/en/docs/http/ngx_http_map_module.html