Letting a container know its exposed ports in Docker - docker

Let's say I start a container, exposing a random port to 80 like this: docker run -d -p 80 -name my_container username/container.
Is there any way to tell my_container on which host's port his 80 was exposed?
Edit: My situation:
I'm running Apache to serve some static HTML files, and an Go API server on this container. I'm exposing both services here. The static files request data from the server via javascript on the user's browser, but to be able to do this, the clients need to know on which port the API server is made available, to be able to connect to it. Is this the appropriate way to do this?

I don't think there exists an easy to tell from the container the host port on which its port 80 was exposed, but I also believe there is a good reason for that: making the container dependent on this would make it dependent on its containing environment, which goes against Docker's logic.
If you really need this, you could pass the host port as an environment variable to the container using the -e flag (assuming that the host port is fixed), or rely on a hack such as mounting the Docker socket in the container (-v /var/run/docker.sock:/var/run/docker.sock) and have it "inspect himself" (which is similar to what progrium/ambassadord does to implement its omni mode).
Maybe you should clarify why you need this information in the first place and perhaps there's a simpler solution that can help you achieve that.

You can run docker ps which will show the ports, for example
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
containerid ubuntu:14.04 /bin/bash 14 seconds ago Up 13 seconds 0.0.0.0:49153->80/tcp my_container
In this instance it is 49153.
Also docker inspect will tell you lots about your container, including the port mappings
$ docker inspect my_container | grep HostPort
"HostPort": "49153"

Related

Custom configuration for redis container

