How can I see what port a phoenix app in production is actually trying to use?

I am trying to use deliver to start a phoenix app in production on port 4000

I deploy and start the app with:

mix edeliver start production

Ping seems to be able to contact the server–I get a pong response with:

mix edeliver ping production

But if I ssh to the production host and try to load a page with curl I get a connection refused:

curl localhost:4000

Is there any way to check what port Phoenix/Elixir is trying to use in production?
I checked these logs:
/var/log/erlang.log.1
/var/log/run_erl.log

I see an error in erlang.log.1–but no explicit entry that indicates what port it thinks it is using:

…driver #Port<0.2646> failed: fd=0…

Is there a verbose or debug option that would log or display info about what port the app is actually trying to use?

If I ssh into the production host and start the server manually is there a way to find out what port it is trying to bind to?

There should be something like this among the first lines of erlang.log.1

16:48:52.820 [info] Running MyApp.Web.Endpoint with Cowboy using http://0.0.0.0:8080

in case of a successful start.

In the case of an unsuccessful start is there a way to see what port the phoenix app is trying to bind to?

It will try to bind to the port which is specified in your configs or 4000 for http [0] and 4040 for https [1], which I think are plug’s defaults. I wouldn’t expect it to try to bind to anything else, but who knows.

[0] https://github.com/elixir-lang/plug/blob/master/lib/plug/adapters/cowboy.ex#L162
[1] https://github.com/elixir-lang/plug/blob/master/lib/plug/adapters/cowboy.ex#L167

I am trying to debug the server. I believe that I have specified port 4000 in the configs. The server starts, but does not accept connections on port 4000. So in trying to debug this, one thought is that the port specification in the config is not correct. I was hoping to find a debug or verbose option that would show what port the server is attempting to bind to, so that I could verify that it is, indeed, port 4000. For example if the debug info told me that the server was trying to bind to a different port, then that would tell me that I have a problem with my port config.
Does this thought process make sense? Does anyone have a different approach to suggest?

Yes. Does the app start? Can you connect to its remote_console like

$ bin/<name> remote_console

If yes, then you might get the state of either cowboy or plug with :sys.get_state and find out what ports they think they are using.

Also, if there is no

16:48:52.820 [info] Running MyApp.Web.Endpoint with Cowboy using http://0.0.0.0:8080

in erlang.log.1, then cowboy probably wasn’t started.

have you uncommented the config :phoenix, :serve_endpoints, true in your production config?

3 Likes

@idi527: Yes. I have verified that if I start the app, I can get a remote console.
How can I use the remote console to get info that would help me figure out what is going on?

Try typing :sys.get_state MyApp.Web.Endpoint.Server into the remote_console. There should be port info somewhere in the returned tuple. For me it was this

iex(myapp@127.0.0.1)1> :sys.get_state MyApp.Web.Endpoint.Server
{:state, {:local, MyApp.Web.Endpoint.Server}, :one_for_one,
 [{:child, #PID<0.1640.0>, {:ranch_listener_sup, MyApp.Web.Endpoint.HTTP},
   {Phoenix.Endpoint.CowboyHandler, :start_link,
    [:http, MyApp.Web.Endpoint,
     {:ranch_listener_sup, :start_link,
      [MyApp.Web.Endpoint.HTTP, 100, :ranch_tcp,
       [max_connections: 16384, port: 8080], :cowboy_protocol, # <-- here it is
       [env: [dispatch: [{:_, [],
           [{["user", "websocket"], [], Phoenix.Endpoint.CowboyWebSocket,
             {Phoenix.Transports.WebSocket,
              {MyApp.Web.Endpoint, MyApp.Web.UserSocket, :websocket}}},
            {:_, [], Plug.Adapters.Cowboy.Handler,
             {MyApp.Web.Endpoint, []}}]}]]]]}]}, :permanent, :infinity,
   :supervisor, [:ranch_listener_sup]}], :undefined, 3, 5, [], 0,
 Phoenix.Endpoint.Handler, {:web, MyApp.Web.Endpoint}}

but replace MyApp.Web in MyApp.Web.Endpoint.Server with the name of your app.

3 Likes

Thanks @manukall and @idi527 you helped me resolve my issue.
@manukall: you were right, I had not un-commented the config :phoenix, :serve_endpoints, true in my prod.exs config file.
After fixing that, re-building, re-deploying and re-starting, then I was able to use the remote_console as @idi527 suggested (using the appName.Endpoint from my prod.exs file, appending .Server to the end of that then issuing this command on the console::sys.get_state Myapp.Endpoint.Server
The result verified the successful operation:

 {:state, {:local, Myapp.Endpoint.Server}, :one_for_one,
  [{:child, #PID<0.1338.0>, {:ranch_listener_sup, Myapp.Endpoint.HTTP},
    {Phoenix.Endpoint.CowboyHandler, :start_link,
     [:http, Myapp.Endpoint,
      {:ranch_listener_sup, :start_link,
       [Myapp.Endpoint.HTTP, 100, :ranch_tcp,
        [max_connections: 16384, port: 4000], :cowboy_protocol,
        [env: [dispatch: [{:_, [],
            [{["socket", "websocket"], [], Phoenix.Endpoint.CowboyWebSocket,
              {Phoenix.Transports.WebSocket,
               {Myapp.Endpoint, Myapp.UserSocket, :websocket}}},
             {:_, [], Plug.Adapters.Cowboy.Handler,
              {Myapp.Endpoint, []}}]}]]]]}]}, :permanent, :infinity, :supervisor,
    [:ranch_listener_sup]}], :undefined, 3, 5, [], 0, Phoenix.Endpoint.Server,
  {:myapp, Myapp.Endpoint}}
2 Likes

Just got that horrible message liked … Just in case, the easiest way to learn the port is

:ranch.get_port(YourAppWeb.Endpoint.HTTP) # or HTTPS
1 Like