I have several services in a docker-compose.yml
that need to speak with one another. This isn't the problem since the composer takes care of all the networking internally. However, one of the services requires a whitelist to allow communication to its API. This whitelist has an unfortunate limitation of IPv4 addresses only - it does not resolve hostnames.
I would like to avoid having to define my own custom network and assigning static IP addresses to the containers, keeping it flexible. I have searched up and down and don't see a way to resolve the service names at runtime, or even during the build phase for that matter.
I've tried installing DNS tools and using dig
but is unable to determine an IP address. This probably has to do with my lack of understanding of how Docker deals with the networking layer.
So my questions are:
docker-compose
, does it assign static addresses to the container or is there a possibility of the containers IP changing after a reboot?I faced a similar challenge some month ago, and it is possible to obtain what you want (even if I was working on Kubernetes and not with docker-compose).
Docker provides an internal DNS resolution system, as explained in this StackOverflow question.
If you hack a little bit with dig
, you see that the container uses a different DNS IP from your host.
In particular, launching the Wordpress example form the docker-compose documentation you can see it in the following way:
mkdir /tmp/test && cd /tmp/test
# create a docker-compose.yaml file and past the example from the link above
docker-compose up -d
# it should be test_default, check it out with `docker network ls`
docker run --rm -it --network test_default ubuntu /bin/bash
And then, inside the container type:
apt-get update && apt-get install -y dnsutils
dig wordpress
You should obtain something similar to this:
root@91e47b426ed3:/# dig wordpress
; <<>> DiG 9.11.3-1ubuntu1.3-Ubuntu <<>> wordpress
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 17239
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;wordpress. IN A
;; ANSWER SECTION:
wordpress. 600 IN A 172.18.0.3
;; Query time: 0 msec
;; SERVER: 127.0.0.11#53(127.0.0.11)
;; WHEN: Sun Feb 17 19:39:24 UTC 2019
;; MSG SIZE rcvd: 52
Here you see that the field SERVER
says 127.0.0.11#53
, that's the internal Docker DNS system in my case. You can check that the address is the one reported (in my case 172.18.0.3
) installing curl
and reaching it at the port 80
.
With that in mind, you can create a script or a program that periodically performs address resolution, takes the address list the DNS returns for that service and updates your whitelist accordingly.
How can I resolve a containers service name either at runtime or during the build phase?
Taking Java as example, you can use the InetAddress class that given an URL it gives back a list of IP4 and IP6 addresses (you can filter them using InetAddressValidator
from the Apache Common library). You can see more here (that's how I solved the problem). In Linux, there is a specific syscall, getaddrinfo, to obtain a list of IPs given an URL.
When building with docker-compose, does it assign static addresses to the container or is there a possibility of the containers IP changing after a reboot?
Regarding the second question, docker-compose uses the same logic of docker build
, so it won't assign static IP addresses or similar. On top of that, if a container crashes and gets restarted, there is the possibility that its IP changes.