Sinatra doesn't want to say hello - ruby

What could possibly be wrong? I run this file:
require 'sinatra'
get '/' do
"Just Do It"
end
Server starts up:
== Sinatra (v2.0.0) has taken the stage on 3000 for development with backup from Thin
Thin web server (v1.7.1 codename Muffin Mode)
Maximum connections set to 1024
Listening on 127.0.0.1:3000, CTRL+C to stop
(I set the address and port because it is what I have in my vagrantfile.
However I get nothing, either in Chrome or Firefox. I've tried various config.ru's and changed the file above to an ru extension to try rackup but that hasn't worked either.
I have uninstalled and reinstalled the Mustermann and Sinatra gems and made sure I had the gems that are required in base.rb.
Any ideas?

Related

Need config.ru to Start up a Sinatra App from within a Docker Container?

Why isn't the simple command ruby my app.rb working to boot up my Sinatra application from within a Docker container?
I have a very simple Sinatra app:
# myapp.rb
require 'sinatra'
get '/' do
'Hello world!'
end
I run this locally with ruby myapp.rb and I get the following output
== Sinatra (v2.1.0) has taken the stage on 4567 for development with backup from Puma
Puma starting in single mode...
* Puma version: 5.1.1 (ruby 2.7.0-p0) ("At Your Service")
* Min threads: 0
* Max threads: 5
* Environment: development
* PID: 49242
* Listening on http://127.0.0.1:4567
* Listening on http://[::1]:4567
Use Ctrl-C to stop
Opens up on http://127.0.0.1:4567 with no issue. When moving to Dockerize the app, I create a Gemfile with Sinatra and the following Dockerfile.
FROM ruby:2.7.0
WORKDIR /code
COPY . /code
RUN bundle install
CMD ["ruby", "myapp.rb"]
Standing up the container, it seem successful (Docker Desktop is green, no terminal errors), but clicking on the suggested link http://localhost:4567/ doesn't load (sad Chrome face). Logs from within the container look like so
[2020-12-27 18:04:52] INFO WEBrick 1.6.0
[2020-12-27 18:04:52] INFO ruby 2.7.0 (2019-12-25) [x86_64-linux]
== Sinatra (v2.1.0) has taken the stage on 4567 for development with backup from WEBrick
[2020-12-27 18:04:52] INFO WEBrick::HTTPServer#start: pid=1 port=4567
However, when I add the below config.ru file and change the last line of my Dockerfile to CMD ["bundle", "exec", "rackup", "--host", "0.0.0.0", "-p", "4567"], http://localhost:4567/ opens with no issue.
# config.ru
require './myapp'
run Sinatra::Application
Why are these tweaks necessary to make the app work? The logs from with the container look nearly the same.
[2020-12-27 18:01:49] INFO WEBrick 1.6.0
[2020-12-27 18:01:49] INFO ruby 2.7.0 (2019-12-25) [x86_64-linux]
[2020-12-27 18:01:49] INFO WEBrick::HTTPServer#start: pid=1 port=4567
172.17.0.1 - - [27/Dec/2020:18:02:44 +0000] "GET / HTTP/1.1" 200 12 0.0420
I'm not necessarily wondering about "best practices" here (this is a side project). I'm more just trying to understand what I might be missing about how Dockerizing apps works.
Docker commands for both cases (and I clear the images/containers between runs):
docker build --tag sinatra-img .
docker run --name sinatra-app -dp 4567:4567 sinatra-img
When you start your app with ruby myapp.rb in a Docker container, your app is listening on localhost because it is running in development mode. If your Docker server runs in a VM, you won't be able to access your app. To fix this, when you run your app in a Docker container, make sure that it is listening on 0.0.0.0: ruby myapp.rb -o 0.0.0.0
NOTE:
The following answer relates to a previous version of the question. The new question has a different answer (fixing the binding address using the -o 0.0.0.0 CLI argument).
The Sinatra framework is based on Rack and requires a Rack compatible server... either that, or it can also fallback on the WEBrick server that's included with the Ruby language bundle.
WEBrick is a decent server, but it wasn't designed for the heavier loads or the needs of an actual web application running in production.
For this reason, you SHOULD use a Rack compatible server.
However, this does not mean that you have to use the rackup CLI helper.
Some servers, like Puma, iodine and passenger include their own CLI, so you could run your application using:
CMD ["bundle", "exec", "puma", "-p", "4567"]
Type puma -h (or iodine -h) for more command line options. A server's specific CLI might offer some server specific features you don't get with backup. For example, Iodine exposes some security options through it's CLI (maximum file upload size, maximum total header length, web socket message limits, etc').
Using the server's CLI interface should be considered a better option.
In addition, although I wouldn't recommend it, some servers also provide a Ruby API that allows you start the server from a Ruby script (instead of a config.ru file). i.e., with iodine (I'm biased):
ENV['PORT'] ||= "4567"
require 'iodine' # will test the `ENV['PORT']` value
require 'sinatra'
get '/' do
'Hello world!'
end
Iodine.listen service: :http, public: './public', handler: Sinatra::Application
# Iodine.threads = 16 # or whatever.
# Iodine.workers = -2 # half the core count (negative value).
Iodine.start
I wouldn't use this approach. It tends to be more fragile and it also hardcodes both the environment and the server settings in the application.
I would just add the config.ru and use a decent server (I like iodine, but Puma is much more popular and unless you need real-time pub/sub, websockets or some specific security/performance features, popular is often safer).
EDIT (according to comment):
If what you're really looking for is to embed the command bundle exec into the Ruby script (for version control using a gemfile), you can start the script with the lines
#!/usr/bin/env ruby
require 'bundler'
Bundler.require
Or, if you don't want to use a gemfile at all (or don't require version control), you can jus start the first line with:
#!/usr/bin/env ruby
Then you can start your server directly:
CMD ["puma", "-p", "4567"]
Or, without using the server's CLI, using the example script above, run:
CMD ["my_script.rb"]

