eth crypt
eth crypt

Reputation: 307

docker swarm: how to publish a service only on a specific node that runs a task

I created a docker-compose.yml file containing two services that are run on two different nodes. The two services are meant to communicate on the same port as client and server. Below is my docker-compose.yml file.

 version: "3"
services:
  service1:
    image: localrepo/image1
    deploy:
      placement:
        constraints: [node.hostname == node1]
      replicas: 1
      resources:
        limits:
          cpus: "1"
          memory: 1000M
      restart_policy:
        condition: on-failure
    ports:
      - 8000:8000
    networks:
      - webnet

  service2:
    image: localrepo/image2
    deploy:
      placement:
        constraints: [node.hostname == node2]
      replicas: 1
      resources:
        limits:
          cpus: "1"
          memory: 500M
      restart_policy:
        condition: on-failure
    ports:
      - "8000:8000"
    networks:
      - webnet
networks:
  webnet:

When I issue docker stack deploy -c I get error, reading

> Error response from daemon: rpc error: code = 3 desc = port '8000' is already in use by service.

In this thread I read that deploying a service in a swarm makes the port accessible throughout any node in the swarm. If I understand correctly, that makes the port occupied by any node in the cluster. In the same thread, it was suggested to use mode=host publishing, which will only expose the port on the actual host that the container runs. I applied that in the port as:

ports: - "mode=host, target=8000, published=8000"

Making that change in both service and trying to issue docker stack gives another error:

> 1 error(s) decoding:

* Invalid containerPort: mode=host, target=8000, published=8000

Does anyone know how to fix this issue?

p.s: I tried both "Version3" and "Version3.2" but the issue didn't solve.

Upvotes: 2

Views: 7002

Answers (2)

eth crypt
eth crypt

Reputation: 307

The problem is fixed after upgrading to the latest docker version, 18.01.0-ce

Upvotes: 1

SangminKim
SangminKim

Reputation: 9136

I don't know how did you specify host mode since your docker-compose.yml doesn't represent host mode anywhere.

Incidentally, try with long syntax which can specify host mode in docker-compose.yml file.

This long syntax is new in v3.2 and the below is the example(I check it works)

(This is compatible docker engine version against docker-compose syntax version.)

version: '3.4'     # version: '3.2' also will works

networks:
    swarm_network:
        driver: overlay


services:
    service1:
        image: asleea/test

        command: ["nc", "-vlkp", "8000"]

        deploy:
            mode: replicated
            replicas: 1
            placement:
                constraints:
                    - node.hostname == node1

        ports:
            - published: 8000
              target: 8000
              mode: host

        networks:
            swarm_network:

    service2:
        image: asleea/test

        command: ["nc", "service1", "8000"]

        deploy:
            mode: replicated
            replicas: 1
            placement:
                constraints:
                    - node.hostname == node2

        ports:
            - published: 8000
              target: 8000
              mode: host

        networks:
            swarm_network:

Upvotes: 5

Related Questions