Remove exposed port from docker

Solution 1:

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!

Solution 2:

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.