Can a Rails 5 application with ActionCable be deployed on Windows?

I have a Rails 5 application which I was planning to deploy on Linux, but because we needed some access very specific Windows-only software, I need to deploy it on Windows Server 2012 R2. My software stack (or mix) was supposed to be Nginx/Puma/Rails/PostgreSQL/Redis. Everything installs for me on Windows except Puma, and the Rails documentation says that I need Puma for ActionCable.
How do I get Puma to run on Windows? I have seen and tried snippets of things to try, and I have also seen and tried snippets on what not to do, such as running in daemon mode because fork() is not supported. Does anybody have a repeatable set of instructions on how to get Puma to work on Windows with a Rails application?
Or, if Puma a non-starter for Windows, is there a repeatable alternative for deploying a Rails 5 application with ActionCable to a Windows Server host (e.g. Windows 2012 R2)?
According to the readme file from the github page, following things to keep in mind:
daemon mode is not supported. so comment out/remove the following, if there is such line.
daemonize false
Workers do not work in Windows since it does not support processes. We want the workers to be "0". So comment out following lines:
workers 2 # The default is "0"
preload_app!
server sockets are not seamless on restart, they must be closed and reopened. These platforms have no way to pass descriptors into a new process that is exposed to ruby.
Do not use unix socket, instead bind the server to "tcp://". So comment out any line that looks like following:
bind 'unix:///var/run/puma.sock'
bind 'unix:///var/run/puma.sock?umask=0111'
Instead use following:
bind "tcp://127.0.0.1:4001"
# You don't have to if you don't need to specify a port
# since the default is "tcp://0.0.0.0:9292"
If you see any http parse error (malformed http request) after starting rails server, try this answer. If it doesn't work, then comment out this line from config/environments/production.rb or config/environments/production.rb (depending on which environment you want to run Puma)
config.force_ssl = true
Here is what the puma.rb file might look like:
worker 0 # Not necessary. The default is "0"
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
threads threads_count, threads_count
bind "tcp://127.0.0.1:4001" # Not necessary. Default is "tcp://0.0.0.0:9292"
environment ENV.fetch("RAILS_ENV") { "development" }
plugin :tmp_restart
Finally run bundle exec puma -C config\puma.rb and it should work.

