Creating Docker DNS aliases

Before embedded DNS, the only way to alias a container to a different name was to use links. As we’ve seen in previous recipes, this is still the method used to create localized or container-specific aliases. However, what if you wanted to have an alias with a larger scope, one that any container connected to a given network could resolve? The embedded DNS server offers what are referred to as network-scoped aliases, which are resolvable within a given user-defined network. In this recipe, we’ll show you how to create network-scoped aliases within user-defined networks.

Getting ready

In this recipe, we’ll be demonstrating the configuration on a single Docker host. It is assumed that this host has Docker installed and that Docker is in its default configuration. We’ll be altering name resolution settings on the host, so you’ll need root-level access.

How to do it…

Network aliases can be defined in a couple of different ways. They can be defined at container runtime or when you connect a container to a network. Once again, network aliases are a feature only provided when a container implements a user-defined network. You cannot create a network alias without specifying a user-defined network at the same time. Docker will prevent you from specifying them at container runtime:

user@docker1:~$ docker run -dP --name=web1 --net-alias=webserver1 
jonlangemak/web_server_1
460f587d0fb3e70842b37736639c150b6d333fd0b647345aa7ed9e0505ebfd2d
docker: Error response from daemon: Network-scoped alias is supported only for containers in user defined networks.
user@docker1:~$

If we create a user-defined network and specify it as part of the container configuration, the command will execute successfully:

user@docker1:~$ docker network create -d bridge mybridge1
663f9fe0b4a0dbf7a0be3c4eaf8da262f7e2b3235de252ed5a5b481b68416ca2
user@docker1:~$ docker run -dP --name=web1 --net=mybridge1 
--net-alias=webserver1 jonlangemak/web_server_1
05025adf381c7933f427e647a512f60198b29a3cd07a1d6126bc9a6d4de0a279
user@docker1:~$

Once the alias is created, we can see it as part of the specific container's configuration. For instance, if we now inspect the container web1, we’ll see a defined alias under its network configuration:

user@docker1:~$ docker inspect web1
…<Additional output removed for brevity>…
                “mybridge1”: {
                    “IPAMConfig”: null,
                    “Links”: null,
                    “Aliases”: [
                        “webserver1”,
                        “6916ac68c459”
                    ],
                    “NetworkID”: “a75b46cc785b88ddfbc83ad7b6ab7ced88bbafef3f64e3e4314904fb95aa9e5c”,
                    “EndpointID”: “620bc4bf9962b7c6a1e59a3dad8d3ebf25831ea00fea4874a9a5fcc750db5534”,
                    “Gateway”: “172.18.0.1”,
                    “IPAddress”: “172.18.0.2”,
…<Additional output removed for brevity>…
user@docker1:~$

Now, let’s start another container named web2 and see if we can resolve the alias:

user@docker1:~$ docker run -dP --name=web2 --net=mybridge1 
jonlangemak/web_server_2
9b6d23ce868bf62999030a8c1eb29c3ca7b3836e8e3cbb7247d4d8e12955f117
user@docker1:~$ docker exec -it web2 ping webserver1 -c 2
PING webserver1 (172.18.0.2): 48 data bytes
56 bytes from 172.18.0.2: icmp_seq=0 ttl=64 time=0.104 ms
56 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.091 ms
--- webserver1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.091/0.098/0.104/0.000 ms
user@docker1:~$

There are a couple of interesting things to point out here. First, this method for defining aliases is vastly different than the linking method in more than just scope. With links, a source container specified what it wanted a target container to be aliases to. In the case of network aliases, a source container sets its own alias.

Second, this only worked because the container web2 is on the same user-defined network as web1. Because the alias' scope is the entire user-defined network, this means that the same container could go by different aliases on a different user-defined networks. For instance, let’s create another user-defined network:

user@docker1:~$ docker network create -d bridge mybridge2
d867d7ad3a1f639cde8926405acd3a36e99352f0e2a45871db5263caf3b59c44
user@docker1:~$

Now, let’s attach the container web1 to it:

user@docker1:~$ docker network connect --alias=fooserver mybridge2 web1

Recall that we said you can define network-scoped aliases as part of the network connect subcommand as well:

user@docker1:~$ docker inspect web1
…<Additional output removed for brevity>…
                “mybridge1”: {
                    “IPAMConfig”: null,
                    “Links”: null,
                    “Aliases”: [
                        “webserver1”,
                        “6916ac68c459”
                    ],
                    “NetworkID”: “a75b46cc785b88ddfbc83ad7b6ab7ced88bbafef3f64e3e4314904fb95aa9e5c”,
                    “EndpointID”: “620bc4bf9962b7c6a1e59a3dad8d3ebf25831ea00fea4874a9a5fcc750db5534”,
                    “Gateway”: “172.18.0.1”,
                    “IPAddress”: “172.18.0.2”,
                    “IPPrefixLen”: 16,
                    “IPv6Gateway”: “”,
                    “GlobalIPv6Address”: “”,
                    “GlobalIPv6PrefixLen”: 0,
                    “MacAddress”: “02:42:ac:12:00:02”
                },
                “mybridge2”: {
                    “IPAMConfig”: {},
                    “Links”: null,
                    “Aliases”: [
                        “fooserver”,
                        “6916ac68c459”
                    ],
                    “NetworkID”: “daf24590cc8f9c9bf859eb31dab42554c6c14c1c1e4396b3511524fe89789a58”,
                    “EndpointID”: “a36572ec71077377cebfe750f4e533e0316669352894b93df101dcdabebf9fa7”,
                    “Gateway”: “172.19.0.1”,
                    “IPAddress”: “172.19.0.2”,
user@docker1:~$

Note that the container web1 now has two aliases, one on each network. Because the container web2 is only connected to one network, it is still only able to resolve the alias associated with the mybridge1 network:

user@docker1:~$ docker exec -it web2 ping webserver1 -c 2
PING webserver1 (172.18.0.2): 48 data bytes
56 bytes from 172.18.0.2: icmp_seq=0 ttl=64 time=0.079 ms
56 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.123 ms
--- webserver1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.079/0.101/0.123/0.000 ms
user@docker1:~$ docker exec -it web2 ping fooserver -c 2
ping: unknown host
user@docker1:~$

However, once we connect web2 to the mybridge2 network, it is now able to resolve both aliases:

user@docker1:~$ docker network connect mybridge2 web2
user@docker1:~$ docker exec -it web2 ping webserver1 -c 2
PING webserver1 (172.18.0.2): 48 data bytes
56 bytes from 172.18.0.2: icmp_seq=0 ttl=64 time=0.064 ms
56 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.097 ms
--- webserver1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.064/0.081/0.097/0.000 ms
user@docker1:~$ docker exec -it web2 ping fooserver -c 2
PING fooserver (172.19.0.2): 48 data bytes
56 bytes from 172.19.0.2: icmp_seq=0 ttl=64 time=0.080 ms
56 bytes from 172.19.0.2: icmp_seq=1 ttl=64 time=0.087 ms
--- fooserver ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.080/0.083/0.087/0.000 ms
user@docker1:~$

Interestingly, Docker also lets you define the same alias to multiple containers. For instance, let’s now start a third container named web3 and connect it to mybridge1 using the same alias as web1 (webserver1):

user@docker1:~$ docker run -dP --name=web3 --net=mybridge1 
--net-alias=webserver1 jonlangemak/web_server_1
cdf22ba64231553dd7e876b5718e155b1312cca68a621049e04265f5326e063c
user@docker1:~$

The alias is now defined for the container web1 as well as web2. However, attempts to resolve the alias from web2 still point to web1:

user@docker1:~$ docker exec -it web2 ping webserver1 -c 2
PING webserver1 (172.18.0.2): 48 data bytes
56 bytes from 172.18.0.2: icmp_seq=0 ttl=64 time=0.066 ms
56 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.088 ms
--- webserver1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.066/0.077/0.088/0.000 ms
user@docker1:~$

If we disconnect or stop the container web1, we should see that the resolution now changes to web3 since it’s still active on the network and has the same alias:

user@docker1:~$ docker stop web1
web1
user@docker1:~$ docker exec -it web2 ping webserver1 -c 2
PING webserver1 (172.18.0.4): 48 data bytes
56 bytes from 172.18.0.4: icmp_seq=0 ttl=64 time=0.085 ms
56 bytes from 172.18.0.4: icmp_seq=1 ttl=64 time=0.091 ms
--- webserver1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.085/0.088/0.091/0.000 ms
user@docker1:~$

This functionality can provide you with some interesting options in terms of high availability or failover, especially when coupled with the overlay network type.

It should be noted that this functionality works for all user-defined network types including the overlay network type. We’ve used bridges in these examples to keep the examples simple.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset