Difference between “expose” and “publish” in docker

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:

  • Problems with RSelenium
  • Error checking TLS connection with Docksal
  • getUserMedia in Firefox in Docker not working when using audio
  • Is it possible to perform Docker-call from a container into the host?
  • Docker: how to connect two bridges
  • serverspec command returning blank strings
  • ...
    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?

  • HAProxy over SSL with RabbitMQ SSL authentication + Kombu client - IOError('Socket Closed')
  • Pass messages as file through docker-py
  • Kindle in a docker-container
  • Microservices registering Docker internal IP on Eureka instead of public one
  • How to share host network bridge when using docker in docker
  • Docker+Jboss, port mapping
  • 2 Solutions collect form web for “Difference between “expose” and “publish” in docker”

    Basically, you have three options:

    • Neither specify EXPOSE nor -p.
    • Only specify EXPOSE.
    • Specify EXPOSE and -p.

    If you do not specify any of those, the service in the container will not be accessible from anywhere except 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.

    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, 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.

    The EXPOSE allow you to define private (container) and public (host) ports to expose at image build time for when the container is running.
    The public port is optional, if not a public port is specified, a random port will be selected on host by docker to expose the specified container port on Dockerfile.

    A good pratice is do not specify public port, because it limits only one container per host ( a second container will throw a port already in use ).

    You can use -p in docker run to control what public port the exposed container ports will be connectable.

    Anyway, If you do not use EXPOSE nor -p, no ports will be exposed.

    If you always use -p at docker run you do not need EXPOSE but if you use EXPOSE your docker run command may be more simple, EXPOSE can be useful if you don’t care what port will be expose on host, or if you are sure of only one container will be loaded.

    Docker will be the best open platform for developers and sysadmins to build, ship, and run distributed applications.