Remove exposed port from docker

7

4

I'm creating a container from an image that had a published port (3000). I want to publish a new port (3030) and only this one, if I use the --publish 3030:3030 I end up with both ports published (3000 and 3030).

Is it possible to somehow unpublish a port from a running container or do I have to start my image from scratch?

Olivier

Posted 2014-08-27T15:39:30.450

Reputation: 1 179

Answers

9

The clean way is to create a new image: usually, you always want your docker container and images to be reproducible. If you manually change something deviating from your image, you rob yourself of that behaviour (something someone else managing the infrastructure you're working in would expect.)

There is currently no clean way to do this through the Docker API, but make sure to check if there's a new development in their documentation.

Specifically, there's a bug report (Changeable/Editable volumes / ports on github) you may want to comment on / subscribe to if this interests you.

Right now, directly managing the DNAT with iptables is the way to go. It's how docker does it anyway, but please be aware that beyond your desired effect I'm not sure if there are any side-effects to it (e.g. docker trying to re-add those rules etc.)

First, you'll have to look up the forwarded port in the following list:

iptables -t nat --line-numbers --numeric --list

which produces an output like this:

Chain PREROUTING (policy ACCEPT)
num  target     prot opt source               destination
1    DOCKER     all  --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination
1    DOCKER     all  --  0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
num  target     prot opt source               destination
1    MASQUERADE  all  --  172.17.0.0/16        0.0.0.0/0

Chain DOCKER (2 references)
num  target     prot opt source               destination
1    DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8080 to:172.17.1.1:80
2    DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8081 to:172.17.1.2:80
3    DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8082 to:172.17.1.3:80

then, you may delete the matching rule(s) by using

iptables -t nat -D DOCKER $num
, e.g. to replace the rule that matches port 8081 you have to use
iptables -t nat -D DOCKER 2

Enjoy!

deucalion

Posted 2014-08-27T15:39:30.450

Reputation: 455

1

docker create -p 127.0.0.1:0:3000 will expose port 3000 to random host port bound to localhost interface only. Not the best solution but ensures port won't be accessible from network.

Sergey Alaev

Posted 2014-08-27T15:39:30.450

Reputation: 111

0

I had started a little script to remove registered volumes from a docker image. It uses a workaround by using "docker save" to a tarball with layers, editing the metadata, and "docker load" back including the history. Adding the option to remove exposed ports was just another trick that the script can do.

Have a look at docker-copyedit - it can help if that unexposing ports would occur regularly.

Guido U. Draheim

Posted 2014-08-27T15:39:30.450

Reputation: 101