How do I assign a port mapping to an existing Docker container?

DockerPortLxcLinux Containers

Docker Problem Overview


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?

Docker Solutions


Solution 1 - Docker

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,

  1. stop running container

     docker stop test01
    
  2. commit the container

     docker commit test01 test02
    

NOTE: The above, test02 is a new image that I'm constructing from the test01 container.

  1. 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 2 - Docker

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.

  1. Stop the container (docker stop <container_name>).
  2. Stop docker service (per Tacsiazuma's comment)
  3. Change the file.
  4. Restart your docker engine (to flush/clear config caches).
  5. 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 3 - Docker

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 - Docker

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 - Docker

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

  1. Create a new network if your previous container not in any named ones.

    docker network create my_network

  2. Join your existing container to the created network

    docker network connect my_network my_existing_container

  3. 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

  4. 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

  1. 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;
}

Solution 6 - Docker

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.

Solution 7 - Docker

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.

Solution 8 - Docker

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.

Solution 9 - Docker

To change HostPort of a container on Docker Desktop (on Windows 10 / MacOS)

# list all containers
$ docker ps -a
$ docker stop docker101tutorial 
# Use grep 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
$ find /var/lib/docker/containers/ -name config.v2.json -exec grep -H fff0a4b22d {} \;
/var/lib/docker/containers/c1eda20b30f058bce9f8ece3b47a21641df5b399770e12ab57416a954d3c8bbf/config.v2.json
# edit it
$ vi /var/lib/docker/containers/c1eda20b30f058bce9f8ece3b47a21641df5b399770e12ab57416a954d3c8bbf/hostconfig.json
  • Press i for insert mode.
  • Change "HostPort":"80" to "HostPort":"8092"
  • Press Escape and write :wq. Press Enter.
  • Do not start/stop docker101tutorial now. Otherwise changes to HostPort will be reverted.
  • Right click Docker Desktop tray icon and click Restart.
  • In Docker Desktop's list of containers, look at your container. Displayed port should change to 8092.
  • Start your container. Now it will be mapped to port 8092 on host.

Based on @holdfenytolvaj answer.

Solution 10 - Docker

we an use handy tools like ssh to accomplish this easily.

I was using ubuntu host and ubuntu based docker image.

  1. Inside docker have openssh-client installed.
  2. Outside docker (host) have openssh-server server installed.

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.

Solution 11 - Docker

  1. Stop the docker engine and that container.
  2. Go to /var/lib/docker/containers/${container_id} directory and edit hostconfig.json
  3. Edit PortBindings.HostPort that you want the change.
  4. Start docker engine and container.

Solution 12 - Docker

I am developing a dockerizer go package for deploying batch processing apps in docker containers. My package includes a MessageBroker component that has 3 ports to publish: jobAgentPort, backendPort, frontendPort.

I'll cut a long story short by suggesting that it's better to design an endpointProvider component that is embedded into your server/proxy/broker.

That is, the container deployment is at least a 2 step process.

  1. the endpointProvider component is created and cached in the related package by jobId or similar key.
  2. the server/proxy/broker is built into a binary where your code accepts an endpointConfig component that is output by the endpointProvider.

eg the server/proxy/broker constructor has a signature: NewMessageBroker(epc *EndpointConfig) *MessageBroker. Then, using the docker-client api, a container image is created and finally the container is started (docker run) and ports are published using the endpointConfig that exposes the port values.

Solution 13 - Docker

For Windows & Mac Users, there is another pretty easy and friendly way to change the mapping port:

> 1. download kitematic > > 2. go to the settings page of the container, on the ports tab, you can directly modify the published port there. > > 3. start the container again

Solution 14 - Docker

"docker run -p 8761:8761 --name ."

Solution 15 - Docker

> How do I assign a port mapping to an existing Docker container ?

It's very Simple. There is two thing one is local server PORT like 800,8080 etc. on your machine and the second one is your container PORT which you want to map. Docker Port mapping

 docker run -p 8080:8080 <Image ID> 

To get Image Id you can use

docker ps

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionthasmoView Question on Stackoverflow
Solution 1 - DockerFujimoto YouichiView Answer on Stackoverflow
Solution 2 - DockerholdfenytolvajView Answer on Stackoverflow
Solution 3 - DockerjpetazzoView Answer on Stackoverflow
Solution 4 - DockerLucaView Answer on Stackoverflow
Solution 5 - DockerSean C.View Answer on Stackoverflow
Solution 6 - DockerMansur Ul HasanView Answer on Stackoverflow
Solution 7 - Dockerdocker-noobView Answer on Stackoverflow
Solution 8 - DockerrajalokanView Answer on Stackoverflow
Solution 9 - DockerrofrolView Answer on Stackoverflow
Solution 10 - DockermelchiView Answer on Stackoverflow
Solution 11 - DockerezileliView Answer on Stackoverflow
Solution 12 - Dockerpmg7670View Answer on Stackoverflow
Solution 13 - DockerjohnView Answer on Stackoverflow
Solution 14 - DockerNageswara RaoView Answer on Stackoverflow
Solution 15 - DockerSaurabh kumarView Answer on Stackoverflow