0

Set up two servers, one as a manager node and one as a worker node.

The worker node is labeled role_1=true .

The manager node is labeled role_2, role_3.

$ docker node update --label-add role_1=true node_1
node_1

$ docker node update --label-add role_2=true node_2
node_2

$ docker node update --label-add role_3=true node_2
node_2

$ docker node inspect node_1 --pretty
ID:                     rdnmlf1m0ge
Labels:
 - role_1=true

$ docker node inspect node_2 --pretty
ID:                     td1cq8oxxrk2a
Labels:
 - role_2=true
 - role_3=true

The main.go file, Dockerfile is:

main.go

package main

import (
        "net/http"
)

func main() {
        http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
                w.Write([]byte("Hello World!"))
        })

        err := http.ListenAndServe(":8080", nil)
        if err != nil {
                return
        }
}

dockerfile

FROM golang:latest

ENV GO111MODULE=off

WORKDIR /go/src/app
COPY . /go/src/app

RUN go build -o simple_program

ENTRYPOINT ["/go/src/app/simple_program"]

Write docker-compose file as below. Add only the label of the manager node to constraints .

version: '3.7'

services:
  api_server:
    image: simple_program
    deploy:
      mode: global
      placement:
        constraints:
          - node.labels.role_2 == true
          - node.labels.role_3 == true
    ports:
      - 8080:8080

It works as expected.

$ docker stack deploy --compose-file docker-compose.yml simple_http_server
Creating network simple_http_server_default
Creating service simple_http_server_api_server

$ docker service ls
ID                 NAME                                MODE      REPLICAS   IMAGE                      PORTS
2vksfee0e4ef   simple_http_server_api_server   global        1/1         simple_program:latest   *:8080->8080/tcp

If it is distributed to both the manager node and the worker node or distributed only to the worker node, the service does not come up.

version: '3.7'

services:
  api_server:
    image: simple_program
    deploy:
      mode: global
      placement:
        constraints:
          - node.labels.role_1 == true
          - node.labels.role_3 == true
    ports:
      - 8080:8080

$ docker service ls
ID                  NAME                               MODE      REPLICAS   IMAGE                       PORTS
rhto667wd9lb   simple_http_server_api_server   global       0/0         simple_program:latest   *:8080->8080/tcp

Nothing shows up in service logs either.

$ docker service ps --no-trunc simple_http_server_api_server
ID        NAME      IMAGE     NODE      DESIRED STATE   CURRENT STATE   ERROR     PORTS

$ docker service logs simple_http_server_api_server
$

I read the stackoverflow questions and answers below, but it didn't help.

Multiple label placement constraints in docker swarm

battlecook
  • 471
  • 6
  • 17

1 Answers1

2

From placement-constraints: "If you specify multiple placement constraints, the service only deploys onto nodes where they are all met."

Your second deployment lists a constraint combination of node_1 and node_3 which is impossible as you have no node that satisfies this.

Chris Becke
  • 34,244
  • 12
  • 79
  • 148