Simple Ruby "Hello, World" Program for Webrick Using Virtual Hosts

I searched the internet for a "Hello, World" type program for Webrick in Ruby, but could not find anything that worked. I found this guide on SO but for the life of me could not get it to work.
Consulting the Ruby Documentation for Webrick led me to some code snippets that got me going in the right direction. There were no easy-to-follow tutorials so I wanted to add my answer on SO.
I was using Ubuntu 14.04 without Apache or Nginx and wanted my server for a virtual host. Webrick by default does not respond to requests concurrently but for me this was a plus in addition to its small footprint. I was hoping to get it working without the Rails framework for an even lighter footprint.
To get started, I installed Ruby with the Ubuntu package manager. If you are using CentOS or another Linux distribution, you can adapt this step to your particular package manager. Also make sure port 80 is open on your web server. It's possible to get SSL with Webrick but I chose not to at this point.
sudo apt-get install ruby
Here is the script which I named myapp.rb that I am using. I placed it /var/www/myapp. Ideally, I think it should not be in document root. You should also create a special user and group just to run the script to improve security (I have not outlined those steps here)
require 'webrick'
server = WEBrick::HTTPServer.new(:Port => 80,
:SSLEnable => false,
:DocumentRoot => '/var/www/myapp',
:ServerAlias => 'myapp.example.com')
server.mount_proc '/' do |req, res|
res.body = 'Hello, world!'
end
trap 'INT' do server.shutdown end
server.start
The require statement above tells Ruby to include the Webrick classes when running the program. The second line of the script creates an instance of Webrick with the following options:
Use Port 80
Disable SSL
Set the document root to /var/www/myapp
Set the Server Alias to myapp.example.com
Of course, you'll have to configure your particular domains DNS'. The server.mount_proc is telling Ruby to serve the response, "Hello, world" at document root. I think you can specify a subdirectory there if you life. The Ruby Webrick documentation above has information on that.
The line that begins with trap means that the web server can be stopped with Ctrl-C. To start the script I typed the following at the SSH command line:
ruby myapp.rb

Can't launch simple Sinatra app using rackup and jRuby (no response from web server)

I've got a Sinatra "hello world" app that I am trying to run using jRuby. It works when I run the app, but not when I run rackup. Can anyone tell me what is going on here?
Here's the app, in a file 'app.rb':
require 'rubygems'
require 'bundler/setup'
require 'sinatra'
configure do
set :bind, '0.0.0.0'
end
get '/' do
'Boo!'
end
I can run this using bundle exec ruby app.rb and it works fine:
jonea#centos7andy[~/andy/sinatra_sand_jruby]%: bundle exec ruby app.rb
[2015-01-12 10:36:06] INFO WEBrick 1.3.1
[2015-01-12 10:36:06] INFO ruby 1.9.3 (2014-12-09) [java]
== Sinatra/1.4.5 has taken the stage on 4567 for development with backup from WEBrick
[2015-01-12 10:36:06] INFO WEBrick::HTTPServer#start: pid=31654 port=4567
Here is my config.ru to call the above program:
require 'rubygems'
require 'bundler/setup'
require 'sinatra'
require './app'
run Sinatra::Application
If I run this, it appears to work, but I can't access the server using a web browser:
jonea#centos7andy[~/andy/sinatra_sand_jruby]%: bundle exec rackup -p4567
[2015-01-12 10:29:06] INFO WEBrick 1.3.1
[2015-01-12 10:29:06] INFO ruby 1.9.3 (2014-12-09) [java]
[2015-01-12 10:29:06] INFO WEBrick::HTTPServer#start: pid=31553 port=4567
I note the suspicious lack of "Sinatra has taken the stage..."
When you run the Ruby file directly (or when you add Sinatra.run! to the config.ru file) Sinatra runs its own server. In this case the call to set :bind, '0.0.0.0' will take effect. When you run through rackup this setting is ignored.
The default host that rackup listens to is localhost, so the server will only be available through the same machine, you won’t be able to access it from other machines. To access it through other machines set the --host option:
bundle exec rackup -p4567 --host 0.0.0.0
(Note the output of rackup -h for the current version says the default host is 0.0.0.0, but this is out of date and has been fixed in master.)
Well, this is hardly sufficient to explain what is going on, but I can make it work if in config.ru I replace
run Sinatra::Application
with
Sinatra::Application.run!
In fact, knowing that makes me even more confused. Some sort of bug in Rack?
#config.ru
require "./app.rb"
set :bind, '0.0.0.0'
set :port, 9292 #set your port!
Sinatra::Application.run!
try this code and type rackup
Then you can get the results you want.
I have slightly similar situation.
But the difference is that, my Jruby + Sinatra rackup app is finally starts responding.
But it takes lots of time, sometimes it starts responding 5 minutes after app start.
I found out, that after app start port is not listened for some period time.
If we make netstat -an it will not show our app port.
Actually I don't know the reason of such behavior, but I'll dig for it.

