I'm not sure if I've misunderstood something here, but it seems like it's only possible to set port mappings by creating a new container from an image. Is there a way to assign a port mapping to an existing Docker container?
This question is related to
docker
port
lxc
linux-containers
If you are not comfortable with Docker depth configuration, iptables would be your friend.
iptables -t nat -A DOCKER -p tcp --dport ${YOURPORT} -j DNAT --to-destination ${CONTAINERIP}:${YOURPORT}
iptables -t nat -A POSTROUTING -j MASQUERADE -p tcp --source ${CONTAINERIP} --destination ${CONTAINERIP} --dport ${YOURPORT}
iptables -A DOCKER -j ACCEPT -p tcp --destination ${CONTAINERIP} --dport ${YOURPORT}
This is just a trick, not a recommended way. This works with my scenario because I could not stop the container.
Editing hostconfig.json seems to not working now. It only ends with that port being exposed but not published to host. Commiting and recreating containers is not the best approach to me. No one mentioned docker network
?
The best solution would be using reversed proxy within the same network
Create a new network if your previous container not in any named ones.
docker network create my_network
Join your existing container to the created network
docker network connect my_network my_existing_container
Start a reversed proxy service(e.g. nginx) publishing the ports you need, joining the same network
docker run -d --name nginx --network my_network -p 9000:9000 nginx
Optionally remove the default.conf in nginx
docker exec nginx rm /etc/nginx/conf.d/default.conf
Create a new nginx config
server
{
listen 9000;
location / {
proxy_pass http://my_existing_container:9000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Copy the config to nginx container.
docker cp ./my_conf.conf nginx:/etc/nginx/conf.d/my_conf.conf
Restart nginx
docker restart nginx
Advantages: To publish new ports, you can safely stop/update/recreate nginx container as you wish without touching the business container. If you need zero down time for nginx, it is possible to add more reversed proxy services joining the same network. Besides, a container can join more than one network.
Edit:
To reverse proxy non-http services, the config file is a bit different. Here is a simple example:
upstream my_service {
server my_existing_container:9000;
}
server {
listen 9000;
proxy_pass my_service;
}
/var/lib/docker/containers/${container_id}
directory and edit hostconfig.json
PortBindings.HostPort
that you want the change.Not sure if you can apply port mapping a running container. You can apply port forwarding while running a container which is different than creating a new container.
$ docker run -p <public_port>:<private_port> -d <image>
will start running container. This tutorial explains port redirection.
If by "existing" you mean "running", then it's not (currently) possible to add a port mapping.
You can, however, dynamically add a new network interface with e.g. Pipework, if you need to expose a service in a running container without stopping/restarting it.
we an use handy tools like ssh to accomplish this easily.
I was using ubuntu host and ubuntu based docker image.
when a new port is needed to be mapped out,
inside the docker run the following command
ssh -R8888:localhost:8888 <username>@172.17.0.1
172.17.0.1 was the ip of the docker interface
(you can get this by running
ifconfig docker0 | grep "inet addr" | cut -f2 -d":" | cut -f1 -d" "
on the host).
here I had local 8888 port mapped back to the hosts 8888. you can change the port as needed.
if you need one more port, you can kill the ssh and add one more line of -R to it with the new port.
I have tested this with netcat.
If you simply want to change the port of the running container, you do:
sudo docker stop NAME
sudo docker run -d -p 81:80 NAME
where as:
"-d" to background / deamon the docker
"-p" enable port mapping
"81" external (exposed) port you use to access with your browser
"80" internal docker container listen port
If you run docker run <NAME>
it will spawn a new image, which most likely isn't what you want.
If you want to change a current image do the following:
docker ps -a
Take the id of your target container and go to:
cd /var/lib/docker/containers/<conainerID><and then some:)>
Stop the container:
docker stop <NAME>
Change the files
vi config.v2.json
"Config": {
....
"ExposedPorts": {
"80/tcp": {},
"8888/tcp": {}
},
....
},
"NetworkSettings": {
....
"Ports": {
"80/tcp": [
{
"HostIp": "",
"HostPort": "80"
}
],
And change file
vi hostconfig.json
"PortBindings": {
"80/tcp": [
{
"HostIp": "",
"HostPort": "80"
}
],
"8888/tcp": [
{
"HostIp": "",
"HostPort": "8888"
}
]
}
Restart your docker and it should work.
For Windows & Mac Users, there is another pretty easy and friendly way to change the mapping port:
download kitematic
go to the settings page of the container, on the ports tab, you can directly modify the published port there.
start the container again
# list all containers
$ docker ps -a
$ docker stop docker101tutorial
# Use grep or rg to get Id of container
$ docker inspect docker101tutorial | grep -i id
"Id": "sha256:fff0a4b22d6f3d2eb8d2748b8a8bbc9967ea87199988acee8e86ac70bce9c3eb",
# run plain ubuntu docker image with shell and change it's namespace to docker host
# https://stackoverflow.com/questions/60408574/how-to-access-var-lib-docker-in-windows-10-docker-desktop/60411313#60411313
# https://forums.docker.com/t/the-location-of-images-in-docker-for-windows/19647/4
$ docker run -it --privileged --pid=host ubuntu nsenter -t 1 -m -u -i sh
# We want to find out the directory of docker101tutorial container. We are looking for:
# `"Image":"sha256:fff0a4b22d6f3d2eb8d2748b8a8bbc9967ea87199988acee8e86ac70bce9c3eb"`
# in /var/lib/docker/containers/*/config.v2.json
$ grep -rl --include=config.v2.json fff0a4b22d /var/lib/docker/containers/
/var/lib/docker/containers/c1eda20b30f058bce9f8ece3b47a21641df5b399770e12ab57416a954d3c8bbf/config.v2.json
# edit it
$ vi /var/lib/docker/containers/c1eda20b30f058bce9f8ece3b47a21641df5b399770e12ab57416a954d3c8bbf/hostconfig.json
i
for insert mode."HostPort":"80"
to "HostPort":"8092"
Escape
and write :wq
. Press Enter
.docker101tutorial
now. Otherwise changes to HostPort
will be reverted.8092
.8092
on host.Based on @holdfenytolvaj answer.
I'm also interested in this problem.
As @Thasmo mentioned, port forwardings can be specified ONLY with docker run
(and docker create
) command.
Other commands, docker start
does not have -p
option and docker port
only displays current forwardings.
To add port forwardings, I always follow these steps,
stop running container
docker stop test01
commit the container
docker commit test01 test02
NOTE: The above, test02
is a new image that I'm constructing from the test01
container.
re-run from the commited image
docker run -p 8080:8080 -td test02
Where the first 8080 is the local port and the second 8080 is the container port.
In Fujimoto Youichi's example test01
is a container, whereas test02
is an image.
Before doing docker run
you can remove the original container and then assign the container the same name again:
$ docker stop container01
$ docker commit container01 image01
$ docker rm container01
$ docker run -d -P --name container01 image01
(Using -P
to expose ports to random ports rather than manually assigning).
Source: Stackoverflow.com