How do I know mapped port of host from docker container? - linux

I have a docker container running where I a have mapped 8090 port of host to 8080 port of docker container (running a tomcat server). Is there any way by which I can get the mapped port information from container?
i.e. is there any way by which I can get to know about 8090:8080 mapping from container?

When you link containers, docker sets environment variables which you can use inside one docker to tell how you can communicate with another docker. You can manually do something similar to let your docker know about the host's mapping:
export HOST_8080=8090
docker run -p $HOST_8080:8080 -e "HOST_8080=$HOST_8080" --name my_docker_name my_docker_image /bin/bash -c export
explanation:
export HOST_8080=8090 defines an environment variable on your host (so you won't have to write the "8090" thing twice).
-p $HOST_8080:8080 maps the 8090 port on the host to 8080 on the docker.
-e "HOST_8080=$HOST_8080" defines an environment variable inside the docker, which is called HOST_8080, with value 8090.
/bin/bash -c export just prints the environment variables so you can see this is actually working. Replace this with your docker's CMD.

Related

What does localhost means inside a Docker container?

Say, if I use this command inside a docker container.
/opt/lampp/bin/mysql -h localhost -u root -pThePassword
What would the localhost here refer to? The host machine's IP or the docker container's own IP?
From inside a container, localhost always refers to the current container. It never refers to another container, and it never refers to anything else running on your physical system that's not in the same container. It's not usually useful to make outbound connections to localhost or configure localhost as your database host.
From a shell on your host system, localhost could refer to daemons running on your system outside Docker, or to ports you've published with docker run -p options.
From a different system, localhost refers to the system it's called from.
In terms of IP addresses, localhost is always 127.0.0.1, and that IP address is special and is always localhost and behaves the same way as above.
If you want to make a connection to a container...
...from another container, the best way is to make sure they're on the same Docker network (you started them from the same Docker Compose YAML file; you did a docker network create and then did docker run --net ... on the same network) and use Docker's internal DNS service to refer to them by the container's --name or its name in the Docker Compose YAML file and the port number inside the container. Even if the target has a published port with a docker run -p option or Docker Compose ports: setting, use the second (container-internal) port number.
...from outside Docker space, make sure you started the container with a docker run -p or Docker Compose ports: option, and connect to the host's IP address or DNS name using the first port number from that option.
...from a terminal window or browser on the same physical host, not in a container, in this case and in this case only, localhost will work consistently.
Except:
If you started a container with --net host, localhost refers to the physical host, and you're in the "terminal window on the same physical host" scenario.
If you've gone out of your way to have multiple servers in the same container, you can use localhost to communicate between them.
If you're running in Kubernetes, and you have multiple containers in the same pod, you can use localhost to communicate between them. Between pods, you should set up a service in front of each pod/deployment, and use DNS names of the form service-name.namespace-name.svc.cluster.local.
Definitely, It will be your container, if you are running command in container.
/opt/lampp/bin/mysql -h localhost -u root -pThePassword
If you run this command inside container then it will try to connect mysql running inside container.

Deploying in azure with --net doesn't bind

I am trying to deploy a docker container that has to use other external services so I added the --net flag while running the container.
docker run -it --net=host -p 8090:8000 --env-file=.env -v /etc/logs:/logs --restart=always -d --name=rank rank
But when I check my docker's containers with docker ps -a it doesn't show that the port binding is correctly done. Nevertheless, if I remove the --net flag it runs but it can't communicate to Redis docker.
When using --net=host the port mapping has no effect. You are running the container on your host network, so whichever port the program inside your container is binding to, is bound to the host.
You cannot change the port, the only way would be to have the port inside the container controlled using a environment variable or a config.
docker doesn't through an error when both options are used but it ignores the port mapping as such when --net=host is used. So that is the reason your container runs but doesn't show any port mapping

How can I forward localhost port on my container to localhost on my host?

I have a daemon on my host running on some port (i.e. 8008) and my code normally interacts with the daemon by contacting localhost:8008 for instance.
I've now containerized my code but not yet the daemon.
How can I forward the localhost:8008 on my container to localhost:8008 on the host running the container (and therefore the daemon as well).
The following is netstat -tlnp on my host. I'd like the container to forward localhost:2009 to localhost:2009 on the host
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:2009 0.0.0.0:* LISTEN 22547/ssh
tcp6 0 0 :::22 :::* LISTEN -
tcp6 0 0 ::1:2009 :::* LISTEN 22547/ssh
So the way you need to think about this is that Docker containers have their own network stack (unless you explicitly tell it to share the host's stack with --net=host). This means ports need to be exposed both inside the docker container and also on the outside (documentation), when linked with host ports. The ports exposed on the container need to be bound to the host ports explicitly (with -p xxxx:yyyy in your docker run command) or implicitly (using EXPOSE in your Dockerfile and using -P on the command line), like it says here. If your Dockerfile does not contain EXPOSE 8008, or you do not specify --expose 8008 in your docker run command, your container can't talk to the outside world, even if you then use -p 8008:8008 in your docker run command!
So to get tcp/8008 on the host linked with tcp/8008 on the container, you need EXPOSE 8008 inside your Dockerfile (and then docker build your container) OR --expose 8008 in your docker run command. In addition, you need to either use -P to implicitly or -p 8008:8008 to explicitly link that exposed container port to the host port. An example docker run command to do this might look like:
docker run -it --expose 8008 -p 8008:8008 myContainer
It's handy to remember that in the -p 8008:8008 command line option, the order for this operation is -p HOST_PORT:CONTAINER_PORT. Also, don't forget that you won't be able to SSH into your container from another machine on the internet unless you also have this port unblocked in iptables on the host. I always end up forgetting about that and waste half an hour before I remember I forgot to iptables -A INPUT ... for that specific tcp port on the host machine. But you should be able to SSH from your host into the container without the iptables rule, since it uses loopback for local connections. Good luck!
TL;DR: You can use the special hostname host.docker.internal instead of localhost anywhere inside the container that you want to access localhost on the host. Note that:
macOS and Windows versions of Docker Desktop have this feature enabled by default.
Linux hosts (using Docker v 20.10 and above - since December 14th 2020) require you to add --add-host=host.docker.internal:host-gateway to your Docker command to enable the feature.
Docker Compose on Linux requires you to add the following lines to the container definition:
extra_hosts:
- "host.docker.internal:host-gateway"
Full answer: Is the host running MacOS or Windows? Buried in the documentation for Docker Desktop is the fact that there is no docker0 bridge on MacOS and there is no docker0 bridge on Windows. Apparently that's the cause of this. In both cases the workaround (given right after, in a subsection titled "Use cases and workarounds") is to use the special hostname host.docker.internal in placed of localhost anywhere inside the container that you want to access localhost on the host.
If the host is Linux, there are some Linux-only techniques for achieving this. However, host.docker.internal is also useable with a Linux host, but it has to be enabled first. See the Linux part of the TL;DR, above, for instructions.
By this method, in OP's case host.docker.internal:8008 should be used instead of localhost:8008. Note that this is a code or configuration change of the application code running inside the container. There is no need to mention the port in the container configuration. Do not try to use -p or --expose in the docker run commandline. Not only is it not necessary, but your container will fail to start if the host application you want the container to connect to is already listening on that port.
After checked the answers and did some investigation, I believe there are 2 ways of doing that and these 2 only work in Linux environment.
The first is in this post How to access host port from docker container
The second should be set your --network=host when you docker run or docker container create. In this case, your docker will use the same network interface you use in Mac.
However, both ways above cannot be used in Mac, so I think it is not possible to forward from the container to host in Mac environment. Correct me if I am wrong.
I'm not sure if you can do that just with docker's settings.
If my under standing is correct, expose port is not what you looking for.
Instead, establish ssh port forwarding from container to host mightbe the answer.
You can easily use -p 127.0.0.1:8008:8008 and forward the container's port 8008 to localhost's port 8008. An example docker command would be:
docker run -it -p 127.0.0.1:8008:8008 <image name>
If you're doing this on your local machine, you can simple specify the network type as host when starting your container (--network host), which will make your host machine share network with your docker container.
eg:
Start your container:
docker run -it --rm --network host <container>
On your host machine, Run:
python3 -m http.server 8822
Now from your container run:
curl 127.0.0.1:8822
If all went well you'll see traffic on your host terminal.
Serving HTTP on 0.0.0.0 port 8822 (http://0.0.0.0:8822/) ...
127.0.0.1 - - [24/Jan/2023 22:37:01] "GET / HTTP/1.1" 200 -
docker run -d --name <NAME OF YOUR CONTAINER> -p 8008:8008 <YOUR IMAGE>
That will publish port 8008 in your container to 8008 on your host.

Creating a container with a variable port

I want to create an image for couchdb, to run multiple couchdb instances. For reasons that are a bit long to clarify, I want the couchdb instance in the container to listen to a non default port, which is also not known at image definition time, since this will be a container parameter.
From the host I would run the container with:
sudo docker run -d -p 10000:30000 --name couchdb -e COUCHDB_PORT=30000 my/couchdb
Which would make the port in the container (30000), where couchdb is listening, to be reachable through port 10000 in the host. This port should a per-container paramenter.
This way from the container I could do:
curl -X GET localhost:30000
And from the host I could do:
curl -X GET localhost:10000
Both requests would be hitting the same couchdb server.
Setting up the container has been easy (it is just a matter of processing the environment variable to automatically edit the couchdb config file), but now I have reached a blocking problem. At the end of the Dockerfile I have:
# the default couchdb port, which in my case is not
# known at image creation time
EXPOSE 5984
Apparently I need to expose the port where my service is running inside the container, but I do not know that when creating the image. This is a run-time parameter, which will differ from container to container.
How can I expose a port when starting up the container?

Exposing a Docker container port

I have been trying to connect to a docker container via ip, but reamins unsuccessful. When I used "docker inspect container-id" I get this result.
My virtual box settings are by default:
Can someone help me resolving this issue?
When running docker, you can specify which port(s) you'd like to be accessible to the outside world. Basic syntax is:
docker run -p hostPort:containerPort imageName
or just
docker run -p hostPort imageName
In the first case, externally, hostPort will be used, but inside the container: containerPort will be used. In the second instance, you'd just be using that port both inside and outside your container.
You can also create an image with ports exposed by using the EXPOSE command in a Dockerfile.
You need to perform port forwarding or just simply expose port.
Port Forwarding:
docker run -p 2022:22 -p 2375:2375
Expose Port:
docker run -p 22 -p 2375

Resources