cli icon indicating copy to clipboard operation
cli copied to clipboard

Stack deploy fails if "target" or "published" port is a string

Open thaJeztah opened this issue 6 years ago • 5 comments

As reported by @ushuz https://github.com/docker/cli/issues/229#issuecomment-381066533

version: '3.4'
services:
    web:
        image: nginx:alpine
        ports:
          - published: '8080'
            target: 80

Deploying the above produces:

$ docker stack deploy -c docker-compose.yml hello

services.web.ports.0.published must be a integer

The same issue is present for target:

version: '3.4'
services:
    web:
        image: nginx:alpine
        ports:
          - published: 8080
            target: '80'
$ docker stack deploy -c docker-compose.yml hello 

services.web.ports.0.target must be a integer

Changing both to an integer makes this work:

version: '3.4'
services:
    web:
        image: nginx:alpine
        ports:
          - published: 8080
            target: 80
$ docker stack deploy -c docker-compose.yml hello 

Creating network hello_default
Creating service hello_web

Reproduced on:

Client:
 Version:      18.05.0-ce
 API version:  1.37
 Go version:   go1.9.5
 Git commit:   f150324
 Built:        Wed May  9 22:12:05 2018
 OS/Arch:      darwin/amd64
 Experimental: true
 Orchestrator: swarm

Server:
 Engine:
  Version:      18.05.0-ce
  API version:  1.37 (minimum version 1.12)
  Go version:   go1.10.1
  Git commit:   f150324
  Built:        Wed May  9 22:20:16 2018
  OS/Arch:      linux/amd64
  Experimental: true

thaJeztah avatar May 22 '18 07:05 thaJeztah

Discussing with @vdemeester; this also relates to https://github.com/docker/cli/issues/839

The long form --publish published=<port>,target=<port> syntax currently does not support port-ranges (see https://github.com/docker/cli/issues/839), and expects a single port to be passed (as integer)

While it's generally good to be strict (we expect a number, so error if it's not a number), from a UX-perspective, I think (my 0.02c) it's ok to accept the port to be passed either as an integer, or as a string containing just a number.

thaJeztah avatar May 22 '18 08:05 thaJeztah

EDIT: Changing the version to "3.5" made it work.

Changing both to an integer did not work for me.

version: "3"
services:
  db:
    image: couchdb
    ports:
     - published: 5984
       target: 5984
    deploy:
      restart_policy:
        condition: on-failure
  fs:
    image: minio/minio
    command: server /data
    ports:
     - published: 9001
       target: 9000
    deploy:
      restart_policy:
        condition: on-failure
PS> docker stack deploy --compose-file .\docker-compose.yml algdata
services.db.ports.0 must be a string or number

Docker version 18.05.0-ce, build f150324 Windows 10

doxxx avatar Jun 07 '18 15:06 doxxx

@doxxx version: "3" means 3.0. The extend form of ports has been introduced in version 3.2, that's why you're getting this error. In version 3.0, ports only support a list of integer (or string)

vdemeester avatar Jun 07 '18 15:06 vdemeester

This is happening with Docker version 20.10.17, build 100c701.

Fully defined Compose yaml config generated using docker compose convert would give something like:

(version: "3.9" is added manually)

version: "3.9"
name: syncthing
services:
  syncthing:
    image: syncthing/syncthing
    network_mode: host
    ports:
    - mode: ingress
      target: 8384
      published: "8384"
      protocol: tcp
    - mode: ingress
      target: 22000
      published: "22000"
      protocol: tcp
    - mode: ingress
      target: 22000
      published: "22000"
      protocol: udp
    restart: unless-stopped
networks:
  traefik-public:
    name: traefik-public
    driver: overlay
    external: true
    attachable: true

When attempting to deploy to Swarm, two errors will show:

services.syncthing.ports.0.published must be a integer

(root) Additional property name is not allowed

Why is the compose file that is generated using the Docker compose plugin not compatible with Docker stack deploy out of the box?

Edit: For whoever that stumbles upon this issue again, my current workaround is to pin the version of Docker I am using to deploy to a version < 20.10.15.

Seems like compose was integrated into Docker Engine version 20.10.15 and onward. I suspect something has changed in the way docker stack deploy reads the config file to deploy to Swarm, but I have yet to look into it myself, to be frank.

gordonpn avatar Jun 29 '22 05:06 gordonpn

This is happening with Docker version 20.10.17, build 100c701.

Fully defined Compose yaml config generated using docker compose convert would give something like:

(version: "3.9" is added manually)

version: "3.9"
name: syncthing
services:
  syncthing:
    image: syncthing/syncthing
    network_mode: host
    ports:
    - mode: ingress
      target: 8384
      published: "8384"
      protocol: tcp
    - mode: ingress
      target: 22000
      published: "22000"
      protocol: tcp
    - mode: ingress
      target: 22000
      published: "22000"
      protocol: udp
    restart: unless-stopped
networks:
  traefik-public:
    name: traefik-public
    driver: overlay
    external: true
    attachable: true

When attempting to deploy to Swarm, two errors will show:

services.syncthing.ports.0.published must be a integer

(root) Additional property name is not allowed

Why is the compose file that is generated using the Docker compose plugin not compatible with Docker stack deploy out of the box?

Edit: For whoever that stumbles upon this issue again, my current workaround is to pin the version of Docker I am using to deploy to a version < 20.10.15.

Seems like compose was integrated into Docker Engine version 20.10.15 and onward. I suspect something has changed in the way docker stack deploy reads the config file to deploy to Swarm, but I have yet to look into it myself, to be frank.

I have same problem,

Verison : Docker version 20.10.17, build 100c701 Error : services.[ProjectName].ports.0 must be a string or number

Change on yml

    ports:
      - "80:80"

to

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

Update:

I have fix the problem, by change the version to 3.4

from

version: "3" 

to

version: "3.4" 

nelsonpoon avatar Aug 11 '22 09:08 nelsonpoon

workaround using sed:

sed -i '/published:/ s/"//g' docker-compose.yml

diegobill avatar Feb 10 '23 16:02 diegobill