SOLUTION
Answering my own question if anyone else comes across this:
(Quoting and revising a bit from here):
Opening ports is only needed when you want to Listen for the requests not sending. By default Docker provides the necessary network namespace for your container to communicate to the host or outside world.
So, you could it in one of two ways:
1] Use --net=host in your docker run and send requests to the localhost port. In this case your containerized app is effectively sharing the host’s network stack.
2] Talk to the container network gateway (which is usually 172.17.0.1) or your host’s hostname from your container. Then you are able to send the datagrams to your server program running on your host.
In my case, I went for option 2 where:
My containerized program acts as a UDP data sender, writing its data to 172.17.01:8888 (written in C).
Back on the host, I have a simple python program binding to 172.17.01:8888, acting as the data receiver:
import socket
host = "172.17.0.1"
port = 8888
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM | socket.SO_REUSEADDR)
s.bind((host, port))
print "waiting on port:", port
while 1:
data, addr = s.recvfrom(1024)
print data
Importantly, neither the Dockerfile (via EXPOSE command) nor the docker run command (via -p option) refer to this UDP port at all.