I want to adapt my redis settings via custom conf file and followed the documentation for the implementation. Running my container with the following command throws no error - so far so good.
docker run --name redis-container --net redis -v .../redis:/etc/redis -d redis redis-server /etc/redis/redis.conf
To check if my config file is read I switched the default port 6379 to port 6380 but looking at my docker ports via docker ps shows the default 6379 as my port.
Is there a difference between the redis port itself and the container port or where is my problem located?
The standard Redis image Dockerfile contains the line
EXPOSE 6379
Once a port has been exposed this way, there is no way to un-expose it. Exposing a port has fairly few practical effects in modern Docker, but the most visible is that 6379/tcp will show up in the docker ps output for each exposed port even if it's not separately published (docker run -p). There's no way to remove this port number from the docker ps output.
Docker's port system (the EXPOSE directive and the docker run -p option) are a little bit disconnected from what the application inside the container is actually doing. In your case the container is configured to expose port 6379 but the process is actually listening on port 6380; Docker has no way of knowing these don't match up. Changing the application configuration won't change the container configuration, and vice versa.
As a practical matter you don't usually need to change application ports. Since this Redis will be the only thing running in its container and its corresponding isolated network namespace, it can't conflict with other Redises on the host or in other containers. If you need to remap it on the host, you can use different port numbers for -p; the second number must match what the process is listening on (and Docker can't auto-detect or check this) but the first can be any port.
docker run -p 6380:6379 ... redis
If you're trying to check whether your configuration has had an effect, running CONFIG GET via redis-cli could be a more direct way to ask what the server's configuration is.

How to assign public IP's to docker conteiners?

I want to run 5 docker cointeiners with same app, it uses port 50505, I want expose this port to internet.
My server runs Ubuntu 18.04
Assigned IPs
204.12.240.210-214
So looks like i got 4 IP adresses
I can ssh to any of them and it works.
Now I am bit fresh with docker still learning it.
Anyone could give commands how to create network with this IP and then how to start instance with this IP's ?
I believe its possible.
Normalli I start app like this:
docker run -d -P --net=host -v /mnt/chaindata:/go-matrix/chaindata --name matrix --restart always disarmm/matrix
But when u start 2nd instance it will crash cuz ports are used by first one
So I could fix that with IP's
It doesn't seem a question regarding Docker, if I were you, I would setup a Nginx as a proxy/load balancer and pass traffic to the backend service, be it any service running on Docker or others
Also you can create Nginx using Docker
Next is how you assign the IP and find the port Nginx is listening to
To be honestly, I don't know how to handle it with --net=host.
But, one possible solution is: not use host network, use default bridge0's bridge network. But you need to know the ports of your application used, and expose it by yourself. Then, when expose the ports, you can specify the ip.
Something like follows:
docker run -d -p 204.12.240.210:80:80 -p 204.12.240.210:8080:8080 disarmm/matrix
docker run -d -p 204.12.240.211:80:80 -p 204.12.240.211:8080:8080 disarmm/matrix
Then, you can see in host, you have two 80/8080 ports open on same host machine binding with different IP.
As mentioned above, the limit is: you have to know what ports you used exactly.
See this for format.

Need some help on Docker's dynamic port mapping with Host?

I have a use case where there will be multiple Docker containers running with web server. I can't bind port 80 for all containers. I am looking for a solution where I can bind container's dynamic ports to host at 80. Is it something possible with Traefik? If so, how?
I have to implement it for gitlab's review-apps. If anyone has done it before, please guide me.
If I understood your question, you can do it at the primitive stage itself while starting the container. Below command will bind port 80 of host to a dynamic (random) port on the container:
docker run --name <container-name> -d -p 80 <image-name>
If you are talking about knowing the dynamic ports you need to use a service discovery tool which in turn will talk to Docker API and extract the information for you.
N.B: I don't have much idea about Traefik but the above are usual ways to achieve what is asked.

How to get the mapped port on host from a docker container?

I want to run a task in some docker containers on different hosts. And I have written a manager app to manage the containers(start task, stop task, get status, etc...) . Once a container is started, it will send an http request to the manager with its address and port, so the manager will know how to manage the container.
Since there may be more than one containers running on a same host, they would be mapped to different ports. To register a container on my manager, I have to know which port each container is mapped to.
How can I get the mapped port inside a docker container?
There's an solution here How do I know mapped port of host from docker container? . But it's not applicable if I run container with -P. Since this question is asked more than 1 year ago, I'm wondering maybe there's a new feature added to docker to solve this problem.
You can also you docker port container_id
The doc
https://docs.docker.com/engine/reference/commandline/port/
examples from the doc
$ docker port test
7890/tcp -> 0.0.0.0:4321
9876/tcp -> 0.0.0.0:1234
$ docker port test 7890/tcp
0.0.0.0:4321
$ docker port test 7890/udp
2014/06/24 11:53:36 Error: No public port '7890/udp' published for test
$ docker port test 7890
0.0.0.0:4321
i share /var/run/docker.sock to container and get self info
docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock alpine:latest sh
in container shell
env //get HOSTNAME
curl --unix-socket /var/run/docker.sock http://localhost/containers/3c6b9e44a622/json
the 3c6b9e44a622 is your HOSTNAME
Once a container is started, it will send an http request to the manager with its address and port
This isn't going to be working. From inside a container you cannot figure out to which docker host port a container port is mapped to.
What I can think about which would work and be the closest to what you describe is making the container open a websocket connection to the manager. Such a connection would allow two ways communication between your manager and container while still being over HTTP.
What you are trying to achieve is called service discovery. There are already tools for service discovery that work with Docker. You should pick one of them instead of trying to make your own.
See for instance:
etcd
consul
zookeeper
If you really want to implement your service discovery system, one way to go is to have your manager use the docker event command (or one of the docker client librairies). This would enable your manager to get notified of containers creations/deletions with nothing to do on the container side.
Then query the docker host to figure out the ports that are mapped to your containers with docker port.

prevent Docker from exposing port on host

If i start a container using -p 80 for example, docker will assign a random outbound port.
Everytime Docker assign a port, it also add an iptable rule to open this port to the world, is it possible to prevent this behaviour ?
Note : I am using a nginx load balancer to get the content, I really don't need to have my application associated with two different port.
You can specify both interface and port as follows:
-p ip:hostPort:containerPort
or
-p ip::containerPort
Another solution is to run nginx inside container and to use conteiner linking without exposing other services whatsoever.
The iptable feature is a startup parameter for the docker demon. Look for the docker demon conf file in your docker installation. Add --iptables=false and docker never touches your iptables.

Resources