How do I publish a UDP Port on Docker? - docker

How do I forward a UDP port from my Docker container to the host machine?

Use the -p flag and add /udp suffix to the port number.
-p 53160:53160/udp
Full command
sudo docker run -p 53160:53160 \
-p 53160:53160/udp -p 58846:58846 \
-p 8112:8112 -t -i aostanin/deluge /start.sh
If you're running boot2docker on Mac, be sure to forward the same ports on boot2docker to your local machine.
You can also document that your container needs to receive UDP using EXPOSE in The Dockerfile (EXPOSE does not publish the port):
EXPOSE 8285/udp
Here is a link with more Docker Networking info covered in the container docs:
https://docs.docker.com/config/containers/container-networking/
(Courtesy of Old Pro in the comments)

Just thought I would pitch in for docker-compose config.
ports:
- "9955:9955/udp"

Related

Is it possible to set a port under "host mode" in docker?

Is it possible to config the port number in docker under "host mode"?
I wanna bind the application to 5050 port instead of 80 port .
However, when I run below script, it will default bind in 80 port:
sudo docker run --name=myname --network host -d webapi:1.0.0 --restart=always
So I tried to run with "-p 5050", for example
sudo docker run --name=myname --network host -d webapi:1.0.0 --restart=always -p 5050
sudo docker run --name=myname --network host -d webapi:1.0.0 --restart=always -p 5050:5050
Unfortunately, my Linux terminal returned with :
WARNING: Published ports are discarded when using host network mode
The docker image looks like something like this:
https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/docker/building-net-docker-images?view=aspnetcore-2.2
And my Dockerfile looks like this:
FROM microsoft/dotnet:2.1-aspnetcore-runtime
WORKDIR /publish
COPY . .
EXPOSE 5050
ENTRYPOINT ["dotnet", "WebApi.dll"]
Easy way out would be to run your application on 5050 port. Once your container is up & running you must be able to access your app on port 5050 on Docker host. You need not to bind any kind of ports because you are using the host network itself.
Thanks user "#atline" for the answer.
Only 80 port is allowed.
More reference is found here:
https://docs.docker.com/network/host/

Does docker require additional port when try to run container?

In my workplace docker is running behind firewall, only the port that is meant to serve webpage is excluded by rule.
The container starts but website does not open for same port.
If I host the website from machine running container using python -m SimpleHTTPServer it works.
docker container run --restart=always -p 8081: 8082 -it vue-js-app: latest
From the Docker documentation:
Publish or expose port (-p, --expose)
$ docker run -p 127.0.0.1:80:8080/tcp ubuntu bash
This binds port 8080 of the container to TCP port 80 on 127.0.0.1 of
the host machine. You can also specify udp and sctp ports. The Docker
User Guide explains in detail how to manipulate ports in Docker.
$ docker run --expose 80 ubuntu bash
This exposes port 80 of the container without publishing the port to
the host system’s interfaces.
And, from the Docker User Guide:
You also saw how you can bind a container’s ports to a specific port
using the -p flag. Here port 80 of the host is mapped to port 5000 of
the container:
$ docker run -d -p 80:5000 training/webapp python app.py
So, as an example of how to expose the ports you can use:
docker container run --restart always -p 8081:8082 -it vue-js-app:latest

How to connect to server on Docker from host machine?

