Docker stack deploy port mapping ignores interface restrictions

I am putting together - one piece at a time - a service stack that includes a nginx reverse proxy server and a docker registry. When deploying the registry I want to map the registry container port 5000 to 127.0.0.1:5000. No need to make the registry available on all interfaces given the nginx reverse proxy.

My docker-compose file (see below) specifies that mapping and if I execute it with docker-compose -f docker-compose.prod.yml up everything works fine and the desired port mapping is in place.

If I deploy using docker stack deploy -c docker-compose.prod.yml docker-registry the service is deployed but my port mapping restrictions are not honored. It appears - at least to my eyes - that port 5000 is bound to all the hosts interfaces.

Any idea what’s going on here? IS it really binding to all interfaces? If so, is there a fix?

-steve

docker version: Docker version 17.05.0-ce, build 89658be

docker-compose.prod.yml:
version: ‘3’

services:
  app:
    image: registry:2
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.hostname == oberon
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s
    labels:
        com.awt.description: ${PROJECT_DESCRIPTION}
        com.awt.environment: "PROD"
        com.awt.version: ${VERSION}
    logging:
      driver: "syslog"
    networks:
      - reverse-proxy
    ports:
       - "127.0.0.1:5000:5000"
    restart: unless-stopped
    volumes:
      - docker-registry-data:/var/lib/registry

networks:
  reverse-proxy:

volumes:
  docker-registry-data:

docker inspect --pretty docker-registry-app:

ID: j0lxym0582q7l546h9sf4x722
Name: docker-registry_app
Labels:
com.docker.stack.namespace=docker-registry
Service Mode: Replicated
Replicas: 1
Placement:
Constraints: [node.hostname == oberon]
UpdateConfig:
Parallelism: 1
On failure: pause
Monitoring Period: 5s
Max failure ratio: 0
Update order: stop-first
RollbackConfig:
Parallelism: 1
On failure: pause
Monitoring Period: 5s
Max failure ratio: 0
Rollback order: stop-first
ContainerSpec:
Image: registry:2@sha256:f5552e60ffd56fecbe2f04b61a3089a9cd755bd9352b6b5ab22cf2208af6a3a8
Mounts:
Target = /var/lib/registry
Source = docker-registry_docker-registry-data
ReadOnly = false
Type = volume
Resources:
Networks: docker-registry_reverse-proxy
Endpoint Mode: vip
Ports:
PublishedPort = 5000
Protocol = tcp
TargetPort = 5000
PublishMode = ingress

It’s always so much fun to have to answer yourself And you’ve realized you’ve been clueless :slight_smile:

With respect to needing to have a port mapping that includes an interface - even localhost - that doesn’t make much sense in a swarm where one doesn’t know and shouldn’t care about the available interfaces.

And with respect to needing to map the the registry container port to the host, one doesn’t need to. As long as the nginx container and the registry container reference the same network, then we can access it simply by service name over the overlay network.

Chalk it up to learning things the hard way.

-steve