How to expose port on live containers?


As DevOps, we often make quite a lot of mistakes and one of the most oversight mistakes we generally do is forget to expose a port for the container.

When you realize that you have not exposed any port for the container then you start looking for ways to change the port mapping of a live container or in other words, we can say Is there a way to expose a port on a live running container.

Ideally, it is not possible to expose the port on live containers. As a general docker recommendation what you should do instead is create a new docker image then run the docker image along with exposing for the port mapping.

Well what if you can not create a new Docker Image and you have to rely on the existing docker image which you are running without any exposed port?

There are few ways by which you can expose the port on a live running container -

  1. By updating the desired port entry into config.v2.json and hostconfig.json
  2. Create a new container using the existing container image and then expose the port
  3. Using Docker network - Reversed proxy within the same network
  4. On docker destop(Window 10/MacOS)


1. By updating the desired port entry into config.v2.json and hostconfig.json

Lets us consider I want to expose port 1313 on my live running container.

As a first step what you need to do is docker inspect

1docker inspect <your_container_image_name> 

The above command will spit out all the configurations of the running docker image. You have to carefully look for the Ports and HostPort configuration.

I have not exposed any port then your configuration should look like this -

1"Ports": {
2 "80/tcp": [ 
3{
4 "HostIp": "0.0.0.0",
5 "HostPort": "80"
6 }
7]
8 }, 

The above configuration only tells you that expose port 80 of docker container to port 80 of my docker host machine.



1.1 Edit config.v2.json and update port details

Under the path /var/lib/docker/containers/ you should find a file named config.v2.json.

You have to update the config.v2.json and add the desired port which you want to expose -

Open the config.v2.json in vi editor

1vi /var/lib/docker/containers/config.v2.json 

Update the port details -

 1...
 2{
 3"Config": {
 4....
 5"ExposedPorts": {
 6"80/tcp": {},
 7"1313/tcp": {}
 8},
 9....
10},
11"NetworkSettings": {
12....
13"Ports": {
14 "80/tcp": [
15 {
16 "HostIp": "",
17 "HostPort": "80"
18 }
19 ],
20 "1313/tcp": [
21 {
22 "HostIp": "",
23 "HostPort": "1313"
24 }
25 ]
26 },
27....
28}  

(Note - Since the docker configuration is too long so I have only taken the necessary code snippet which you need to update)



1.2 Update the PortBindings inside hostconfig.json

There is one more file named hostconfig.json which you need to edit and inside that file, you should add an entry for PortBinding

Open the hostconfig.json in vi mode for editing

1vi /var/lib/docker/containers//hostconfig.json  

Add the following PortBinding entry -

 1{
 2....
 3 "PortBindings": {
 4 "80/tcp": [
 5 {
 6 "HostIp": "",
 7 "HostPort": "80"
 8 }
 9 ],
10 "1313/tcp": [
11 {
12 "HostIp": "",
13 "HostPort": "1313"
14 }
15 ]
16 },
17.....
18}

1.3 Restart your docker engine

After updating the config.v2.json and hostconfig.json you should restart your docker engine.

Be watchful about any error, your docker engine should start without any errors.

Once after successful restart, you can verify the ports by running the docker ps command.



2. Create a new container using the existing container image and then expose the port

The other way around is to create a new docker image from the existing live docker image and expose the ports on the newly created docker image.

Here is the command sequence which you should follow -

  1. Stop live docker image
1docker stop existing_old_docker_image
  1. Commit and new container using the existing live docker image
1docker commit existing_old_docker_image new_docker_image 

(*Note - In the above docker commit command we are trying to create a new_docker_image from existing docker image .i.e. existing_old_docker_image )

  1. After creating new_docker_image you can use -p flap to expose the port
1docker run -p 1313:1313 -td new_docker_image 


3. Using Docker network - Reversed proxy within the same network

If the above Step-1 and Step-2 do not work for you. Then I would recommend you to look for Docker Network which can help you to create a reversed proxy within the same network.

Here are the steps -

  1. Create your docker network
1docker network create new_network 
  1. Add your existing existing_old_docker_image to the newly created network new_network
1docker network connect new_network existing_old_docker_image
  1. Start the reversed proxy services in the same network
1docker run -d --name nginx --network new_network -p 1313:1313 nginx 
  1. Update haproxy.cfg or create a new my_docker_nginx.conf
 1server
 2{
 3    listen 9000;
 4
 5    location / {
 6        proxy_pass http://new_docker_image:1313;
 7        proxy_http_version 1.1;
 8        proxy_set_header Upgrade $http_upgrade;
 9        proxy_set_header Connection 'upgrade';
10        proxy_set_header Host $host;
11        proxy_cache_bypass $http_upgrade;
12    }
13} 
  1. If you have created a new my_docker_nginx.conf then you must copy the new conf to nginx:/etc/nginx/conf.d/
1docker cp ./my_docker_nginx.conf nginx:/etc/nginx/conf.d/my_docker_nginx.conf
  1. Restart docker nginx
1docker restart nginx  

At first, creating nginx services sounds very complex but it can certainly benefit you if you can afford downtime in your production environment. So with reversed proxy, you can add more containers into the container network with zero downtime.

4. On docker desktop(Window 10/macOS)

Well, this step is specifically for Windows 10 and macOS users using Docker Desktop.

Here are the steps for changing the HostPort -

  1. View and list all the containers -
1docker ps -a 
  1. Stop your existing container
1docker stop existing_old_docker_image  
  1. Get the docker container id of your existing_old_docker_image
1docker inspect existing_old_docker_image | grep -i id 
  1. Spin up plain ubuntu docker image with an update it's the namespace to the docker host
1docker run -it --privileged --pid=host ubuntu nsenter -t 1 -m -u -i sh 
  1. Locate/find config.v2.json using container id
1find /var/lib/docker/containers/ -name config.v2.json -exec grep -H fsdkfl384j{} \; 

The above command should return you a complete path of config.v2.json -

1/var/lib/docker/containers/kdi30923o0fudh38923hrp9093rj88083/config.v2.json 
  1. Edit hostconfig.json

In the previous step, we found the path of config.v2.json at the same path you should find hostconfig.json also.

Open hostconfig.json in edit mode

1vi /var/lib/docker/containers/kdi30923o0fudh38923hrp9093rj88083/hostconfig.json 
  1. Update HostPort

You should update the HostPort to desired port .i.e. - 1313

  1. Restart your Docker desktop and now it is being mapped to new port 1313

References -

  1. Stackoverflow - How do I assign a port mapping to an existing Docker container?

Posts in this Series