Ok, I am pretty new to Docker world. So this might be a very basic question.
I have a container running in Docker, which is running RabbitMQ. Let's say the name of this container is "Rabbit-container".
RabbitMQ container was started with this command:
docker run -d -t -i --name rmq -p 5672:5672 rabbitmq:3-management
Python script command with 2 args:
python ~/Documents/myscripts/migrate_data.py amqp://rabbit:5672/ ~/Documents/queue/
Now, I am running a Python script from my host machine, which is creating some messages. I want to send these messages to my "Rabbit-container". Hence I want to connect to this container from my host machine (Mac OSX).
Is this even possible? If yes, how?
Please let me know if more details are needed.
So, I solved it by simply mapping the RMQ listening port to host OS:
docker run -d -t -i --name rmq -p 15672:15672 -p 5672:5672 rabbitmq:3-management
I previously had only -p 15672:15672 in my command. This is mapping the Admin UI from Docker container to my host OS. I added -p 5672:5672, which mapped RabbitMQ listening port from Docker container to host OS.
If you're running this container in your local OSX system then you should find your default docker-machine ip address by running:
docker-machine ip default
Then you can change your python script to point to that address and mapped port on <your_docker_machine_ip>:5672.
That happens because docker runs in a virtualization engine on OSX and Windows, so when you map a port to the host, you're actually mapping it to the virtual machine.
You'd need to run the container with port 5672 exposed, perhaps 15672 as well if you want WebUI, and 5671 if you use SSL, or any other port for which you add tcp listener in rabbitmq.
It would be also easier if you had a specific IP and a host name for the rabbitmq container. To do this, you'd need to create your own docker network
docker network create --subnet=172.18.0.0/16 mynet123
After that start the container like so
docker run -d --net mynet123--ip 172.18.0.11 --hostname rmq1 --name rmq_container_name -p 15673:15672 rabbitmq:3-management
note that with rabbitmq:3-management image the port 5672 is (well, was when I used it) already exposed so no need to do that. --name is for container name, and --hostname obviously for host name.
So now, from your host you can connect to rmq1 rabbitmq server.
You said that you have never used docker-machine before, so i assume you are using the Docker Beta for Mac (you should see the docker-icon in the menu bar at the top).
Your docker run command for rabbit is correct. If you now want to connect to rabbit, you have two options:
Wrap your python script in a new container and link it to rabbit:
docker run -it --rm --name migration --link rmq:rabbit -v ~/Documents/myscripts:/app -w /app python:3 python migrate_data.py
Note that we have to link rmq:rabbit, because you name your container rmq but use rabbit in the script.
Execute your python script on your host machine and use localhost:5672
python ~/Documents/myscripts/migrate_data.py amqp://localhost:5672/ ~/Documents/queue/

Is it possible to set a different host port than the container's exposed port in docker?

Is it possible to set a different host port than the container's exposed port in docker? For example docker run -name some_container -p 80:8080 -i -t some_img If so, is it -p host:container or -p container:host? I've looked through the docs and haven't found any examples of this nor details on the publish option for docker run.
Additionally, I don't want to use the same port as the container because that is where Kubernete's api-server is listening.
It is host:container and it is possible to set different port on the host.
This Link has some good examples.
Yes you can map any host port to container port unless it is being used by other application
docker run -p 80:8080 --name=centos centos:latest
it is host:container format.

Exposing a port on a live Docker container

