The Microsoft ecosystem is not kind to Ruby developers. The Ruby SDK for Azure was retired in February 2021, and the support for Ruby in the OpenAPI client generator Kiota is extremely limited, if not unusable. However, .NET Aspire is a special case. This ambitious local development orchestrator is not tied to any specific technology, as I explained in my previous article on the inner workings of .NET Aspire. Therefore, it is possible to run Ruby on Rails web applications on it.
Please note, the source code presented in this article is subject to change, as .NET Aspire is still under development.
Update 4/11/2024: This post has been updated to reflect the latest changes in .NET Aspire preview 5.
Prerequisites
- .NET SDK and .NET Aspire must be installed (latest version at the time of this article: preview 5),
- Ruby 3.x (for Windows, use RubyInstaller),
- Ruby on Rails.
Developing a custom Rails resource for .NET Aspire’s app model
.NET Aspire uses an “application model”, which represents the list of resources that make up a distributed application. The two primary resource types in .NET Aspire are executables and containers. For Ruby on Rails web applications, we want to create an executable with the following command:
ruby bin/rails server
This command is used to start a Rails application and is cross-platform. Thanks to the extensibility of the .NET Aspire app model, we can define our own Rails resource, which inherits from the ExecutableResource
class in .NET Aspire. Here is the complete source code for declaring a Rails application in .NET Aspire:
using Microsoft.Extensions.Hosting;
namespace Aspire.Hosting;
internal class RailsAppResource(string name, string workingDirectory)
: ExecutableResource(name, "ruby", workingDirectory);
internal static class RailsAppExtensions
{
public static IResourceBuilder<RailsAppResource> AddRailsApp(
this IDistributedApplicationBuilder builder, string name, string command, string workingDirectory, string[]? args = null)
{
var resource = new RailsAppResource(name, workingDirectory);
return builder.AddResource(resource)
.WithArgs(context =>
{
context.Args.Add("bin/rails");
context.Args.Add(command);
if (args is not null)
{
foreach (var arg in args)
{
context.Args.Add(arg);
}
}
})
.WithOtlpExporter()
.WithEnvironment("RAILS_ENV", builder.Environment.IsDevelopment() ? "development" : "production")
.ExcludeFromManifest();
}
}
Let’s focus on the experience of declaring a Rails application in your Program.cs file of your .NET Aspire project:
var builder = DistributedApplication.CreateBuilder(args);
builder.AddRailsApp("myrailsapp", "server", "path/to/your/rails/app")
.WithEndpoint(port: 3000, scheme: "http", env: "PORT");
builder.Build().Run();
.NET Aspire preview 5 changes
- You can now disable the Aspire proxy for a Rails app resource by specifying
isProxied
asfalse
:.WithEndpoint(port: 3000, scheme: "http", env: "PORT", isProxied: false)
. - If your Rails app is using an unsecured transport (non-TLS
http
) protocol, you need to set the environment variableASPIRE_ALLOW_UNSECURED_TRANSPORT
totrue
. See Allow unsecure transport in .NET Aspire.