4

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?

Harindaka
  • 4,658
  • 8
  • 43
  • 62

1 Answers1

2

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
John
  • 536
  • 5
  • 16
  • Thanks @John. This helps me understand the issue. Good if someone else can shed some light on how to expose the swarm externally with a single ip or DNS similar to how a conventional load balance setup would do but without statically linking any worker nodes (i.e. in an nginx config file) taking into consideration that we can issue docker service scale and docker swarm join commands subsequently to scale where the solution needs to automatically include the new nodes as well. Is that even possible? – Harindaka Apr 16 '17 at 19:10
  • I wonder if this will help https://github.com/vfarcic/docker-flow-proxy – Harindaka Apr 16 '17 at 19:13
  • Docker swarm networking automatically load balance the replicas of the services, about "statically linking", that's exactly the purpose of the dns. There's a different between expose with the run api, and the service api, what you want to do in swarm, it's not expose, it's publish them. Look at this page -> https://docs.docker.com/docker-cloud/apps/ports/ – Dani Apr 16 '17 at 22:01