I am trying to start two instances of Puma server (one API and another WebApp) (through hanami gem based application) on my development machine but unable to start the server for WebApp successfully. API server starts normally but WebApp server shows error Address already in use - bind(2) for "127.0.0.1" port 9293
.
Please find below the server startup logs.
API App Logs
jignesh@jignesh-Latitude-7290:~/hanami_projects/my_api_app$ bundle exec hanami server --port=2400
13:59:36 - INFO - Using Guardfile at /......./my_api_app/Guardfile.
13:59:36 - INFO - Puma starting on port 2400 in development environment.
13:59:36 - INFO - Guard is now watching at '/......./my_api_app'
[15170] Puma starting in cluster mode...
[15170] * Puma version: 6.2.1 (ruby 3.1.2-p20) ("Speaking of Now")
[15170] * Min threads: 5
[15170] * Max threads: 5
[15170] * Environment: development
[15170] * Master PID: 15170
[15170] * Workers: 2
[15170] * Restarts: (✔) hot (✖) phased
[15170] * Preloading application
[15170] * Listening on http://0.0.0.0:2400
[15170] Use Ctrl-C to stop
[15170] * Starting control server on http://127.0.0.1:9293
[15170] * Starting control server on http://[::1]:9293
[15170] - Worker 0 (PID: 15177) booted in 0.0s, phase: 0
[15170] - Worker 1 (PID: 15179) booted in 0.0s, phase: 0
[15170] ! Terminating timed out worker (worker failed to check in within 60 seconds): 15177
[15170] - Worker 0 (PID: 25100) booted in 0.0s, phase: 0
WebApp Logs
jignesh@jignesh-Latitude-7290:~/hanami_projects/my_web_app$ bundle exec hanami server
15:32:31 - INFO - Using Guardfile at /......./my_web_app/Guardfile.
15:32:32 - INFO - Puma starting on port 2300 in development environment.
15:32:32 - INFO - Guard is now watching at '/......./my_web_app'
[25763] Puma starting in cluster mode...
[25763] * Puma version: 6.2.2 (ruby 3.1.2-p20) ("Speaking of Now")
[25763] * Min threads: 5
[25763] * Max threads: 5
[25763] * Environment: development
[25763] * Master PID: 25763
[25763] * Workers: 2
[25763] * Restarts: (✔) hot (✖) phased
[25763] * Preloading application
[25763] * Listening on http://127.0.0.1:2300
[25763] Use Ctrl-C to stop
/home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:335:in `initialize': Address already in use - bind(2) for "127.0.0.1" port 9293 (Errno::EADDRINUSE)
from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:335:in `new'
from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:335:in `add_tcp_listener'
from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:329:in `block in add_tcp_listener'
from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:328:in `each'
from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:328:in `add_tcp_listener'
from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:164:in `block in parse'
from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:147:in `each'
from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:147:in `parse'
from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/runner.rb:78:in `start_control'
from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/cluster.rb:410:in `run'
from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/launcher.rb:194:in `run'
from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/cli.rb:75:in `run'
from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/bin/puma:10:in `<top (required)>'
from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/bin/puma:25:in `load'
from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/bin/puma:25:in `<main>'
from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/bin/ruby_executable_hooks:22:in `eval'
from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/bin/ruby_executable_hooks:22:in `<main>'
Following is the Puma config files app/config/puma.rb
. In both the application the configuration is identical.
# frozen_string_literal: true
max_threads_count = ENV.fetch("HANAMI_MAX_THREADS", 5)
min_threads_count = ENV.fetch("HANAMI_MIN_THREADS") { max_threads_count }
threads min_threads_count, max_threads_count
port ENV.fetch("HANAMI_PORT", 2300)
environment ENV.fetch("HANAMI_ENV", "development")
workers ENV.fetch("HANAMI_WEB_CONCURRENCY", 2)
on_worker_boot do
Hanami.shutdown
end
preload_app!
So for my WebApp I tried making following changes to my_web_app/config/puma.rb
based on the suggestions in https://github.com/puma/puma/issues/2113
#port ENV.fetch("HANAMI_PORT", 2300)
bind "tcp://127.0.0.1:2300"
but no luck.
Exploring more I found few more resources at following locations
https://github.com/puma/puma/issues/782 https://github.com/puma/puma/issues/1022 https://github.com/puma/puma/pull/1318
but couldn't get exactly what I should do in my case.
Can anybody please help me resolving this?
Just in case it helps following are the contents of my /etc/hosts
127.0.0.1 localhost
127.0.1.1 jignesh-Latitude-7290
127.0.0.1 api.some_api.local
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
Thanks.
When puma starts it has two ports that listen: the HTTP server and the control server. You are configuring a different port for the HTTP server but not for the control server. That causes the error you see because the second server is attempting to start a control server on a port that is already in use.
Check the documentation on Control/Status Server:
Puma has a built-in status and control app that can be used to query and control Puma.
$ puma --control-url tcp://127.0.0.1:9293 --control-token foo
Puma will start the control server on localhost port 9293. All requests to the control server will need to include control token (in this case,
token=foo
) as a query parameter. This allows for simple authentication. Check outPuma::App::Status
or status.rb to see what the status app has available.
Thus the answer is that you need to start the second app with the --control-url
option, e.g.:
bundle exec puma --port=2400
and
bundle exec puma --control-url tcp://127.0.01:9294 --port=2300
But I would recommend that you specifically define all options on the command line for each for clarity, and then I'd flip the order so that you know that 9293
is for 2300
since they both have 3 and 9294
is for 2400
since they both have 4:
bundle exec puma --control-url tcp://127.0.01:9293 --port=2300
bundle exec puma --control-url tcp://127.0.01:9294 --port=2400
There is no option in puma.rb
that allows this option to be set so it must be configured from the command line. You're presently using bundle exec hanami ...
rather than bundle exec puma ...
so there are two possible paths to make this flag work:
bundle exec hanami --control-url ...
and it successfully passes those flags to Puma (but I don't know if this will work as I don't have a hanami app to test it with)bundle exec puma --control-url ...
and have to configure puma.rb
to load your hanami app (which is explained in the answer to How to configure Puma for a Hanami Application?)I recommend trying #1 first and if it doesn't work then look at #2.
Either way, defining the --control-url
flag will resolve this error.