Why Can't I Access Service in Docker Swarm by its Name or VIP?

Harindaka picture Harindaka · Apr 16, 2017 · Viewed 8k times · Source

So I have a docker engine (version 1.12.6, build 78d1802) running in an Ubuntu host.

I created initiated a swarm using

docker swarm init --advertise-addr 192.168.1.2

I have a locally prebuilt image using which I create a service called nodeapp as follows

docker service create --name nodeapp --publish 3000:3000 --replicas 2 node-app-image

Now when I type curl localhost:3000 I get the expected proper response and everything works up to this point.

This document and many others I referred seem to suggest that docker v1.12.x has inbuilt load balancing / routing via either DNS or VIP methods.

So I'm trying to access my service via service name or virtual ip as follows

curl nodeapp:3000 to which I get curl: (6) Could not resolve host: nodeapp

and

curl 10.255.0.6:3000 to which I get curl: (7) Failed to connect to 10.255.0.6 port 3000: Connection timed out

Note that I used the following command to obtain the virtual ip

docker service inspect --format {{.Endpoint.VirtualIPs}} nodeapp which yields [{boq3g7s47w47q2ej56li9s3dw 10.255.0.6/16}]

Why can't I access my service using the VIP or Service Name even though I can access it using localhost:3000?

Answer

John picture John · Apr 16, 2017

From this page:

By default, when you create a service attached to a network, the swarm assigns the service a VIP. The VIP maps to a DNS alias based upon the service name. Containers on the network share DNS mappings for the service via gossip so any container on the network can access the service via its service name.

So it appears that dns resolution will only work between containers, and not on the host (by default at least, I assume there would be a way to configure the dns on the host to resolve these services).

For example, create a service running nginx:

docker service create \
  --replicas 3 \
  --name my-web \
  --network my-network \
  nginx

View the service:

$ docker service ps my-web

NAME                                IMAGE  NODE   DESIRED STATE  CURRENT STATE               ERROR
my-web.1.63s86gf6a0ms34mvboniev7bs  nginx  node1  Running        Running 58 seconds ago
my-web.2.6b3q2qbjveo4zauc6xig7au10  nginx  node2  Running        Running 58 seconds ago
my-web.3.66u2hcrz0miqpc8h0y0f3v7aw  nginx  node3  Running        Running about a minute ago

Create a new service/container:

$ docker service create \
  --name my-busybox \
  --network my-network \
  busybox \
  sleep 3000

View the container:

$ docker service ps my-busybox

NAME                                    IMAGE    NODE   DESIRED STATE  CURRENT STATE          ERROR
my-busybox.1.1dok2cmx2mln5hbqve8ilnair  busybox  node1  Running        Running 5 seconds ago

Enter the container:

$ docker exec -it my-busybox.1.1dok2cmx2mln5hbqve8ilnair /bin/sh

From within the container, you can resolve the nginx service:

$ nslookup my-web

Server:    127.0.0.11
Address 1: 127.0.0.11

Name:      my-web
Address 1: 10.0.9.2 ip-10-0-9-2.us-west-2.compute.internal