Trying to find a creative solution to assign an unused host:container port while submitting docker run from a range of possible ports. I am very close to figuring it out and trying to see if below approach works smartly. So far, I have decided to do following:
- docker inspect and find ports already used by running containers .e.g.
$ docker ps -a --format "{{.Ports}}"
0.0.0.0:8780->8080/tcp
0.0.0.0:4022->4022/tcp, 0.0.0.0:5022->5022/tcp
0.0.0.0:4013->4013/tcp, 0.0.0.0:5013->5013/tcp, 0.0.0.0:6013->6013/tcp
- From above I was able to extract last 2 digits(UUID) of all ports ( since I will be mapping the same port )
$ docker ps -a --format "{{.Ports}}" | sed -re 's/^.*->[0-9][0-9]([0-9]+)/tcp.*$/1/'
80
13
- My docker run will have port mapping as below:
-p 40${UUID}:40${UUID}
-p 50${UUID}:50${UUID}
-p 60${UUID}:60${UUID}
- Now I want to generate the UUID (in the range of 00-50) that do not exist in above output so that every time my script runs it assigns an unused port range to the container on the fly.
Is it possible for a bash one-liner to achieve what I am trying to achieve? python approach will also work. If there is any better way to achieve above, Im keen to learn as well. Expected output for UUID below will return 2 digit value between 0-50 but not 13,22,80.
UUID=`docker ps -a --format "{{.Ports}}" | sed -re 's/^.*->[0-9][0-9]([0-9]+)/tcp.*$/1/' | <additional parsing logic>`
Much thanks in advance. Interesting that docker does not have a way to dynamically manage port assignments based on range so have to go this path.
UPDATE: The list of ports on host and container need to configured in the above way due to firewall limitations. On host, only specific range is opened for tcp. While, on container the same ports are assigned to specific conf values. Hence both host/container ports cannot be dynamically assigned without setting on environment.
2
Answers
Docker can pretty much do this on its own, provided you don’t really care about the format of the host port.
The first trick is that the two
docker run -p
port numbers don’t need to match. It’s common for the process inside the container to listen on a fixed port, which might be remapped. Say your process listens on port 4000; then you candocker run -p 4123:4000
to map host port 4123 to container port 4000, without reconfiguring the container process.The second trick is that you don’t actually need two port numbers. If you only provide one port number, it’s the container port, and Docker picks the host port. You need to look up yourself what that port number is, but the
docker ps
recipe you have does that. (There’s also a dedicateddocker port
.)The advantages here are that you’re guaranteed Docker will pick an unused port, and you don’t have to do any manual inspection of what’s running on your host system. In your example you have groups of related ports and you were hoping to publish related 40xx, 50xx, 60xx ports; if Docker picks the ports you’ll probably get sequential arbitrary-looking numbers like 32769, 32770, 32771 that aren’t obviously related to the container ports.
This should produce the expected result :