port in use when not using a port

I'm trying to run the following Sinatra application and am getting an error message telling me that I can't start a server, either because port's already in use or because I don't have root privileges. I have never had this problem before starting a Sinatra application. I updated to Mountain Lion for my mac a few days ago and wonder if this might be the cause of the problem. I also use RVM. Can anyone provide a suggestion...
require "sinatra"
class MyApp < Sinatra::Base
get '/' do
"Hello from MyApp"
end
end
== Sinatra/1.3.3 has taken the stage on 4567 for development with backup from Thin
>> Thin web server (v1.5.0 codename Knife)
>> Maximum connections set to 1024
>> Listening on 0.0.0.0:4567, CTRL+C to stop
/Users/me/.rvm/gems/ruby-1.9.2-p290#global/gems/eventmachine-1.0.0/lib/eventmachine.rb:526:in `start_tcp_server': no acceptor (port is in use or requires root privileges) (RuntimeError)
Update:
I can still run a rails server on my machine so I think the problem is specific to Sinatra. Furthermore, I was able to run Sinatra applications fine up til a few days ago, when I started playing around with this Rack Tutorialwhich instructed me to explicitly to set a port. I'm wondering if that made a permanent change.
>> Rack::Handler::WEBrick.run my_rack_proc, :Port => 9876
[2011-10-24 11:32:21] INFO WEBrick 1.3.1
[2011-10-24 11:32:21] INFO ruby 1.9.2 (2011-07-09) [i386-mingw32]
[2011-10-24 11:32:21] INFO WEBrick::HTTPServer#start: pid=480 port=9876
Note: I had a different answer before. I've replaced it with a new, more focused answer, but I left the old answer at the bottom for anyone still looking for it.
New answer:
This error is caused by the fact that the last time you had a server running, you closed the terminal without killing the server. I believe this is called 'running headless', like a chicken with its head cut off. So even though nobody is around watching, the server is still running and taking up the 'space' called port 9393. When you try to start a new server, there is already one running. It's kind of like a parking spot: since there is already a car there, you can't part a new one in the same spot.
Here's how I reproduced the error. I booted up a sinatra server, closed down the terminal without killing the server first, opened up a new terminal, and tried to boot up another server.
Taras-MacBook-Air:SurveyDBCGroupProject tlroys$ shotgun
== Shotgun/Thin on http://127.0.0.1:9393/
Thin web server (v1.6.1 codename Death Proof)
Maximum connections set to 1024
Listening on 127.0.0.1:9393, CTRL+C to stop
/Users/tlroys/.rvm/gems/ruby-1.9.3-p484/gems/eventmachine-1.0.3/lib/eventmachine.rb:526:in `start_tcp_server': no acceptor (port is in use or requires root privileges) (RuntimeError)
#deleted stack trace
What do you do if a car is parked in your spot? You can call the tow truck and tell the driver the license plate number of the car, and tell them to tow it away.
To find out the license plate number of the car, run the following set of commands I found on Stack Overflow
ps aux | grep ruby
This finds the process id, aka the license plate number of the 'car' occupying the 'parking spot.' Note: the server occupying my 'spot' is in fact a server written using the programming language ruby: sort of like some cars are Chevorlets. I can tell the person finding out the license plate number to look for the chevrolet, and he will find the right car as long as there are no other cars around. Since this 'zombie server' is the only ruby process running on my computer, telling the grep command to look for ruby will give the right process id/ license plate numbers. If I wanted to be more specific, I could probably say
ps aux | grep shotgun
and get the same result.
-The output should look like this: there should be two things in the list
27235 ?? S 0:00.72 /Users/tlroys/.rvm/gems/ruby-1.9.3-p484/bin/shotgun
27393 s000 S+ 0:00.00 grep ruby
The first one is the actual 'zombie server' you are looking for. The second thing is funny, because you are looking for all processes that contains the word ruby, and so it find the process that is looking for all processes that contain the word ruby. Haha.
Kill the first process. with the following command. Make sure to change the numbers to the actual process id:
kill -9 27235
You'll have to change the 27235 to the actual process id that you see, but you get the idea. The tow truck has come, dragged the car away to the junkyard, and left the spot free for me to use.
Old answer:
I had exactly the same issue, and as far as I can tell it was because there was a ruby process running on the port that I run my sinatra apps on. Below is the error (With the stack trace remove for brevity's sake) and the commands I ran to figure out what was going wrong and fix it.
In short, I tried to start my sinatra app, and it said port is in use or required root privileges. I then used the Tin Man's lsof command (seen above) to find out what ports were in use.
It showed that ruby was running on port 9393. I killed it with killall. I tried starting my sinatra app again. It worked.
Taras-MacBook-Air:sinatra_sandbox tlroys$ bundle exec shotgun config.ru
The source :rubygems is deprecated because HTTP requests are insecure.
Please change your source to 'https://rubygems.org' if possible, or 'http://rubygems.org' if not.
== Shotgun/Thin on http://127.0.0.1:9393/
>> Thin web server (v1.5.0 codename Knife)
>> Maximum connections set to 1024
>> Listening on 127.0.0.1:9393, CTRL+C to stop
/Users/tlroys/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/eventmachine-1.0.0/lib/eventmachine.rb:526:in `start_tcp_server': no acceptor (port is in use or requires root privileges) (RuntimeError)
Taras-MacBook-Air:sinatra_sandbox tlroys$ lsof -i TCP | grep LISTEN
ruby 59176 tlroys 9u IPv4 0xffffff8012fbdc00 0t0 TCP localhost:9393 (LISTEN)
Taras-MacBook-Air:sinatra_sandbox tlroys$ killall ruby
Taras-MacBook-Air:sinatra_sandbox tlroys$ bundle exec shotgun config.ru
The source :rubygems is deprecated because HTTP requests are insecure.
Please change your source to 'https://rubygems.org' if possible, or 'http://rubygems.org' if not.
Shotgun/Thin on http://127.0.0.1:9393/
Thin web server (v1.5.0 codename Knife)
Maximum connections set to 1024
Listening on 127.0.0.1:9393, CTRL+C to stop
The restriction about only root being able to open "well known port#s" has nothing to do with Ruby - it's an OS thing. It's also, in general, a Good Thing.
Look at "cannot start sinatra process - eventmachine 'no acceptor'".
There are two suggestions in the link:
The configuration issue he encountered might well fix your problem
If nothing else, the link also shows you how to change the port# (to some different - and perhaps higher) number.

Resources