quda
Plug Cowboy - Search dynamically for a free port to run the server
I am building a simple http server using Plug.Cowboy (no Phoenix pls!) to serve a json API for a customer. A microservice.
The problem is the customer has a complex environment with multiple services of many sorts, containers, microservices etc. that are serving on various ports in his server. Therefore we were requested to develop the service to look dynamically and launch itself on a free/unused port.
When we build the Elixir app it is requested to declare the port at Plug initialization or it defaults to 4000/4040:
def start(_type, _args) do
children = [
{Plug.Cowboy, scheme: :http, plug: MyApp, port: 1234}
]
...
How can I re-factory this to search the first available unused port in a certain range ?
Thanks in advance,
Q.T.
Marked As Solved
dodo
You could probably use Erlang -- gen_tcp (not tested):
def start(_type, _args) do
children = [
{Plug.Cowboy, scheme: :http, plug: MyApp, port: get_free_port(4000)}
]
...
end
defp get_free_port(start) do
case :gen_tcp.listen(start, [:binary]) do
{:ok, socket} ->
:ok = :gen_tcp.close(socket)
start
{:error, :eaddrinuse} ->
get_free_port(start + 1)
end
end
Also Liked
joey_the_snake
If you put port: 0 it seems to look for an available port and use it. I’m not sure if this is safe to be counted on though. I tried it out because in erlang gen_tcp.listen finds an available port when you set port to 0.
Nicd
It should be safe at least on Linux, see the source: linux/inet_connection_sock.c at 38f80f42147ff658aff218edb0a88c37e58bf44f · torvalds/linux · GitHub
This seems to be a Unix convention of getting a random available port. If you then need to know what port you got, possibly you can dig at the Cowboy socket to gain that information.
hauleth
You cannot limit range, but as other have said, using port 0 will give you random port from ephemeral range (configured by the OS). The problem though is how to later extract that port from within your application (it is not done automatically for you).
However using ephemeral ports for listening with your services is a little bit weird, what exactly you are trying to accomplish?
LostKobrakai
You could just try listing on a port with the actual server, if it doesn’t fail your there. No separation between checking and using.







