docker / for-linux

Docker Engine for Linux
https://docs.docker.com/engine/installation/
751 stars 84 forks source link

docker port and the -p option should have the same order for ports. #429

Open kindlychung opened 6 years ago

kindlychung commented 6 years ago

Expected behavior

Order of ports should be consistent.

Actual behavior

docker run -p has the format <external_ip>:<external_port>:<container_port>, while the ports reported by docker port has the format <container_port>/protocal -> <external_ip>:<external_port>.

Output of docker version:

Client:
 Version:           18.06.1-ce
 API version:       1.38
 Go version:        go1.10.3
 Git commit:        e68fc7a
 Built:             Tue Aug 21 17:24:51 2018
 OS/Arch:           linux/amd64
 Experimental:      false

Server:
 Engine:
  Version:          18.06.1-ce
  API version:      1.38 (minimum version 1.12)
  Go version:       go1.10.3
  Git commit:       e68fc7a
  Built:            Tue Aug 21 17:23:15 2018
  OS/Arch:          linux/amd64
  Experimental:     false

Output of docker info:

Containers: 1
 Running: 1
 Paused: 0
 Stopped: 0
Images: 31
Server Version: 18.06.1-ce
Storage Driver: overlay2
 Backing Filesystem: extfs
 Supports d_type: true
 Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 468a545b9edcd5932818eb9de8e72413e616e86e
runc version: 69663f0bd4b60df09991c08812a60108003fa340
init version: fec3683
Security Options:
 apparmor
 seccomp
  Profile: default
Kernel Version: 4.15.0-33-generic
Operating System: Ubuntu 18.04.1 LTS
OSType: linux
Architecture: x86_64
CPUs: 8
Total Memory: 31.14GiB
Name: kaiyin-XPS-15-9560
ID: 2AWK:KLOZ:TOJ2:J2SO:IXRH:5X7Q:FDJU:FIUY:RWVN:EYD5:BTYS:JGKB
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Username: keenzien
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false
cpuguy83 commented 6 years ago

The UX is for getting the host port of a container where as the -p syntax is for setting the host port of the container.

The format itself is also actually a list:

$ docker run -d --name test -p 80 -p 443 nginx
c85d2645be9dddab9af48858c3746328dd4673a321f20214ffd62e6552223783
~  $ docker port test
443/tcp -> 0.0.0.0:32769
80/tcp -> 0.0.0.0:32770

It also supports pulling the host port for a specific container port:

$ docker port test 80
0.0.0.0:32770
thaJeztah commented 5 years ago

I don't think we can change the default output of docker ports without breaking people.

FWIW, there was a PR at some point to add --format to the docker port command (PR here: https://github.com/moby/moby/pull/31859), but there was no consensus on adding more features to the command (docker port is a bit of an odd-one out, as it overlaps in functionality with docker container inspect / docker inspect, and there are no comparable commands for other properties of a container)

For now, you could use docker container inspect to achieve this;

Start a container, that publishes some ports on ephemeral ("random") ports;

docker run -d -p 80 -p 443 -p 8080 --name test nginx:alpine
8f47e335b3e446972bcbd2abb6829b453adbc93cac743af7e5860d26b0a1f961

The docker port command shows the standard format;

docker port test
443/tcp -> 0.0.0.0:32770
80/tcp -> 0.0.0.0:32771
8080/tcp -> 0.0.0.0:32769

But you can use custom formatting on docker container inspect to use your own format;

docker container inspect --format '{{.NetworkSettings.Ports}}' test
map[80/tcp:[{0.0.0.0 32768}]]

docker container inspect --format '{{json .NetworkSettings.Ports}}' test
{"80/tcp":[{"HostIp":"0.0.0.0","HostPort":"32768"}]}

For these arrays/lists, it's a bit complicated to write the template, but here's an example;

docker container inspect --format '{{ range $key, $value := .NetworkSettings.Ports }}{{ range . }}{{ .HostIp }}:{{ .HostPort}} -> {{ $key }}, {{end}}{{ end }}'  test
0.0.0.0:32770->443/tcp, 0.0.0.0:32771->80/tcp, 0.0.0.0:32769->8080/tcp,

If you need a newline (I think) you have to add a literal newline in the template (don't think it expands \n);

docker container inspect --format '{{ range $key, $value := .NetworkSettings.Ports }}{{ range . }}{{ .HostIp }}:{{ .HostPort}} -> {{ $key }}
{{end}}{{ end }}'  test

Or have bash expand the newline;

docker container inspect --format '{{ range $key, $value := .NetworkSettings.Ports }}{{ range . }}{{ .HostIp }}:{{ .HostPort}} -> {{ $key }}'$'\n''{{end}}{{ end }}'  test

You can set define this a function in your shell (or add to, e.g., your ~/.bashrc)

docker_ports() {
  docker container inspect --format '{{ range $key, $value := .NetworkSettings.Ports }}{{ range . }}{{ .HostIp }}:{{ .HostPort}} -> {{ $key }}'$'\n''{{end}}{{ end }}' "$@";
}

First, load the function

. ~/.bashrc 

And you can now run docker_ports <container> to use your custom output

docker_ports test
0.0.0.0:32770 -> 443/tcp
0.0.0.0:32771 -> 80/tcp
0.0.0.0:32769 -> 8080/tcp