How to change the listening port of a Docker container without restarting.

Recently I came up with the following problem: “How to change the listening port of a docker container without restarting the container.” I…

How to change the listening port of a Docker container without restarting.
Photo by Dina Lydia on Unsplash

Recently I came up with the following problem: “How to change the listening port of a docker container without restarting the container.” I could not find a docker-native solution, but still, there is a straightforward solution! using Nginx and its capability to proxy ports, let’s see how.

Create a container listening to a port.

I created the following MySQL container listening to port 3306 of the host.

$ docker run --rm -v mysqldata:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=test -p 3306:3306 mysql

Create the Nginx tcp reverse proxy configuration.

Then installed Nginx to the host and created the following config at /etc/nginx/nginx.conf

load_module /usr/lib/nginx/modules/ngx_stream_module.so; 
events {} 
stream { 
  server { 
    listen 6000; 
    proxy_pass 127.0.0.1:3306; 
  } 
}

The server directive asks Nginx to open a TCP listener on port 6000 of the host, and the proxy_pass asks Nginx to redirect all traffic from 6000 to port 3306 of the host, the port that the container is listening to.

Test NGINX configuration.

After creating or modifying an nginx configuration is highly recommended to test the configuration for errors before starting nginx. To do this, enter the following, if everything is ok should return success messages.

$ sudo nginx -t 
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok 
nginx: configuration file /etc/nginx/nginx.conf test is successful

Try to connect to the proxy port.

Now we need to check if our MySQL container is listening on the configured port. To do this for MySQL I will try to connect with the CLI client tool.

If everything goes well, it should connect and pop a MySQL prompt.

$ mysql --user=root --password=test  --port=6000 --protocol=tcp --host=localhost 
mysql: [Warning] Using a password on the command line interface can be insecure. 
Welcome to the MySQL monitor.  Commands end with ; or \g. 
Your MySQL connection id is 9 
Server version: 8.0.32 MySQL Community Server - GPL 
 
Copyright (c) 2000, 2023, Oracle and/or its affiliates. 
 
Oracle is a registered trademark of Oracle Corporation and/or its 
affiliates. Other names may be trademarks of their respective 
owners. 
 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. 
 
mysql>

Change NGINX configuration and reload.

Let’s try to change the listening port. I have set the port to 7000

load_module /usr/lib/nginx/modules/ngx_stream_module.so; 
events {} 
stream { 
  server { 
    listen 7000; 
    proxy_pass 127.0.0.1:3306; 
  } 
}

I am verifying that the configuration is ok.

$ sudo nginx -t 
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok 
nginx: configuration file /etc/nginx/nginx.conf test is successful

And reload the configuration

$ sudo nginx -s reload

Now the Nginx should listen on port 7000 and proxy the traffic to port 3306 of the host. We can also verify the ports that nginx listens to using the ss command

$ sudo ss -tlnp | grep -i nginx 
State   Recv-Q  Send-Q   Local Address:Port   Peer Address:Port Process 
LISTEN  0       511            0.0.0.0:7000        0.0.0.0:*     users:(("nginx",pid=340,fd=8),("nginx",pid=324,fd=8))

And the final test that accepts connections on the new port

$ mysql --user=root --password=test  --port=7000 --protocol=tcp --host=localhost 
mysql: [Warning] Using a password on the command line interface can be insecure. 
Welcome to the MySQL monitor.  Commands end with ; or \g. 
Your MySQL connection id is 10 
Server version: 8.0.32 MySQL Community Server - GPL 
 
Copyright (c) 2000, 2023, Oracle and/or its affiliates. 
 
Oracle is a registered trademark of Oracle Corporation and/or its 
affiliates. Other names may be trademarks of their respective 
owners. 
 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. 
 
mysql>

Why should you use “reload” instead of “restart”

The reload signal changes the configuration of nginx but does not destroy the established connections, which could be a requirement in your business logic!

Conclusion.

Nginx is a very flexible and versatile tool! can be used for many occasions apart from an HTTP server! I hope you enjoyed this article!

Join Medium with my referral link - Konstantinos Patronas
As a Medium member, a portion of your membership fee goes to writers you read, and you get full access to every story…