Easy Microservices with Hyper Container-as-a-Service

I’m getting back into the groove of using Docker.

My most recent project requires that I be able to deploy a variable number of independent “bots”, each running the same code, but a different configuration. In technical terms, that translates to being able to instantly deploy a Docker container based on a custom pre-built Ubuntu image. Each bot would be a container. Oh, and this would potentially scale to thousands of bots.

EC2 was not a good solution to this problem for a few reasons:

Cost: the last time I calculated, it came out to about $12/mo for the weakest instance. I saw recently that Amazon offered a new service at $5/mo. Still a bit expensive.

Granularity: I don’t want a full instance or a cluster. Just a single container with an IP that I can connect to.

Deployment Speed: EC2 is ridiculously slow in bringing up instances. For some on-demand services, spending over a minute to spin up an instance is unacceptable.

Sure, there’s the AWS ECS service which claims to deal with containers, but I found it overly complex for my needs. When architecting a web app that consists of several modular interdependent components, I prefer each component to be as simple and predictable as possible.

Thankfully, I discovered a Container-as-a-Service called Hyper.sh, and they fit my needs perfectly. Hyper is a service where you work with remote docker containers exactly the way you would work with local containers. 1.) They bill you by the second, 2.) you only deal with containers, and 3.) these containers spin up within a few seconds to a usable state!

On top of that, their API is just the way a developer would want it. The command line interface is identical to Docker, e.g. hyper run -ti ubuntu:14.04 /bin/bash. The REST API endpoints are intuitive, e.g. POST /containers/${id}/start. It’s a perfect tool for deploying temporary microservices.

There is one caveat that any user of Hyper should be aware of: inbound communication to a container requires allocating what’s called an “FIP” or “Floating IP”.

Each allocated FIP costs $1/mo with no granularity. That’s $1 instantly added to the balance upon allocation of an IP and a partial month is treated like a full month. So you’ll want to strongly consider a way of reusing these FIPs or a way to avoid allocating them in the first place because allocating fresh ones frequently can quickly add up. Without the FIP, you can still have outbound communication, such as sending out an HTTP request, and indeed getting back the response. I’ll be using an outbound polling mechanism for the bots to communicate with a central “controller” API.

Nonetheless, I think Hyper is certainly filling in a much-needed niche. I am in no way affiliated with Hyper, but I hope they get plenty of business and stick around for a while.

A Pattern for Making Bots

Creating API-driven applications is fun, but in this age of data analysis and machine learning, it seems like there’s a new frontier beyond simple CRUD interfaces.

I thought it would be fun to start looking at what it takes to build a bot with Node.js. I knew that fundamentally, the bot would execute tasks (functions) sequentially, perhaps with a randomish interval of time between each task for the human effect.

That’s simple enough. Just have an Array of functions, and iterate through them with setInterval or setTimeout, right? Sure, that’s the quick and dirty way. But what about something that runs in a loop, forever?

Coming from a mobile app development background, I noticed that for both the iOS and Android SDKs, the ListView component doesn’t merely get data from an array, but rather from an Adapter, which is a class that dynamically generates an item based on some input, normally an index. The ListView doesn’t care how the adapter gets the data- it simply requests the data for a given input and hopefully something is returned.

With an adapter, it’s generally as simple as grabbing the data at index i of an array:

But because the data is generated on-the-fly when it’s needed, there’s far more possibilities:

 

So the adapter pattern is ideal when you have a potentially endless list of stuff, or in this case, a list of “actions”.

 

The cool thing here is that the bot doesn’t care about the underlying implementation of the adapter. We could easily create several different adapters, each that give the bot a different set of “instructions”.

Going even deeper, I wanted to create a framework for building dynamic “decision trees” that would generate actions based on conditions. The end result looks like this:

 

A tree data structure is appropriate here because in real life, we generally take different “paths”, which influence what the next action will be. Sometimes we have to jump backwards or forwards in the itinerary. By creating a basic set of classes for each node (Branch, Action, Jumper, Marker, Reset, Splitter, etc.) we can succinctly describe a set of possible actions and even serialize the tree for persistent storing.

