Question
I'm experimenting with Dockerfiles, and I think I understand most of the logic. However, I don't see the difference between "exposing" and "publishing" a port in this context.
All the tutorials I have seen first include the EXPOSE
command in the
Dockerfile:
...
EXPOSE 8080
...
They then build an image from this Dockerfile:
$ docker build -t an_image - < Dockerfile
And then publish the same port as above when running the image:
$ docker run -d -p 8080 an_image
or publish all ports using
$ docker run -d -P an_image
What is the point of exposing a port in the Dockerfile, if it will be published anyway? Would there ever be a need to expose a port first, and not publish it later? Effectively, I would like to specify all the ports that I will use in the Dockerfile when creating the image, and then not bother with them again, running them simply with:
$ docker run -d an_image
Is this possible?
Answer
Basically, you have three (four) options:
-
Neither specify
EXPOSE
nor-p
-
Only specify
EXPOSE
-
Specify
EXPOSE
and-p
-
Only specify
-p
which implicitly doesEXPOSE
-
If you specify neither
EXPOSE
nor-p
, the service in the container will only be accessible from inside the container itself. -
If you
EXPOSE
a port, the service in the container is not accessible from outside Docker, but from inside other Docker containers. So this is good for inter-container communication. -
If you
EXPOSE
and-p
a port, the service in the container is accessible from anywhere, even outside Docker. -
If you do
-p
, but do notEXPOSE
, Docker does an implicitEXPOSE
. This is because if a port is open to the public, it is automatically also open to other Docker containers. Hence-p
includesEXPOSE
. This is effectively same as 3).
The reason why both are separated is IMHO because:
- choosing a host port depends on the host and hence does not belong to the Dockerfile (otherwise it would be depending on the host),
- and often it's enough if a service in a container is accessible from other containers.
The documentation explicitly states:
The
EXPOSE
instruction exposes ports for use within links.
It also points you to how to link containers (legacy feature), which basically is the inter-container communication I talked about.