ChatGPT解决这个技术问题 Extra ChatGPT

What is the difference between docker-compose ports vs expose

What is the difference between ports and expose options in docker-compose.yml?


o
ospider

According to the docker-compose reference,

Ports is defined as:

Expose ports. Either specify both ports (HOST:CONTAINER), or just the container port (a random host port will be chosen).

Ports mentioned in docker-compose.yml will be shared among different services started by the docker-compose.

Ports will be exposed to the host machine to a random port or a given port.

My docker-compose.yml looks like:

mysql:
  image: mysql:5.7
  ports:
    - "3306"

If I do docker-compose ps, it will look like:

  Name                     Command               State            Ports
-------------------------------------------------------------------------------------
  mysql_1       docker-entrypoint.sh mysqld      Up      0.0.0.0:32769->3306/tcp

Expose is defined as:

Expose ports without publishing them to the host machine - they’ll only be accessible to linked services. Only the internal port can be specified.

Ports are not exposed to host machines, only exposed to other services.

mysql:
  image: mysql:5.7
  expose:
    - "3306"

If I do docker-compose ps, it will look like:

  Name                  Command             State    Ports
---------------------------------------------------------------
 mysql_1      docker-entrypoint.sh mysqld   Up      3306/tcp

Edit

In recent versions of Dockerfile, EXPOSE doesn't have any operational impact anymore, it is just informative. (see also)


would it be possible eto explain what advantages there are to specifying expose in a docker-compose? As far as I can tell, you don't need to specify expose to make ports accessible to linked services.
Shouldn't it tell that exposed ports will only be available to services in the same docker network (linking is being replaced for most parts)?.
@Juicy I guess it's similar to expose in Dockerfiles: "The EXPOSE instruction does not actually publish the port. It functions as a type of documentation..." docs.docker.com/engine/reference/builder/#expose
Do Ports override any settings at the firewall level? I just noticed that I didn't open up ports for mysql on the firewall, but they were accessible remotely. I had Ports set to "3306:3306" instead of expose.
And remember, if you use docker-compose run, the port definition in docker-compose.yml is ignored by default. Either use docker-compose up or provide the parameter --service-ports
s
steampowered

ports:

Activates the container to listen for specified port(s) from the world outside of the docker(can be same host machine or a different machine) AND also accessible world inside docker. More than one port can be specified (that's is why ports not port)

https://i.stack.imgur.com/Nb6Om.png

expose:

Activates container to listen for a specific port only from the world inside of docker AND not accessible world outside of the docker. More than one port can be specified

https://i.stack.imgur.com/s4k6E.png


Note that expose allows multiple ports - docs.docker.com/compose/compose-file/#expose - however you only supply the internal port rather than internal + external
That's very important part: 'Activates container to listen for a specific port only from the world inside'
s
sorabzone

Ports This section is used to define the mapping between the host server and Docker container.

ports:
   - 10005:80

It means the application running inside the container is exposed at port 80. But external system/entity cannot access it, so it need to be mapped to host server port.

Note: you have to open the host port 10005 and modify firewall rules to allow external entities to access the application.

They can use

http://{host IP}:10005

something like this

EXPOSE This is exclusively used to define the port on which application is running inside the docker container.

You can define it in dockerfile as well. Generally, it is good and widely used practice to define EXPOSE inside dockerfile because very rarely anyone run them on other port than default 80 port


B
BMitch

Ports

The ports section will publish ports on the host. Docker will setup a forward for a specific port from the host network into the container. By default this is implemented with a userspace proxy process (docker-proxy) that listens on the first port, and forwards into the container, which needs to listen on the second point. If the container is not listening on the destination port, you will still see something listening on the host, but get a connection refused if you try to connect to that host port, from the failed forward into your container.

Note, the container must be listening on all network interfaces since this proxy is not running within the container's network namespace and cannot reach 127.0.0.1 inside the container. The IPv4 method for that is to configure your application to listen on 0.0.0.0.

Also note that published ports do not work in the opposite direction. You cannot connect to a service on the host from the container by publishing a port. Instead you'll find docker errors trying to listen to the already-in-use host port.

Expose

Expose is documentation. It sets metadata on the image, and when running, on the container too. Typically you configure this in the Dockerfile with the EXPOSE instruction, and it serves as documentation for the users running your image, for them to know on which ports by default your application will be listening. When configured with a compose file, this metadata is only set on the container. You can see the exposed ports when you run a docker inspect on the image or container.

There are a few tools that rely on exposed ports. In docker, the -P flag will publish all exposed ports onto ephemeral ports on the host. There are also various reverse proxies that will default to using an exposed port when sending traffic to your application if you do not explicitly set the container port.

Other than those external tools, expose has no impact at all on the networking between containers. You only need a common docker network, and connecting to the container port, to access one container from another. If that network is user created (e.g. not the default bridge network named bridge), you can use DNS to connect to the other containers.


Listen, folks! This answer may not look so nice, but is extremely informative.
F
FishingIsLife

I totally agree with the answers before. I just like to mention that the difference between expose and ports is part of the security concept in docker. It goes hand in hand with the networking of docker. For example:

Imagine an application with a web front-end and a database back-end. The outside world needs access to the web front-end (perhaps on port 80), but only the back-end itself needs access to the database host and port. Using a user-defined bridge, only the web port needs to be opened, and the database application doesn’t need any ports open, since the web front-end can reach it over the user-defined bridge.

This is a common use case when setting up a network architecture in docker. So for example in a default bridge network, not ports are accessible from the outer world. Therefor you can open an ingresspoint with "ports". With using "expose" you define communication within the network. If you want to expose the default ports you don't need to define "expose" in your docker-compose file.