Basically, you have three options:
- Neither specify
EXPOSEnor-p - Only specify
EXPOSE - Specify
EXPOSEand-p
1) If you specify neither EXPOSE nor -p, the service in the container will only be accessible from inside the container itself.
2) 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.
3) If you EXPOSE and -p a port, the service in the container is accessible from anywhere, even outside Docker.
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
EXPOSEinstruction exposes ports for use within links.
It also points you to how to link containers, which basically is the inter-container communication I talked about.
PS: If you do -p, but do not EXPOSE, Docker does an implicit EXPOSE. This is because if a port is open to the public, it is automatically also open to other Docker containers. Hence -p includes EXPOSE. That’s why I didn’t list it above as a fourth case.