As I create the documentation for Rutilus, the next area I’m focusing on is the tutorial. This is the area that is supposed to be extremely simple, that can get a newbie up and running very quickly. Of course it isn’t useful unless it’s hosted in the cloud. So the tutorial will be on how to get Rutilus hosted on a cloud provider as quickly and simply and possible.
Why not Heroku?
My first thought when I consider a simple, quick cloud solution is Heroku. I’m still in love with the process of deploying onto it:
- git push heroku master
- …that’s it
Compared to AWS, it’s a dream. And I thought that since Node.js allows you to use just one process to run multiple applications, we could get away with using one Heroku dyno to run every module. We can’t get a file system on Heroku, but they do have the mLab service which offers Mongo as a service with 500 MB for free. Free Heroku dyno plus free Mongo service… bingo! This could be something that people can get running super quickly and for free too.
Then the problems start happening. 🙂
Heroku only exposes one port. They give it to you internally as an environment variable (and it could be anything) but luckily it always maps to port 80 externally. But it’s still just one port. Rutilus needs a port for the WebSockets connection to the Logger, and at least one port for the Analytics module, which is used for HTTP, to serve up the dashboard and to serve up JSON user profiles/personas etc. Heroku just doesn’t work for this. It could if we used multiple dynos, but now people have to spin up at least two dynos. This starts at $7/month. This means that someone can’t just get started for free. The one free dyno you get and the $7/month “Hobby” dynos are also limited to 500 MB of memory, and we know from testing that the Analytics module in particular can eat up more than that on a big CSV export.
So that brought us back to AWS. The free tier gives you a 1 GB RAM instance for free for one year. And we already used their ECS (EC2 Container Service) to host all the prototype Rutilus modules on individual Docker containers on one instance. I began my quest to recreate that ECS setup with the new open source Rutilus modules. I ran into trouble though, and even after bugging my team mate for help, who definitely is more experienced with Docker and ECS than I was, we both got puzzled by the ceremony involved in setting it up, and the unexpected behavior. It really, really isn’t user friendly for beginners. And there’s no script code you can just run and forget about. It’s a lot of GUI ceremony.
After stumbling across a blog post online that informed me of the –restart switch of the “docker run” command, I had a eureka moment. Docker itself has the ability to manage itself. The pieces are there if you put them together. The “docker run” command is used to start a Docker container. Unfortunately, containers can crash because your application’s process can crash. EC2 manages this if you can get it setup. But the restart switch does too. “docker run –restart on-failure …” will run the container and keep an eye on it to restart it if it crashes. This is perfect! It’s exactly what we need! Now if AWS itself goes down, we need this docker command itself to run automatically when the instance boots back up. Again, ECS handles this. But there’s nothing stopping us from creating a bootup script to do this too. We have the knowledge by now to create our own very basic very simple Docker orchestration tool.
Normally, I’m the type to prefer to use an existing tool. It makes sense to me to delegate the work to someone I know is an expert in it. But in this situation, using that existing tool has proved to be so difficult that rollin our own solution, as long as we test it and know what we’re doing, is definitely the better option. We’ll understand it. And from our user’s perspective, setting up the AWS Rutilus bundle will consist of creating an EC2 instance (which is much, much easier than setting up ECS) and then they’re free from AWS’s GUI. They run our script, which pulls the Dockerfiles from the open source Git repos, builds the Docker images, and creates a startup script with the commands that will run those Docker images as containers that will indeed be restarted in the event of crashing. Create the EC2 instance. Run our script. Done.
I’m in the process of re-creating a Rutilus implementation on AWS using this new method to make sure it’s solid, and so far I’m having a lot of success. Once I finish testing all the modules, I will begin making the tutorial. Our goal is that the tutorial is completely ready by the beginning of March. Our team lead, for whom Rutilus is a black box, will be our guinea pig. He will attempt to set it up and we’ll see how easy this thing is to set up from the perspective of someone unfamiliar with the finer details of its development.