I'm trying to create a Docker container that acts like a full-on virtual machine. I know I can use the EXPOSE instruction inside a Dockerfile to expose a port, and I can use the -p flag with docker run to assign ports, but once a container is actually running, is there a command to open/map additional ports live?
For example, let's say I have a Docker container that is running sshd. Someone else using the container ssh's in and installs httpd. Is there a way to expose port 80 on the container and map it to port 8080 on the host, so that people can visit the web server running in the container, without restarting it?
You cannot do this via Docker, but you can access the container's un-exposed port from the host machine.
If you have a container with something running on its port 8000, you can run
wget http://container_ip:8000
To get the container's IP address, run the 2 commands:
docker ps
docker inspect container_name | grep IPAddress
Internally, Docker shells out to call iptables when you run an image, so maybe some variation on this will work.
To expose the container's port 8000 on your localhost's port 8001:
iptables -t nat -A DOCKER -p tcp --dport 8001 -j DNAT --to-destination 172.17.0.19:8000
One way you can work this out is to setup another container with the port mapping you want, and compare the output of the iptables-save command (though, I had to remove some of the other options that force traffic to go via the docker proxy).
NOTE: this is subverting docker, so should be done with the awareness that it may well create blue smoke.
OR
Another alternative is to look at the (new? post 0.6.6?) -P option - which will use random host ports, and then wire those up.
OR
With 0.6.5, you could use the LINKs feature to bring up a new container that talks to the existing one, with some additional relaying to that container's -p flags? (I have not used LINKs yet.)
OR
With docker 0.11? you can use docker run --net host .. to attach your container directly to the host's network interfaces (i.e., net is not namespaced) and thus all ports you open in the container are exposed.
Here's what I would do:
Commit the live container.
Run the container again with the new image, with ports open (I'd recommend mounting a shared volume and opening the ssh port as well)
sudo docker ps
sudo docker commit <containerid> <foo/live>
sudo docker run -i -p 22 -p 8000:80 -m /data:/data -t <foo/live> /bin/bash
While you cannot expose a new port of an existing container, you can start a new container in the same Docker network and get it to forward traffic to the original container.
# docker run \
--rm \
-p $PORT:1234 \
verb/socat \
TCP-LISTEN:1234,fork \
TCP-CONNECT:$TARGET_CONTAINER_IP:$TARGET_CONTAINER_PORT
Worked Example
Launch a web-service that listens on port 80, but do not expose its internal port 80 (oops!):
# docker run -ti mkodockx/docker-pastebin # Forgot to expose PORT 80!
Find its Docker network IP:
# docker inspect 63256f72142a | grep IPAddress
"IPAddress": "172.17.0.2",
Launch verb/socat with port 8080 exposed, and get it to forward TCP traffic to that IP's port 80:
# docker run --rm -p 8080:1234 verb/socat TCP-LISTEN:1234,fork TCP-CONNECT:172.17.0.2:80
You can now access pastebin on http://localhost:8080/, and your requests goes to socat:1234 which forwards it to pastebin:80, and the response travels the same path in reverse.
IPtables hacks don't work, at least on Docker 1.4.1.
The best way would be to run another container with the exposed port and relay with socat. This is what I've done to (temporarily) connect to the database with SQLPlus:
docker run -d --name sqlplus --link db:db -p 1521:1521 sqlplus
Dockerfile:
FROM debian:7
RUN apt-get update && \
apt-get -y install socat && \
apt-get clean
USER nobody
CMD socat -dddd TCP-LISTEN:1521,reuseaddr,fork TCP:db:1521
Here's another idea. Use SSH to do the port forwarding; this has the benefit of also working in OS X (and probably Windows) when your Docker host is a VM.
docker exec -it <containterid> ssh -R5432:localhost:5432 <user>#<hostip>
To add to the accepted answer iptables solution, I had to run two more commands on the host to open it to the outside world.
HOST> iptables -t nat -A DOCKER -p tcp --dport 443 -j DNAT --to-destination 172.17.0.2:443
HOST> iptables -t nat -A POSTROUTING -j MASQUERADE -p tcp --source 172.17.0.2 --destination 172.17.0.2 --dport https
HOST> iptables -A DOCKER -j ACCEPT -p tcp --destination 172.17.0.2 --dport https
Note: I was opening port https (443), my docker internal IP was 172.17.0.2
Note 2: These rules and temporrary and will only last until the container is restarted
I had to deal with this same issue and was able to solve it without stopping any of my running containers. This is a solution up-to-date as of February 2016, using Docker 1.9.1. Anyway, this answer is a detailed version of #ricardo-branco's answer, but in more depth for new users.
In my scenario, I wanted to temporarily connect to MySQL running in a container, and since other application containers are linked to it, stopping, reconfiguring, and re-running the database container was a non-starter.
Since I'd like to access the MySQL database externally (from Sequel Pro via SSH tunneling), I'm going to use port 33306 on the host machine. (Not 3306, just in case there is an outer MySQL instance running.)
About an hour of tweaking iptables proved fruitless, even though:
Step by step, here's what I did:
mkdir db-expose-33306
cd db-expose-33306
vim Dockerfile
Edit dockerfile, placing this inside:
# Exposes port 3306 on linked "db" container, to be accessible at host:33306
FROM ubuntu:latest # (Recommended to use the same base as the DB container)
RUN apt-get update && \
apt-get -y install socat && \
apt-get clean
USER nobody
EXPOSE 33306
CMD socat -dddd TCP-LISTEN:33306,reuseaddr,fork TCP:db:3306
Then build the image:
docker build -t your-namespace/db-expose-33306 .
Then run it, linking to your running container. (Use -d instead of -rm to keep it in the background until explicitly stopped and removed. I only want it running temporarily in this case.)
docker run -it --rm --name=db-33306 --link the_live_db_container:db -p 33306:33306 your-namespace/db-expose-33306
You can use SSH to create a tunnel and expose your container in your host.
You can do it in both ways, from container to host and from host to container. But you need a SSH tool like OpenSSH in both (client in one and server in another).
For example, in the container, you can do
$ yum install -y openssh openssh-server.x86_64
service sshd restart
Stopping sshd: [FAILED]
Generating SSH2 RSA host key: [ OK ]
Generating SSH1 RSA host key: [ OK ]
Generating SSH2 DSA host key: [ OK ]
Starting sshd: [ OK ]
$ passwd # You need to set a root password..
You can find the container IP address from this line (in the container):
$ ifconfig eth0 | grep "inet addr" | sed 's/^[^:]*:\([^ ]*\).*/\1/g'
172.17.0.2
Then in the host, you can just do:
sudo ssh -NfL 80:0.0.0.0:80 root#172.17.0.2
Based on Robm's answer I have created a Docker image and a Bash script called portcat.
Using portcat, you can easily map multiple ports to an existing Docker container. An example using the (optional) Bash script:
curl -sL https://raw.githubusercontent.com/archan937/portcat/master/script/install | sudo bash
portcat my-awesome-container 3456 4444:8080
And there you go! Portcat is mapping:
port 3456 to my-awesome-container:3456
port 4444 to my-awesome-container:8080
Please note that the Bash script is optional, the following commands:
ipAddress=$(docker inspect my-awesome-container | grep IPAddress | grep -o '[0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{3\}' | head -n 1)
docker run -p 3456:3456 -p 4444:4444 --name=alpine-portcat -it pmelegend/portcat:latest $ipAddress 3456 4444:8080
I hope portcat will come in handy for you guys. Cheers!
There is a handy HAProxy wrapper.
docker run -it -p LOCALPORT:PROXYPORT --rm --link TARGET_CONTAINER:EZNAME -e "BACKEND_HOST=EZNAME" -e "BACKEND_PORT=PROXYPORT" demandbase/docker-tcp-proxy
This creates an HAProxy to the target container. easy peasy.
Here are some solutions:
https://forums.docker.com/t/how-to-expose-port-on-running-container/3252/12
The solution to mapping port while running the container.
docker run -d --net=host myvnc
that will expose and map the port automatically to your host
In case no answer is working for someone - check if your target container is already running in docker network:
CONTAINER=my-target-container
docker inspect $CONTAINER | grep NetworkMode
"NetworkMode": "my-network-name",
Save it for later in the variable $NET_NAME:
NET_NAME=$(docker inspect --format '{{.HostConfig.NetworkMode}}' $CONTAINER)
If yes, you should run the proxy container in the same network.
Next look up the alias for the container:
docker inspect $CONTAINER | grep -A2 Aliases
"Aliases": [
"my-alias",
"23ea4ea42e34a"
Save it for later in the variable $ALIAS:
ALIAS=$(docker inspect --format '{{index .NetworkSettings.Networks "'$NET_NAME'" "Aliases" 0}}' $CONTAINER)
Now run socat in a container in the network $NET_NAME to bridge to the $ALIASed container's exposed (but not published) port:
docker run \
--detach --name my-new-proxy \
--net $NET_NAME \
--publish 8080:1234 \
alpine/socat TCP-LISTEN:1234,fork TCP-CONNECT:$ALIAS:80
You can use an overlay network like Weave Net, which will assign a unique IP address to each container and implicitly expose all the ports to every container part of the network.
Weave also provides host network integration. It is disabled by default but, if you want to also access the container IP addresses (and all its ports) from the host, you can run simply run weave expose.
Full disclosure: I work at Weaveworks.
It's not possible to do live port mapping but there are multiple ways you can give a Docker container what amounts to a real interface like a virtual machine would have.
Macvlan Interfaces
Docker now includes a Macvlan network driver. This attaches a Docker network to a "real world" interface and allows you to assign that networks addresses directly to the container (like a virtual machines bridged mode).
docker network create \
-d macvlan \
--subnet=172.16.86.0/24 \
--gateway=172.16.86.1 \
-o parent=eth0 pub_net
pipework can also map a real interface into a container or setup a sub interface in older versions of Docker.
Routing IP's
If you have control of the network you can route additional networks to your Docker host for use in the containers.
Then you assign that network to the containers and setup your Docker host to route the packets via the docker network.
Shared host interface
The --net host option allows the host interface to be shared into a container but this is probably not a good setup for running multiple containers on the one host due to the shared nature.
Read Ricardo's response first. This worked for me.
However, there exists a scenario where this won't work if the running container was kicked off using docker-compose. This is because docker-compose (I'm running docker 1.17) creates a new network. The way to address this scenario would be
docker network ls
Then append the following
docker run -d --name sqlplus --link db:db -p 1521:1521 sqlplus --net network_name
docker run -i --expose=22 b5593e60c33b bash
ref: https://forums.docker.com/t/how-to-expose-port-on-running-container/3252/5
this may help you

Resources