Though the adapter pattern isn’t a lottery ticket to the machine learning jackpot, something tells me that it’ll serve as a useful utility in the tool belt for greater automation challenges.

The MERN Stack

Every once in a while, certain technologies get bundled together to form a conventional tech stack. There was LAMP, then Ruby on Rails, then MEAN, and probably some other combinations that never caught the limelight.

Mongo, Express and Node go together quite beautifully. That’s all backend. But what about the frontend? As far as SPAs (Single Page Applications) go, there was Backbone, Ember, Angular and a million other frameworks that attempted to solve the issue with modeling data, keeping state, and manipulating the DOM. Apparently Angular won that battle since the MEAN stack became the conventional choice for building a SPA.

And not without merit either. Angular handles routing, push state, two-way data binding, templating, AJAX, dependency injection, and a bunch of other stuff that are a pain in the butt to implement otherwise.

It turns out that most of those features, while nice, aren’t really that important. What we really needed was a tool that did one thing well: DOM manipulation. JQuery’s .html() method wasn’t tied to state. Backbone simply provided you with an empty render() function and gave you the middle finger. Ember had two-way data binding, but had a funky way of dealing with state.

React takes a different paradigm of thinking and focuses on components. The only way to truly have “components” is for all parts of a component to be centralized into a single class. And React pulls this off fruitfully.

With JSX syntax, you’re able to literally plant HTML inside of your JS component. Not in the form of a string, but straight up. Of course, the JSX is transpiled to plain old JS as the equivalent of document.createElement(), but in this case it’s React.createClass().

In React, every component simply has the view and the state. Within the view, you can interpolate data from the state, the way you’d interpolate PHP variables into HTML or the way you’d use Mustache or Handlebars in JS. Whenever the state of a component changes via this.setState(), React will reflect that state in the view automagically, by re-rendering only the affected views.

React brings back inline styles and inline JS, but this time it makes sense. Since the whole component is self-containing, you use inline references to point to parts of that component. The good thing is, the value of the inline attributes can be a plain old JS object, rather than an inline string. This means that it becomes harder to justify external CSS files when you can have per-component styling directly inside the component.

Edit 4/16/18: Ok, inline styles actually still suck. But you the use of JS objects for styling is super beneficial, especially when merging styles.

Want to see the MERN stack in action?

Check out a live demo at: http://www.focuswallpapers.com

See the code at: https://github.com/ryanbennettvoid/MERN-Focus-Wallpapers

Edit 4/16/18 — This stuff is dead/removed. I do have some React Native stuff on GitHub though: https://github.com/ryanbennettvoid

Why Docker Is Only Good On Linux

vagrant-manager.1.0.0.3docker

Between Vagrant and Docker, I wanted a quick and portable way of setting up a specific server configuration for a given project. Doing so on my local machine can get messy.

Generally, you’d use a provision file with Vagrant so that you can set up a single setup script to configure fresh Ubuntu VM instances. It’ll handle SSH, networking and filesystem mounting with simplicity.

But Vagrant is too bulky because you need to bring up a new VM for each project and that can quickly add up. Though the marketing tends to claim that Vagrant isn’t about VMs… it really is. It’s paired with VirtualBox 92.3% of the time.

I first tried Docker on an Ubuntu client. It was awesome because it didn’t require other dependencies like VirtualBox since it uses Linux Containers (whatever the heck those are). Though Docker does require downloading images of Ubuntu, they’re light and usually come in at around 500MB. Also, since Docker’s provisioning system works in layers (like a Git commit for each command that results in a system alteration), there’s a light footprint when you work with variations of your own “base image”.

When I started working on OSX, I thought that the Docker experience would remain the same. But nope. Now I’d need a Linux wrapper to run Docker in. There was originally Boot2Docker, which would load up an Ubuntu VM to run Docker inside, then you’d interface with Docker through that VM. Apparently Docker Toolkit is now the official solution for OSX.

