Docker swarm: Deploy container only to worker nodes / Service only reachable from manager

Hello,

I current play with docker, in details with docker swarm. And now I have two questions
I create 1 manager and 3 worker nodes. I create a service and can scale it. Everything works fine.

But current the manager will also used as container host for the service. And I think this is not the right way. So here my question. How can I prevent that the manager will be used for the service?

And I create the service with a httpd image for playing and the published port is 80. I can only access to this service over the manger url or ip. Is this the normal behavior? Maybe I have not read the documention enough :slight_smile: Is this normal, how it works also in production environment?

br
Rene

great, and now you might want to share your compose file so someone actualy might be able to help you :wink:

You are right:

I try a little bit on my own. But it won’t work. My compose file:

version: "3"
services:
  web:
    # replace username/repo:tag with your name and image details
    image: httpd:latest
    deploy:
      placement: 
        constraints: 
          - node.role != manager
      replicas: 5
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
      restart_policy:
        condition: on-failure
    ports:
      - "80:80"
    networks:
     - webnet

Your placement constraint “node.role != manager” should be equal to “node.role == worker”.

You publish the port the good old way, which defaults to publishing the port to the ingress network, thus beeing affected by mash routing, all nodes in the swarm bind the port and forward it to a replica of the service.

The short version port publishing syntax you use:

ports:
  - "80:80"

should be identical to this long syntax version :

    ports:
      - target: 80
        published: 80
        protocol: tcp
        mode: ingress

Though, you might want to use the explicit long syntax to be sure. If you want to bypass the ingress network, you can use “mode: host” instead, which will bind the port to the workers only!

Why would you want to use 5 replicas on 3 worker nodes? If i were you, I would use the node.role==worker constraint, declare the deploy.mode to global and publish the port in mode:host

One more thing: beware of the restart_policy condition “on-failure”. It does not necessarily mean that an ended container will be recrated. You might want to stick to “any” instead.

Thanks for your help. Now it works.

Great! :slight_smile:

Would you mind sharing your final compose file, so others can benefit from your experience?

:grinning:

#docker stack deploy -c docker-compose.yml getstartedlab
version: "3.7"
services:
  web:
# replace username/repo:tag with your name and image details
image: httpd:latest
deploy:
  placement:
    constraints:
      - node.role == worker
  replicas: 3
  resources:
    limits:
      cpus: "0.1"
      memory: 50M
  restart_policy:
    condition: any
ports:
  - "8888:80"
networks:
  bridge:
1 Like