Reputation: 3045
I couldn't find this documented. Suppose I wanted to publish one port to a known place, but sometime publish all the other "exposed" ports for debugging or testing.
A simple Dockerfile
FROM alpine
CMD /bin/sleep 600
--publish/-p allows me to bind a specific host port to a container port. --publish-all/-P binds all container ports to random ports, which can be found using, for example docker ps
.
$ docker build -t foo .
<build prints>
$ docker run -d -p 8000:8000 -P -p 9000:9000 foo
<some id prints>
$ docker ps --format '{{.Command}} {{.Ports}}'
"/bin/sh -c '/bin/sl…" 0.0.0.0:8000->8000/tcp, 0.0.0.0:9000->9000/tcp
But suppose I have a Dockerfile like this, and publish one port to a known port but the rest to randomly assigned ports.
FROM alpine
EXPOSE 8000
# Various management ports or something
EXPOSE 8005
EXPOSE 8443
EXPOSE 8009
CMD /bin/sleep 600
What is the defined behavior for
$ docker run -d -P -p 8000:8000 foo
Upvotes: 5
Views: 3954
Reputation: 3045
Doing exactly this the behavior seems to be "as expected". The explicit port bindings take precedence over the --publish-all
, independent of where the flags occur. In the example above, the results are
$ docker ps --format '{{.Command}} {{.Ports}}'
"/bin/sh -c '/bin/sl…" 0.0.0.0:8000->8000/tcp, 0.0.0.0:32792->8005/tcp, 0.0.0.0:32791->8009/tcp, 0.0.0.0:32790->8443/tcp
The explicit requested port binding occurs, and the other ports are bound to os-assigned unused ports.
It also clarified something to me I did not understand. I've always mostly ignored "EXPOSE" since the documentation basically said that it doesn't actually do anything but serve as documentation, and to actually "expose" a port you should publish it explicitly. But --publish-all
does use the exposed ports. I had been naively thinking that by doing --publish-all
it would publish ALL the ports that the process I had started was listening on, but those ports are opened after the container is already initialized.
Upvotes: 3