So this means that I’d need to route the networking so that I can access the VM… then access the Docker process within that VM. Not just that, but also mount the filesystem so that I can access a folder in the VM… then also within Docker, access data volumes. Too much abstraction.

I’ll likely just end up using another laptop for Ubuntu + Docker development.

What’s Wrong With Mapbox’s New GL Native Library

I love Mapbox’s tile service. They have awesome quality map tiles that really add polish to any map-driven mobile app.

I’m in the process of building a location-based photo sharing app called ThatSnap for iOS, Android and browsers. So far so good- I’ve launched to iOS and web.

For iOS I’m using Apple’s default MapKit library + FBAnnotationClusterSwift for marker clustering.

Simulator Screen Shot Feb 22, 2016, 3.36.51 AM

For web: Leaflet (the best darned map library ever) + Leaflet.markercluster. Both of these solutions have worked out nicely.

ThatSnap.com Leaflet Example

They’re stable, smooth and have intuitive APIs.

For Android on the other hand, finding a good mapping library is not as easy. Of course, Google Maps is the default choice and an excellent one, but you’ll eventually pay up the whazoo if your app falls within certain commercial guidelines. I’d prefer an open source solution.

I first tried OSMDroid. Though the documentation was practically non-existent, the sample projects helped with getting started, while digging into the method overrides helped with customizing the innards of the library, such as marker rendering. I didn’t have any qualms with OSMDroid, but if I were going to use Mapbox’s tile service, I might as well try their Android SDK.

Mapbox’s original Android SDK was a branch of the OSMDroid project with some refactoring. The incentive for using the Mapbox SDK rather than OSMDroid was that it had integrations that allowed for easy use of Mapbox’s various API services. I recall it being very buggy and I had issues implementing custom features. Vanilla OSMDroid was the better choice.

Fast forward to 2016 and they’ve pulled the rug. That SDK is deprecated now and they’ve actually removed the repo from the public eye and cut all references to it. In it’s place is the new Mapbox GL Native SDK. When I first caught wind of it, I thought “awesome, C++, SVG, OOOH, yay!” I copied the dependency to my gradle file, added the MapView to a fragment and got the new SDK up and running.

First thing’s first: it’s sluggish. Even without markers, you ain’t running anywhere near 60fps. More like 20fps. Then if you want to add markers, it’s ridiculously slow when rendering them. It may take a few seconds to render a couple thousand markers. The bulk addMarker method is faster than using a loop to add markers individually, but it’s still slow compared to pretty much any other mapping solution. Strike 1.

OK, so it wasn’t unbearable. I’d never be showing too many markers anyway because I’d be using cluster markers… But wait… There’s no clustering implementation. That was enough to nearly deter me, but screw it- I ended up taking a Quadtree implementation and creating my own clustering system based on a grid. The tricky part was that the grid would need to be relative to the actual map coordinates, not the screen bounds. Though I would have preferred to save time by using an existing clustering library, it was a good educational experience creating it myself. Nonetheless, Strike 2.

I could now render markers (albeit slowly) and cluster them… now let’s see if I could dynamically change the icons. I would need to first immediately render the icons, then asynchronously load thumbnails from the web, then replace the placeholders with the thumbnails. Surely, I’d just keep a reference to each marker, then modify them and – if needed – invalidate them upon update.

The issue with Mapbox’s current way of handling markers is that you don’t create a “Marker” object, then add it to the map and retrieve it again as a “Marker” object. That’s the normal way of doing things. Instead, you start with a “MarkerOptions” object, add it to the map, and get back a “Marker” object. That’s really counterintuitive when you’re working with complex and dynamic markers that you need to keep reference of. Strike 3.

At that point, I just cut my losses and now I’m back to working with OSMDroid (which is surprisingly still being maintained/updated at this time). I know that the whole C++ thing is new for Mapbox and it’s practically in the beta phase right now but it’s most definitely NOT production ready, in my opinion.

I’m sure that in a few months, once the major issues have been resolved and optimizations made, it’ll be a worth using.