Docker-DCO-1.1-Signed-off-by: SvenDowideit <SvenDowideit@home.org.au> (github: SvenDowideit)
| ... | ... |
@@ -861,26 +861,15 @@ func (cli *DockerCli) CmdTop(args ...string) error {
|
| 861 | 861 |
} |
| 862 | 862 |
|
| 863 | 863 |
func (cli *DockerCli) CmdPort(args ...string) error {
|
| 864 |
- cmd := cli.Subcmd("port", "CONTAINER PRIVATE_PORT", "Lookup the public-facing port that is NAT-ed to PRIVATE_PORT")
|
|
| 864 |
+ cmd := cli.Subcmd("port", "CONTAINER [PRIVATE_PORT[/PROTO]]", "List port mappings for the CONTAINER, or lookup the public-facing port that is NAT-ed to the PRIVATE_PORT")
|
|
| 865 | 865 |
if err := cmd.Parse(args); err != nil {
|
| 866 | 866 |
return nil |
| 867 | 867 |
} |
| 868 |
- if cmd.NArg() != 2 {
|
|
| 868 |
+ if cmd.NArg() < 1 {
|
|
| 869 | 869 |
cmd.Usage() |
| 870 | 870 |
return nil |
| 871 | 871 |
} |
| 872 | 872 |
|
| 873 |
- var ( |
|
| 874 |
- port = cmd.Arg(1) |
|
| 875 |
- proto = "tcp" |
|
| 876 |
- parts = strings.SplitN(port, "/", 2) |
|
| 877 |
- ) |
|
| 878 |
- |
|
| 879 |
- if len(parts) == 2 && len(parts[1]) != 0 {
|
|
| 880 |
- port = parts[0] |
|
| 881 |
- proto = parts[1] |
|
| 882 |
- } |
|
| 883 |
- |
|
| 884 | 873 |
steam, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/json", nil, false)
|
| 885 | 874 |
if err != nil {
|
| 886 | 875 |
return err |
| ... | ... |
@@ -895,14 +884,34 @@ func (cli *DockerCli) CmdPort(args ...string) error {
|
| 895 | 895 |
return err |
| 896 | 896 |
} |
| 897 | 897 |
|
| 898 |
- if frontends, exists := ports[nat.Port(port+"/"+proto)]; exists && frontends != nil {
|
|
| 898 |
+ if cmd.NArg() == 2 {
|
|
| 899 |
+ var ( |
|
| 900 |
+ port = cmd.Arg(1) |
|
| 901 |
+ proto = "tcp" |
|
| 902 |
+ parts = strings.SplitN(port, "/", 2) |
|
| 903 |
+ ) |
|
| 904 |
+ |
|
| 905 |
+ if len(parts) == 2 && len(parts[1]) != 0 {
|
|
| 906 |
+ port = parts[0] |
|
| 907 |
+ proto = parts[1] |
|
| 908 |
+ } |
|
| 909 |
+ natPort := port + "/" + proto |
|
| 910 |
+ if frontends, exists := ports[nat.Port(port+"/"+proto)]; exists && frontends != nil {
|
|
| 911 |
+ for _, frontend := range frontends {
|
|
| 912 |
+ fmt.Fprintf(cli.out, "%s:%s\n", frontend.HostIp, frontend.HostPort) |
|
| 913 |
+ } |
|
| 914 |
+ return nil |
|
| 915 |
+ } |
|
| 916 |
+ return fmt.Errorf("Error: No public port '%s' published for %s", natPort, cmd.Arg(0))
|
|
| 917 |
+ } |
|
| 918 |
+ |
|
| 919 |
+ for from, frontends := range ports {
|
|
| 899 | 920 |
for _, frontend := range frontends {
|
| 900 |
- fmt.Fprintf(cli.out, "%s:%s\n", frontend.HostIp, frontend.HostPort) |
|
| 921 |
+ fmt.Fprintf(cli.out, "%s -> %s:%s\n", from, frontend.HostIp, frontend.HostPort) |
|
| 901 | 922 |
} |
| 902 |
- return nil |
|
| 903 | 923 |
} |
| 904 | 924 |
|
| 905 |
- return fmt.Errorf("Error: No public port '%s' published for %s", cmd.Arg(1), cmd.Arg(0))
|
|
| 925 |
+ return nil |
|
| 906 | 926 |
} |
| 907 | 927 |
|
| 908 | 928 |
// 'docker rmi IMAGE' removes all images with the name IMAGE |
| ... | ... |
@@ -2,14 +2,30 @@ |
| 2 | 2 |
% Docker Community |
| 3 | 3 |
% JUNE 2014 |
| 4 | 4 |
# NAME |
| 5 |
-docker-port - Lookup the public-facing port that is NAT-ed to PRIVATE_PORT |
|
| 5 |
+docker-port - List port mappings for the CONTAINER, or lookup the public-facing port that is NAT-ed to the PRIVATE_PORT |
|
| 6 | 6 |
|
| 7 | 7 |
# SYNOPSIS |
| 8 |
-**docker port** |
|
| 9 |
-CONTAINER PRIVATE_PORT |
|
| 8 |
+**docker port** CONTAINER [PRIVATE_PORT[/PROTO]] |
|
| 10 | 9 |
|
| 11 |
-# OPTIONS |
|
| 12 |
-There are no available options. |
|
| 10 |
+# DESCRIPTION |
|
| 11 |
+List port mappings for the CONTAINER, or lookup the public-facing port that is NAT-ed to the PRIVATE_PORT |
|
| 12 |
+ |
|
| 13 |
+# EXAMPLES |
|
| 14 |
+You can find out all the ports mapped by not specifying a `PRIVATE_PORT`, or |
|
| 15 |
+ask for just a specific mapping: |
|
| 16 |
+ |
|
| 17 |
+ $ docker ps test |
|
| 18 |
+ CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES |
|
| 19 |
+ b650456536c7 busybox:latest top 54 minutes ago Up 54 minutes 0.0.0.0:1234->9876/tcp, 0.0.0.0:4321->7890/tcp test |
|
| 20 |
+ $ docker port test |
|
| 21 |
+ 7890/tcp -> 0.0.0.0:4321 |
|
| 22 |
+ 9876/tcp -> 0.0.0.0:1234 |
|
| 23 |
+ $ docker port test 7890/tcp |
|
| 24 |
+ 0.0.0.0:4321 |
|
| 25 |
+ $ docker port test 7890/udp |
|
| 26 |
+ 2014/06/24 11:53:36 Error: No public port '7890/udp' published for test |
|
| 27 |
+ $ docker port test 7890 |
|
| 28 |
+ 0.0.0.0:4321 |
|
| 13 | 29 |
|
| 14 | 30 |
# HISTORY |
| 15 | 31 |
April 2014, Originally compiled by William Henry (whenry at redhat dot com) |
| ... | ... |
@@ -764,9 +764,25 @@ log entry. |
| 764 | 764 |
|
| 765 | 765 |
## port |
| 766 | 766 |
|
| 767 |
- Usage: docker port CONTAINER PRIVATE_PORT |
|
| 768 |
- |
|
| 769 |
- Lookup the public-facing port that is NAT-ed to PRIVATE_PORT |
|
| 767 |
+ Usage: docker port CONTAINER [PRIVATE_PORT[/PROTO]] |
|
| 768 |
+ |
|
| 769 |
+ List port mappings for the CONTAINER, or lookup the public-facing port that is NAT-ed to the PRIVATE_PORT |
|
| 770 |
+ |
|
| 771 |
+You can find out all the ports mapped by not specifying a `PRIVATE_PORT`, or |
|
| 772 |
+just a specific mapping: |
|
| 773 |
+ |
|
| 774 |
+ $ docker ps test |
|
| 775 |
+ CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES |
|
| 776 |
+ b650456536c7 busybox:latest top 54 minutes ago Up 54 minutes 0.0.0.0:1234->9876/tcp, 0.0.0.0:4321->7890/tcp test |
|
| 777 |
+ $ docker port test |
|
| 778 |
+ 7890/tcp -> 0.0.0.0:4321 |
|
| 779 |
+ 9876/tcp -> 0.0.0.0:1234 |
|
| 780 |
+ $ docker port test 7890/tcp |
|
| 781 |
+ 0.0.0.0:4321 |
|
| 782 |
+ $ docker port test 7890/udp |
|
| 783 |
+ 2014/06/24 11:53:36 Error: No public port '7890/udp' published for test |
|
| 784 |
+ $ docker port test 7890 |
|
| 785 |
+ 0.0.0.0:4321 |
|
| 770 | 786 |
|
| 771 | 787 |
## pause |
| 772 | 788 |
|
| 773 | 789 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,125 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "os/exec" |
|
| 4 |
+ "sort" |
|
| 5 |
+ "strings" |
|
| 6 |
+ "testing" |
|
| 7 |
+) |
|
| 8 |
+ |
|
| 9 |
+func TestListPorts(t *testing.T) {
|
|
| 10 |
+ // one port |
|
| 11 |
+ runCmd := exec.Command(dockerBinary, "run", "-d", "-p", "9876:80", "busybox", "top") |
|
| 12 |
+ out, _, err := runCommandWithOutput(runCmd) |
|
| 13 |
+ errorOut(err, t, out) |
|
| 14 |
+ firstID := stripTrailingCharacters(out) |
|
| 15 |
+ |
|
| 16 |
+ runCmd = exec.Command(dockerBinary, "port", firstID, "80") |
|
| 17 |
+ out, _, err = runCommandWithOutput(runCmd) |
|
| 18 |
+ errorOut(err, t, out) |
|
| 19 |
+ |
|
| 20 |
+ if !assertPortList(t, out, []string{"0.0.0.0:9876"}) {
|
|
| 21 |
+ t.Error("Port list is not correct")
|
|
| 22 |
+ } |
|
| 23 |
+ |
|
| 24 |
+ runCmd = exec.Command(dockerBinary, "port", firstID) |
|
| 25 |
+ out, _, err = runCommandWithOutput(runCmd) |
|
| 26 |
+ errorOut(err, t, out) |
|
| 27 |
+ |
|
| 28 |
+ if !assertPortList(t, out, []string{"80/tcp -> 0.0.0.0:9876"}) {
|
|
| 29 |
+ t.Error("Port list is not correct")
|
|
| 30 |
+ } |
|
| 31 |
+ runCmd = exec.Command(dockerBinary, "rm", "-f", firstID) |
|
| 32 |
+ out, _, err = runCommandWithOutput(runCmd) |
|
| 33 |
+ errorOut(err, t, out) |
|
| 34 |
+ |
|
| 35 |
+ // three port |
|
| 36 |
+ runCmd = exec.Command(dockerBinary, "run", "-d", |
|
| 37 |
+ "-p", "9876:80", |
|
| 38 |
+ "-p", "9877:81", |
|
| 39 |
+ "-p", "9878:82", |
|
| 40 |
+ "busybox", "top") |
|
| 41 |
+ out, _, err = runCommandWithOutput(runCmd) |
|
| 42 |
+ errorOut(err, t, out) |
|
| 43 |
+ ID := stripTrailingCharacters(out) |
|
| 44 |
+ |
|
| 45 |
+ runCmd = exec.Command(dockerBinary, "port", ID, "80") |
|
| 46 |
+ out, _, err = runCommandWithOutput(runCmd) |
|
| 47 |
+ errorOut(err, t, out) |
|
| 48 |
+ |
|
| 49 |
+ if !assertPortList(t, out, []string{"0.0.0.0:9876"}) {
|
|
| 50 |
+ t.Error("Port list is not correct")
|
|
| 51 |
+ } |
|
| 52 |
+ |
|
| 53 |
+ runCmd = exec.Command(dockerBinary, "port", ID) |
|
| 54 |
+ out, _, err = runCommandWithOutput(runCmd) |
|
| 55 |
+ errorOut(err, t, out) |
|
| 56 |
+ |
|
| 57 |
+ if !assertPortList(t, out, []string{
|
|
| 58 |
+ "80/tcp -> 0.0.0.0:9876", |
|
| 59 |
+ "81/tcp -> 0.0.0.0:9877", |
|
| 60 |
+ "82/tcp -> 0.0.0.0:9878"}) {
|
|
| 61 |
+ t.Error("Port list is not correct")
|
|
| 62 |
+ } |
|
| 63 |
+ runCmd = exec.Command(dockerBinary, "rm", "-f", ID) |
|
| 64 |
+ out, _, err = runCommandWithOutput(runCmd) |
|
| 65 |
+ errorOut(err, t, out) |
|
| 66 |
+ |
|
| 67 |
+ // more and one port mapped to the same container port |
|
| 68 |
+ runCmd = exec.Command(dockerBinary, "run", "-d", |
|
| 69 |
+ "-p", "9876:80", |
|
| 70 |
+ "-p", "9999:80", |
|
| 71 |
+ "-p", "9877:81", |
|
| 72 |
+ "-p", "9878:82", |
|
| 73 |
+ "busybox", "top") |
|
| 74 |
+ out, _, err = runCommandWithOutput(runCmd) |
|
| 75 |
+ errorOut(err, t, out) |
|
| 76 |
+ ID = stripTrailingCharacters(out) |
|
| 77 |
+ |
|
| 78 |
+ runCmd = exec.Command(dockerBinary, "port", ID, "80") |
|
| 79 |
+ out, _, err = runCommandWithOutput(runCmd) |
|
| 80 |
+ errorOut(err, t, out) |
|
| 81 |
+ |
|
| 82 |
+ if !assertPortList(t, out, []string{"0.0.0.0:9876", "0.0.0.0:9999"}) {
|
|
| 83 |
+ t.Error("Port list is not correct")
|
|
| 84 |
+ } |
|
| 85 |
+ |
|
| 86 |
+ runCmd = exec.Command(dockerBinary, "port", ID) |
|
| 87 |
+ out, _, err = runCommandWithOutput(runCmd) |
|
| 88 |
+ errorOut(err, t, out) |
|
| 89 |
+ |
|
| 90 |
+ if !assertPortList(t, out, []string{
|
|
| 91 |
+ "80/tcp -> 0.0.0.0:9876", |
|
| 92 |
+ "80/tcp -> 0.0.0.0:9999", |
|
| 93 |
+ "81/tcp -> 0.0.0.0:9877", |
|
| 94 |
+ "82/tcp -> 0.0.0.0:9878"}) {
|
|
| 95 |
+ t.Error("Port list is not correct\n", out)
|
|
| 96 |
+ } |
|
| 97 |
+ runCmd = exec.Command(dockerBinary, "rm", "-f", ID) |
|
| 98 |
+ out, _, err = runCommandWithOutput(runCmd) |
|
| 99 |
+ errorOut(err, t, out) |
|
| 100 |
+ |
|
| 101 |
+ deleteAllContainers() |
|
| 102 |
+ |
|
| 103 |
+ logDone("port - test port list")
|
|
| 104 |
+} |
|
| 105 |
+ |
|
| 106 |
+func assertPortList(t *testing.T, out string, expected []string) bool {
|
|
| 107 |
+ //lines := strings.Split(out, "\n") |
|
| 108 |
+ lines := strings.Split(strings.Trim(out, "\n "), "\n") |
|
| 109 |
+ if len(lines) != len(expected) {
|
|
| 110 |
+ t.Errorf("different size lists %s, %d, %d", out, len(lines), len(expected))
|
|
| 111 |
+ return false |
|
| 112 |
+ } |
|
| 113 |
+ sort.Strings(lines) |
|
| 114 |
+ sort.Strings(expected) |
|
| 115 |
+ |
|
| 116 |
+ for i := 0; i < len(expected); i++ {
|
|
| 117 |
+ if lines[i] != expected[i] {
|
|
| 118 |
+ t.Error("|" + lines[i] + "!=" + expected[i] + "|")
|
|
| 119 |
+ return false |
|
| 120 |
+ } |
|
| 121 |
+ } |
|
| 122 |
+ |
|
| 123 |
+ return true |
|
| 124 |
+} |