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!