Repository: docker/docker-py

Issue:
Client.port() only reports the UDP exposed port mapping if the same port is configured to be mapped on UDP and TCP.
E.g.:
`docker ps`

```
CONTAINER ID  IMAGE         COMMAND        CREATED        STATUS        PORTS                                         NAMES
6348dd5bc7c2  ubuntu:14.04  /usr/bin/bash  8 seconds ago  Up 8 seconds  0.0.0.0:49153->80/udp, 0.0.0.0:49159->80/tcp  expose_ports
```

`In ipython`

```
In [1]: docker_client.port('6348dd5bc7c2', 80)
Out[1]: [{u'HostIp': u'0.0.0.0', u'HostPort': u'49153'}]
```

The reason seems to lie in `/docker/api/container.py`, line 208-210

``` python
def port(self, container, private_port):

...

h_ports = port_settings.get(s_port + '/udp')
if h_ports is None:
    h_ports = port_settings.get(s_port + '/tcp')
```

Instead of basically only accepting a port number for `private_port` and trying for udp and tcp exposed ports, I'd suggest that the method rather accepts an explicit `private_port` input like `1234/tcp`.



Discussion:
`pip freeze | grep docker-py && python --version && docker version`

```
docker-py==0.7.2
Python 2.7.6
Client version: 1.0.1
Client API version: 1.12
Go version (client): go1.2.1
Git commit (client): 990021a
Server version: 1.0.1
Server API version: 1.12
Go version (server): go1.2.1
Git commit (server): 990021a
```

Thanks for the report!

While this has no bearing on that particular bug, I would strongly encourage you to upgrade `docker` to a more recent version if you can. 


Resolving patch:
diff --git a/docker/api/container.py b/docker/api/container.py
--- a/docker/api/container.py
+++ b/docker/api/container.py
@@ -196,7 +196,7 @@ def port(self, container, private_port):
         res = self._get(self._url("/containers/{0}/json", container))
         self._raise_for_status(res)
         json_ = res.json()
-        s_port = str(private_port)
+        private_port = str(private_port)
         h_ports = None
 
         # Port settings is None when the container is running with
@@ -205,9 +205,12 @@ def port(self, container, private_port):
         if port_settings is None:
             return None
 
-        h_ports = port_settings.get(s_port + '/udp')
+        if '/' in private_port:
+            return port_settings.get(private_port)
+
+        h_ports = port_settings.get(private_port + '/tcp')
         if h_ports is None:
-            h_ports = port_settings.get(s_port + '/tcp')
+            h_ports = port_settings.get(private_port + '/udp')
 
         return h_ports
 


Test patch:
diff --git a/tests/integration_test.py b/tests/integration_test.py
--- a/tests/integration_test.py
+++ b/tests/integration_test.py
@@ -17,6 +17,7 @@
 import json
 import io
 import os
+import random
 import shutil
 import signal
 import socket
@@ -1718,3 +1719,27 @@ def test_715(self):
         if six.PY3:
             logs = logs.decode('utf-8')
         assert logs == '1000\n'
+
+    def test_792_explicit_port_protocol(self):
+
+        tcp_port, udp_port = random.sample(range(9999, 32000), 2)
+        ctnr = self.client.create_container(
+            BUSYBOX, 'true', ports=[2000, (2000, 'udp')],
+            host_config=self.client.create_host_config(
+                port_bindings={'2000/tcp': tcp_port, '2000/udp': udp_port}
+            )
+        )
+        self.tmp_containers.append(ctnr)
+        self.client.start(ctnr)
+        self.assertEqual(
+            self.client.port(ctnr, 2000)[0]['HostPort'],
+            six.text_type(tcp_port)
+        )
+        self.assertEqual(
+            self.client.port(ctnr, '2000/tcp')[0]['HostPort'],
+            six.text_type(tcp_port)
+        )
+        self.assertEqual(
+            self.client.port(ctnr, '2000/udp')[0]['HostPort'],
+            six.text_type(udp_port)
+        )