Different connectivity for "run" and "stack"

Hi,

I am following the docker tutorials and I found a behavior that I can’t yet explain. My host is Ubuntu, and my /etc/hosts file is:

127.0.0.1       localhost
127.0.1.1       ubuntu
# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

As you can see, localhost is bound to both 127.0.0.1 and for ::1 (default Ubuntu xenial installation).

When I docker run -d -p 9000:80 my/image I can get to it using both:

  • curl -4 http: //localhost: 9000
  • curl -6 http: //localhost :9000
    (extra spaces above are just to let the forum post them)

So far so good. Now I elaborate a docker-compose.yml as:

version: "3"
services:
  web:
    image: my/image
    deploy:
      replicas: 2
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
      restart_policy:
        condition: on-failure
    ports:
      - "9000:80"
    networks:
      - mynet
networks:
  mynet:

And then I run docker stack deploy -c docker-compose.yml mystack and try the curls aboves with results:

I searched a lot for a concrete answer but could not find one. This was reproducible both under:

  • Win 10 Home + Virtualbox 5.1 + Ubuntu 16.04 xenial + Docker 17.03.1-ce
  • Google Cloud Platform + Ubuntu 16.04 xenial + Docker 17.03.1-ce

Why would IPV6 work with the “run” command, but not with “stack deploy”?

Thanks!

1 Like

This is because docker stack deploy doesn’t bind ports directly like docker run does.
docker stack deploy creates an ingress load balancer across the swarm to allow you to access the container through any node in the swarm. You can proove this by using docker ps and docker inspect and see the differences.
To disable that load balancer, you can use the following “ports” settings (docker-compose file version 3.2 required):

version: "3.2"
services:
web:
    ...
    ports:
        - target: 80
          published: 9000
          mode: host
    deploy:
        mode: global

The mode: global in deploy makes sure one and only one instance run on each node of the swarm, otherwise there will be port collide or the container will be not accessible through certain nodes in swarm.

Thanks so much for your answer.

I get the overall idea, good point you mentioned the ingress load balancer. I’m still trying to get my head around the other pieces of information you provided.

Thanks again,
Renan