Celtic Bean
Celtic Bean

Reputation: 79

Docker expose port internals

In Docker we all know how to expose ports, EXPOSE instruction publishes and -p or -P option to expose during runtime. When we use "docker inspect" or "docker port" to see the port mappings and these configs output are pulled /var/lib/docker/containers/container-id/config.v2.json.

The question I got is when we expose port how does Docker actually changes the port in container, say the Apache or Nginx, say we can have the installation anywhere in the OS or file path, how does Docker finds the correct conf file(Apache /etc/httpd/conf/httpd.conf) to change if I suppose Docker does this on the line "Listen 80" or Listen "443" in the httpd.conf file. Or my whole understanding of Docker is in stake:)

Any help is appreciated.

Upvotes: 0

Views: 8477

Answers (1)

derpirscher
derpirscher

Reputation: 17372

"docker" does not change anything in the internal configuation of the container (or the services it provides).

There are three different points where you can configure ports

  1. the service itself (for instance nginx) inside the image/container

  2. EXPOSE xxxx in the Dockerfile (ie at build time of the image)

  3. docker run -p 80:80 (or the respective equivalent for docker compose) (ie at the runtime of the container)

All three are (in principle) independent of each other. Ie, you can have completely different values in each of them. But in practice, you will have to adjust them to each other to get a working system.

We know, EXPOSE xxxx in the dockerfile doesn't actually publish any port at runtime, but just tells the docker service, that that specific container is running some service that supposed to be listening to port xxxx at runtime. You can see this as sort of documentation for that image. And those EXPOSEd ports will be used when running an image via docker run -P someimage. So it's your responsibility as creator of the Dockerfile to provide the correct values here. Because anyone using that image, will probaby rely on that value.

But regardless, of what port you have EXPOSEd (or not, EXPOSE is completely optional) you still have to publish/bind that port when you run the container For instance when using docker run via -p aaaa:xxxx or when using docker compse via a ports: ... definition in your dockercompose.yml file. Or you could use docker run -P which will pickup the EXPOSEd ports and create an automated binding for them. But be aware that -P uses random ports on the host machine.

Now let us assume you have an nginx image which has the nginx service configured to listen to port 8000. Regardless of what you define with EXPOSE or -p aaaa:xxxx, that nginx service will always listen to port 8000 only and nothing else.

So if you now run your container with docker run -p 80:80, the runtime will bind port 80 of the host to port 80 of the container. But as there is no service listening on port 80 within the container, you simply won't be able to contact your nginx service on port 80. And you also won't be able to connect to nginx on port 8000, because it hasn't been published.

So in a typical setup, if your service in the container is configured to listen to port 8000, you should also EXPOSE 8000 in your dockerfile and use docker run -p aaaa:8000 to bind port aaaa of your host machine to port 8000 of your container, so that you will be able to connect to the nginx service via http://hostmachine:aaaa

Upvotes: 2

Related Questions