Ruby on Rails on Azure App Service (Web Sites) with Linux (and Ubuntu on Windows 10)
Running Ruby on Rails on Windows has historically sucked. Most of the Ruby/Rails folks are Mac and Linux users and haven't focused on getting Rails to be usable for daily development on Windows. There have been some heroic efforts by a number of volunteers to get Rails working with projects like RailsInstaller, but native modules and dependencies almost always cause problems. Even more, when you go to deploy your Rails app you're likely using a Linux host so you may run into differences between operating systems.
Fast forward to today and Windows 10 has the Ubuntu-based "Linux Subsystem for Windows" (WSL) and the native bash shell which means you can run real Linux elf binaries on Windows natively without a Virtual Machine...so you should do your Windows-based Rails development in Bash on Windows.
Ruby on Rails development is great on Windows 10 because you've Windows 10 handling the "windows" UI part and bash and Ubuntu handling the shell.
After I set it up I want to git deploy my app to Azure, easily.
Developing on Ruby on Rails on Windows 10 using WSL
Rails and Ruby folks can apt-get update and apt-get install ruby, they can install rbenv or rvm as they like. These days rbenv is preferred.
Once you have Ubuntu on Windows 10 installed you can quickly install "rbenv" like this within Bash. Here I'm getting 2.3.0.
~$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv
~$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
~$ echo 'eval "$(rbenv init -)"' >> ~/.bashrc
~$ exec $SHELL
~$ git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
~$ echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
~$ exec $SHELL
~$ rbenv install 2.3.0
~$ rbenv global 2.3.0
~$ ruby -v
~$ gem install bundler
~$ rbenv reshash
Here's a screenshot mid-process on my SurfaceBook. This build/install step takes a while and hits the disk a lot, FYI.
At this point I've got Ruby, now I need Rails, as well as NodeJs for the Rails Asset Pipeline. You can change the versions as appropriate.
@ curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -
$ sudo apt-get install -y nodejs
$ gem install rails -v 5.0.1
You will likely also want either PostgresSQL or MySQL or Mongo, or you can use a Cloud DB like Azure DocumentDB.
When you're developing on both Windows and Linux at the same time, you'll likely want to keep your code in one place or the other, not both. I use the automatic mount point that WSL creates at /mnt/c so for this sample I'm at /mnt/c/Users/scott/Desktop/RailsonAzure which maps to a folder on my Windows desktop. You can be anywhere, just be aware of your CR/LF settings and stay in one world.
I did a "rails new ." and got it running locally. Here you can se Visual Studio Code with Ruby Extensions and my project open next to Bash on Windows.
After I've got a Rails app running and I'm able to develop cleanly, jumping between Visual Studio Code on Windows and the Bash prompt within Ubuntu, I want to deploy the app to the web.
Since this is a simple "Hello World" default rails app I can't deploy it somewhere where the Rails Environment is Production. There's no Route in routes.rb (the Yay! You're on Rails message is development-time only) and there's no SECRET_KEY_BASE environment variable set which is used to verify signed cookies. I'll need to add those two things. I'll change routes.rb quickly to just use the default Welcome page for this demo, like this:
Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html get '/' => "rails/welcome#index" end
And I'll add the SECRET_KEY_BASE in as an App Setting/ENV var in the Azure portal when I make my backend, below.
Deploying Ruby on Rails App to Azure App Service on Linux
From the New menu in the Azure portal, choose to Web App on Linux (in preview as of the time I wrote this) from the Web + Mobile option. This will make an App Service Plan that has an App within it. There are a bunch of application stacks you can use here including node.js, PHP, .NET Core, and Ruby.
NOTE: A few glossary and definition points. Azure App Service is the Azure PaaS (Platform as a Service). You run Web Apps on Azure App Service. An Azure App Service Plan is the underlying Virtual Machine (sall, medium, large, etc.) that hosts n number of App Services/Web Sites. I have 20 App Services/Web Sites running under a App Service Plan with a Small VM. By default this is Windows by can run Php, Python, Node, .NET, etc. In this blog post I'm using an App Service Plan that runs Linux and hosts Docker containers. My Rails app will live inside that App Service and you can find the Dockerfiles and other info here https://github.com/Azure-App-Service/ruby or use your own Docker image.
Here you can see my Azure App Service that I'll now deploy to using Git. I could also FTP.
I went into Deployment OPtions and setup a local (to Azure) git repro. Now I can see that under Overview.
On my local bash I add azure as a remote. This can be set up however your workflow is setup. In this case, Git is FTP for code.
$ git add remote azure https://email@example.com:443/RubyOnAzureAppService.git
$ git add .
$ git commit -m "initial"
$ git push azure master
This starts the deployment as the code is pushed to Azure.
IMPORTANT: I will also add "RAILS_ENV= production" and a SECRET_KEY_BASE=to my Azure Application Settings. You can make a new secret with "rake secret."
If I'm having trouble I can turn on Application Logging, Web Server Logging, and Detailed Error Messages under Diagnostic Logs then FTP into the App Service and look at the logs.
This is all in Preview so you'll likely run into issues. They are updating the underlying systems very often. Some gotchas I hit:
- Deploying/redeploying requires an explicit site restart, today. I hear that'll be fixed soon.
- I had to dig log files out via FTP. They are going to expose logs in the portal.
- I used the Kudu "sidecar" site at mysite.scm.azurewebsite.net to get shell access to the Kudu container, but I'd like to be able to ssh into or get to access to the actual running container from the Azure Portal one day.
That said, if you'd like more internal details on how this works, you can watch a session from Connect() last year with developer Nazim Lala. Thanks to James Christianson for his debugging help!
Sponsor: Did you know VSTS can integrate closely with Octopus Deploy? Watch Damian Brady and Brian A. Randell as they show you how to automate deployments from VSTS to Octopus Deploy, and demo the new VSTS Octopus Deploy dashboard widget. Watch now