Is there a way to unexpose a port in Dockerfile? - docker

I am trying to deploy a mosquitto MQTT broker in our corporate cloud through docker image. The allowed ports that are exposed are in the range of 10000-10999.
By default eclipse-mosquitto image exposes port 1883. Is there a way to unexpose port 1883 and expose 10883?
This is my Dockerfile:
FROM eclipse-mosquitto:latest
COPY mosquitto.conf /mosquitto/config/
COPY docker-entrypoint.sh mosquitto-no-auth.conf /
EXPOSE 10883
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["/usr/sbin/mosquitto", "-c", "/mosquitto/config/mosquitto.conf"]

Just because the container exposes port 1883 that doesn't mean that's the port you need to use access a running instance.
When you start the container using the docker run command you get to decide what port on the host machine is mapped to that port on the container.
E.g.
docker run -d -p 10883:1883 eclipse-mosquitto
This will expose port 10883 on the host and map it to 1883 on the container.

"Expose" in dockerfile is kind of a meta data which tells which port you should work with. It does not open any port. So you can easily open any port you want.

Related

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.
"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
the service itself (for instance nginx) inside the image/container
EXPOSE xxxx in the Dockerfile (ie at build time of the image)
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 will listen to port xxxx at runtime. You can see this as sort of documentation for that image. So it's your responsibility as creator of the Dockerfile to provide the correct value 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 that port when you run the container (for instance when using docker run via -p aaaa:xxxx).
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

Unable to run application on Docker if used any other port except default port 80

I have a demo app which is hosted on docker. The exposed port for Docker is 80 and the app is running fine on local machine and I am able to see landing page for my app on localhost:8888.
Docker file is as given below
FROM microsoft/aspnetcore:2.0
COPY dist /app
WORKDIR /app
EXPOSE 80/tcp
ENTRYPOINT ["dotnet", "demoapp.dll"]
Whenever I change line "EXPOSE 80/tcp" to for ex- "EXPOSE 8080/tcp" , "EXPOSE 5000/tcp" etc to expose any other port except 80 of Docker container as given in many online available sample codes, I am unable to run my app on browser. Any port except 80 is not working.
I am able to create image and create container for application too. Everything goes well but when I try to run app on browser (localhost:8080/5000/9000 etc.) The app landing page doesn't load.
Any suggestions? Do I need to do some port related configuration or contact my network team? or any code which I am missing here?
You should be able to expose any port inside the container.
However you publish the exposed port on the host during the start of the container.
This is done with the -p flag of the docker run command.
When you say you are able to access the application using localhost:8888 it means you have run the docker run command with -p 8888:80. This publishes the container port 80 onto the host as port 8888.
To use any other port just change the docker run command to -p 8888:<new exposed port> and that should do it.
See the docker run command help for more info:
https://docs.docker.com/v17.12/edge/engine/reference/commandline/run/#publish-or-expose-port--p-expose
Publish or expose port (-p, –expose)
$ docker run -p 127.0.0.1:80:8080 ubuntu bash
This binds port 8080 of the container to port 80 on
127.0.0.1 of the host machine. The Docker User Guide explains in detail how to manipulate ports in Docker.
If your application runs at port suppose 8080 then make sure to do port mapping while running the container.
docker run -itd -p 8080:8080 <image>
This will map port 8080 of host on port 8080 inside the container. (-p hostport:containerport)
If you don't want port mapping then run docker container in host mode.
docker run -itd --net=host <image>
In this case your container use host network, so whatever port your application is running inside it should get exposed.
For microsoft/aspnetcore, it sets the ASPNETCORE_URLS environment variable to http://+:80 which means that if you have not explicity set a URL in your application, via app.UseUrl in your Program.cs for example, then your application will be listening on port 80 inside the container.
Reference: microsoft/aspnetcore
If you want to change the default port 80, you need to use UseUrls in Program.cs with like below, and use EXPOSE 8080/tcp in dockerfile.
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseUrls("http://+:8080")
.UseStartup<Startup>();
Or, you need to change ASPNETCORE_URLS environment like
FROM microsoft/aspnetcore:2.0
COPY dist /app
WORKDIR /app
EXPOSE 8080/tcp
ENV ASPNETCORE_URLS=http://+:8080
ENTRYPOINT ["dotnet", "demoapp.dll"]
Command to run
docker run -it -p 8080:8080 mytest

Container should communicate to host network, but does not

I have a two HTTP servers on my host machine; one listening on 8080, the other listening on 8081. The 8080 is a webapp, and the 8081 is an API.
I also have a Docker container that should connect to the webapp on 8080 using an automated tool, and that webapp should make HTTP requests to the API that's on 8081.
Here is a visual representation of what I want:
Host machine HTTP 8080
⇩ ⇖
⇧ Docker container
Host machine HTTP 8081
The problem I'm having is that the Docker container cannot connect to the website on the host machines 8080. I'm not sure why, because I set the --network=host flag, so shouldn't it be using the host machines network?
This is my Docker image:
## Redacted irrelevant stuff...
EXPOSE 8080 8081
This is how run the container:
docker run -d -p 8080:8080 -p 8081:8081 --network=host --name=app app
Any ideas what's wrong with my setup?
So you have two services running directly on the machine and you want to deploy a Docker container that should connect to one of those services.
In that case, you shouldn't map those port to the container and you shouldn't expose those ports in the Dockerfile as those ports are not for the container.
Remove the Expose ports from the Dockerfile
Start the container using docker run -d --network=host --name=app app. The container should be able to access the services using localhost:8080.

How to expose more ports on a running docker container

I have exposed port 3306 on my docker container, and I would like to install a web server on it and expose port 80 on the same container.
I don't think you can actually expose more port as the container is running, you'll have to recreate it and expose all of your ports

How to assign as static port to a container?

I want to assign a container a port, so that it gets the same port after every restart of the container.
Example:
I have a container, which has an Apache in it. The Apache runs on port 80 inside the container.
Now, after starting the container, docker assigns a host port to the container port, for example: 49154 -> 80. But the host port changes after restart, depending on the number of running containers. I tried to specify the port in the config.json file of the container, but it gets overwritten.
Is it possible to specify the host port manually?
Thanks in advance and best regards,
Chris
Per the docker.io documentation: https://docs.docker.com/engine/userguide/networking/default_network/dockerlinks/
$ sudo docker run -p 80:80 <image> <cmd>
Default port redirects can be built into a container with the EXPOSE build command.
When you start docker, you can use the '-p' parameter.
docker run -p 80 yourimage apache2 will do what you currently have.
Now, you can specify ':' to make this port static:
docker run -p :80 -p :443 yourimage apache2
If you are using a Dockerfile with the EXPOSE instruction, it is the same thing :)

Resources