How do I assign a port mapping to an existing Docker container?
Solution 1
You can change the port mapping by directly editing the hostconfig.json
file at
/var/lib/docker/containers/[hash_of_the_container]/hostconfig.json
or /var/snap/docker/common/var-lib-docker/containers/[hash_of_the_container]/hostconfig.json
, I believe, if You installed Docker as a snap.
You can determine the [hash_of_the_container] via the docker inspect <container_name>
command and the value of the "Id" field is the hash.
- Stop the container (
docker stop <container_name>
). - Stop docker service (per Tacsiazuma's comment)
- Change the file.
- Restart your docker engine (to flush/clear config caches).
- Start the container (
docker start <container_name>
).
So you don't need to create an image with this approach. You can also change the restart flag here.
P.S. You may visit https://docs.docker.com/engine/admin/ to learn how to correctly restart your docker engine as per your host machine. I used sudo systemctl restart docker
to restart my docker engine that is running on Ubuntu 16.04.
Solution 2
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 thetest01
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.
Solution 3
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.
Solution 4
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).
Solution 5
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;
}
thasmo
Updated on July 16, 2022Comments
-
thasmo almost 2 years
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?
-
Choldrim almost 8 yearsUsing iptables may work like this answer Exposing a Port on a Live Docker Container
-
Lance Kind almost 7 yearsI suspect this is by design. Docker is trying to force you to be "repeatable" and the container is a type of "system of record." Anything you do as step that doesn't affect the container would be an easily lost manual step. Said another way: You want your container to represent all the configuration that's necessary to operate. So if you want to open a new port, then you need to create a new container.
-
Edgar Carvalho almost 5 yearsOld question and I'm not answering it, but I would like to say that maybe you and people upovting this question and answers may have completely misunderstood the concept of docker. Docker are for stateless application, that can scale up or down many times. You should never persist something inside the container for a production enviroment that can't be recreated, if you need to persist, map the directories. Docker is not something like a "light vm", maybe what you are looking for is linuxcontainers.org, lxd is based on docker concept but with a "light vm" in mind.
-
Yaffah over 4 yearsjust in case this might help, it is possible to use the "Kitematic" tool to add port mapping to already running containers. This should imply that there must be docker command to do exactly the same thing but with a little googling :) Good luck
-
-
thasmo over 10 yearsYe, so it seems it's only possible to set options like port mapping at container creation.
-
user69715 over 8 yearsWhat if I want to keep the test01 name?
-
Marco almost 8 years@user69715 - as was described in Luca's answer - stackoverflow.com/a/36189165/33204 you can keep the existing of a container by creating an image of it, deleting the current container,
test01
, and then recreate it using the previously saved image. -
Elijah Lynn almost 8 yearsAnyone know if there is an open issue with Docker to allow port specification (--publish) with
docker start
? -
Rakib over 7 yearsPerfect... There was no need to create an image with this approach
-
Admin over 7 yearsFYI this answer isn't entirely correct.
docker run
creates and starts a new container. It's equivalent to doingdocker create
followed bydocker start
. -
Partly Cloudy over 7 yearsThis should be the top answer. Succinct and it addresses OP's question which none of the others do! Sometimes a negative result is a result!
-
Tacsiazuma over 7 yearsWhen docker stops, it seem to overwrite your changes, so 2. stop docker, 3. change file, 4. start docker engine
-
rohitmohta over 7 yearsI have tried the above and it works. For more details see: mybrainimage.wordpress.com/2017/02/05/…
-
Kalpak Gadre about 7 yearsIt's important to stop container, stop docker engine and change both
hostconfig.json
andconfig.v2.json
to make this work. Use link provided by @rohitmohta to see the details. -
Andrew Savinykh about 7 yearsAnd what happens with the volumes in this scenario?
-
Barry almost 7 yearsPlease be aware. you will LOSE all of your data, depending on the application inside.
-
Andreas Presthammer over 6 yearsImportant to remember to restart the docker engine with (service docker restart) after changing the hostconfig.json file, otherwise the file will revert back.
-
Ciprian Tomoiagă over 6 yearsthis is a great answer ! Thank you! If I want to map
DOCKER_PORT
toMACHINE_PORT
, which parts should be changed ? -
TewWe about 6 years@AndrewSavinykh the volumes will not be transferred to the new container. However, you can link them manually:
docker inspect test01
and search for the mounts section, where you will find your volumes, that were mounted. You can then mount them in the run command:docker run -p 8080:8080 -v 401959be5b03e750500a543e858dc021a5b98c96d10c7c595e4b100edca513d0:/data/db -td test02
-
Afshin about 6 yearsIt's amazing and practical, but for enterprise systems this approach seems to be obfuscating. It's much more better to let a single system controls the workflow.
-
Sean C. about 6 years@Afshin Well for enterprise systems or projects, I think this solution is better than recreating(causes down time) or hacking hostconfig.json file(at least not officially introduced). The extra container just exposes your business container's internal port, rather than makeing any changes to it.
-
thegeko about 6 yearsThis did not work for me on Docker version 17.09.0-ce. After I started the container config files got overwritten back to old values.
-
Arnold Zahrneinder almost 6 yearsThis is a terrible solution, I have no idea how it managed to earn 250 upvotes. Maybe those how upvoted didn't know what kind of mess this solution causes. Yes, it's terrible, and it is equal to starting a new container running on a different port.
-
VeganHunter almost 6 yearsI tried this approach. Kinematic applied the port mappings, indeed. Howeverto apply them, it re-created my container from the original image. So if you are afraid of loosing the changes made in the container itself, do not use this method.
-
dtbaker almost 6 yearsYes
service docker stop
before making any changes to thehostconfig.json
file. It kept getting overwritten until I stopped everything first. -
John almost 6 yearsthis should be the accepted answer. Damn, so docker is caching the config and overwrites it through that cache..
-
nommer almost 6 yearsworked for me, just one thing if using docker app on mac, follow instructions here to get to /var/lib/docker/containers folder: stackoverflow.com/a/41226917/2048266, basically run
screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty
Once you get the tty running you can navigate to /var/lib/docker -
crockeea over 5 years@Arrrr Perhaps you'd like to leave a better answer? I'm sure we'd all appreciate if you told us the much better way to do this.
-
yurenchen over 5 yearsrestart docker service in host system @thegeko
-
Johnny Willer over 5 years@Arrrr This answer is useful when you have a heavy container that takes a long time to get in that state, then you realize that you need to open some ports....
-
Steve Townsend over 5 years@Arrrr - this may indeed not be a general 'best practice'. As a tactical work round, for a persistent Linux container on Windows with clashing ports, which is what I'm using it for, it's pretty much the only way to move my work forward.
-
Monkiki over 5 yearsGreat! The workflow should be: - Stop containers - Stop Docker - Modify hostconfig.json - Start Docker - Start container I didn't have to modify the config.v2.json file.
-
Vijay about 5 yearsfor windows, can any one please share me the location of conatiners folder.?
-
Brooks DuBois about 5 yearsAwesome approach. I needed to configure nginx differently for my container to work behind a proxy, but seems like the correct way to do things. Works for blue-green deployment too.
-
user3335999 almost 5 yearsThis is NOT a solution. You will lose the contents of the container.
-
2b77bee6-5445-4c77-b1eb-4df3e5 almost 5 yearsI preferred this, I get that it doesn't answer the question, and it creates a new container. But at least it works, and this SO result showed up during my search. +1
-
Vikash almost 5 years@user3335999 how ?
-
Dee over 4 yearsthis works! tks! 1.stop container, 2.change files, 3.restart docker, 4.start back container
-
Frediano Ziglio about 4 yearsif the port was not exported from the machine you have also to add it to the
config.v2.json
file, the syntax is like"ExposedPorts":{"8080/tcp":{}}
, usually afterAttachStderr
-
N-ate about 4 yearsDocker Desktop no longer has these config files.
-
anthony almost 4 yearsNote docker wil not know about this manual addition. SO entries are not removed when you later restart the service with the docker exposing the ports properly. So when anything changes, be sure to check iptables very carefully. Especially look for duplicate entries!
-
ATOMP almost 4 years@user3335999 the files were persisted for me when I tried this -- what exactly are you referring to?
-
CivFan almost 4 years@Barry - in what case? This commits the container to an image, which saves all your data in the container to an image. Any volumes or mounts the original container used will of course still be there, since they're separate from containers and images. So I don't follow.
-
Arslan Munir almost 4 yearsI tried this. and it removes all my databases successfully :/
-
Mohsen Abasi almost 4 years@Vijay Why not use linux when docker is better working on it?
-
rofrol over 3 yearsId of the container is different than directory name. Look at stackoverflow.com/a/63455911/588759
-
verystrongjoe over 3 yearsCan I commit new docker image not stopping existing image?
-
James Mchugh over 3 yearsOn a separate note, this is also a great way to add mounts to an existing container.
-
RicarHincapie over 3 yearsWorked perfectly for me. Appreciate you went straight to the files examples. Couldn't been able to do it without you.
-
Oswaldo Zapata over 3 yearsI did this with jenkins and I had to redo everything, ahaha this only ports the configuration of the container but not the content, good thing I did not delete my container yet ahaha
-
NiharGht about 3 yearsThis worked, I was trying to create a postgres service on WIndows 10, I had created the container with -p port publish, but for some strange reason it did not publish the port 5432. This worked. Any idea why this is happening? FYI - in the host file I added this to work "PortBindings":{"5432/tcp":[{"HostIp":"","HostPort":"5432"}]
-
Sergei Vavilov about 3 yearsData can be stored on a volume.. Try inspecting the container for volumes
docker inspect container01
before removing, keep the volume name and mount it when running a new container -
Muhammad Tariq about 3 yearsPlease learn how to properly format the post. Please check how to use markdown in SO for proper formatting.
-
pmg7670 about 3 yearsIf you mean that the answer must have a code solution, then I don't agree. In this case the right answer is the right design pattern
-
Muhammad Tariq about 3 yearsDid I say "use code" or "code solution" anywhere? If you read carefully, I am suggesting you to
Properly Format
your post using markdown. Here is the link to help you understand how to use markdown in SO stackoverflow.com/editing-help -
Vadzim almost 3 years@Vijay, docker files location on Windows under WSL2: stackoverflow.com/questions/65546108/…
-
Vadzim almost 3 yearsDocker files location on Windows under WSL2: stackoverflow.com/questions/65546108/…
-
Hlex almost 3 yearshe means 'existing Docker container'
-
Yunnosch almost 3 yearsWhile this code may solve the question, including an explanation of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations and give an indication of what limitations and assumptions apply.
-
kreigan almost 3 yearsFor some reason, grep on the latest Ubuntu does not recognize
--include
option but it's possible to use the find command to do the same:find /var/lib/docker/containers/ -name config.v2.json -exec grep -H f7828c0aa {} \;
-
Mohammed Nosirat over 2 yearsI think that the answer is missing the syntax of port forwarding, in hostconfig.json add configuration as these
"PortBindings": {"3306/tcp": [{"HostIp": "","HostPort": "3306"}]},
-
Benyamin Jafari - aGn over 2 yearsI could add a new port binding but I couldn't change an existing bounded port!
-
Akif over 2 yearsGreat answer. Don't forget to make changes in the host file of the computer accessing the docker from the local network for the needed application.
-
Konstantin Pelepelin over 2 yearsNice approach! I think using TCP proxy like
socat
could be even easier. -
cincodenada over 2 years@CivFan "Any volumes or mounts the original container used will of course still be there, since they're separate from containers and images." - You're very close to following: yes, data in a volume or mount will be fine. But if data is not in a volume or mount, it will be lost - and data is not always in volumes or mounts, thus data will sometimes be lost.
-
CivFan over 2 years@cincodenada No, any data in
container01
not in a volume or mount or the original image, will be saved inimage01
. Thus the confusion. I guess the data may be lost, in the general sense of losing your keys somewhere in a room, but not lost forever. You just have to know a bit about docker to find it. -
Winand about 2 yearsI like
reproxy
because it's easier to configure:docker create -p EXTERNAL_PORT:8080 --name reproxy_container --network NETWORK_NAME umputun/reproxy --static.enabled --static.rule=*,^/(.*),http://ORIGINAL_CONTAINER:INTERNAL_PORT/$1
-
quetzalcoatl about 2 years@Winand looks nice, and quite clear. umputun/reproxy github site is also quite informative. but it seems it works only for http(s), while
nginx
from the answer covers a bit more cases. nevertheless, reproxy seems a nice addition to the toolset