Meteor ❤ Google (A DevOps post)
I’ve been deploying a client project on Google Compute Engine for several months now, and it’s gotten to the point where it’s been such a qualified success, I’d like to share it with the rest of the world.
We haven’t needed to scale horizontally yet (we’d scale vertically well before then), but we do run separate application servers per client. The application is for healthcare, and Google was a good choice because our resources are covered under a HIPAA BAA. However, if someone wanted to scale horizontally, it’s definitely an option, either using Google App Engine (which I would also recommend).
Now, before we dive in, I haven’t tried this, but technically one could also deploy their Meteor application to Google App Engine, which I’ve been using successfully on a non-Meteor Node app in their Flexible Environment. Your logs would go to Google’s fabulous Stackdriver Logging interface. I’ll provide more information on that in a different post.
The advantage of using App Engine instead of this approach is that you’d have a more managed experience, similar to Modulus or Heroku, than a Digital Ocean VPS. However, if you’ve been deploying with mup for and need a change for whatever reason, keep reading on.
A note on “why Google?” — Google’s Cloud Platform is really quite the amazing experience. Many of the services tie in together very well, and the interface, tools, and documentation are beyond excellent, they’ve given me full control over every aspect of anything I’ve needed to do, and has full parity with available REST and CLI functionality. If you’ve ever had to use AWS, you’re in for a real treat.
What we’re going to do here is just run a bunch of terminal commands via shell scripts. Nothing fancy at all. Conceivably, with these techniques I’m about to outline, you could also deploy to IBM BlueMix, Microsoft Azure, or Amazon Web Services, depending on your needs and infrastructure goals.
I haven’t experimented with Docker much, but you could likely improve on these techniques using that system as well. For most, the additional tooling and domain knowledge is really just not a necessity.
First, let’s get acquainted with Google’s terminology. GCP, Google Cloud Platform. GAE, App Engine is their PaaS (platform as a service). GCE, Google Compute Engine, is their IaaS (infrastructure as a service). They also have GCS, Google Cloud Storage, which is like AWS S3. Their CLI client is called gcloud.
Halright, now let’s dive right in!
Prerequisites to this whole process: A Meteor or Node application, meteor or node installed on your system, a Google Cloud Platform account (easy, free, and you get a few months and a few hundred dollars of credit to try it out!), and the gcloud terminal client installed. The instructions are pretty straightforward, and you can find them here:
Also, feel free to modify what I’m doing here to better match your needs. This is just to get you going, really.
First, you’re going to want a build script, and this is the part that’s Meteor-specific.
This script assumes a few things. You’re working within a development directory that then includes your Meteor project directory. So, we put the app directory outside the directory you’re running your meteor command in. You’re going to then chmod +x ./meteor_build.sh your shell file, so you can run it, and call it with: ./meteor_build.sh (The preceding period in both commands is important, don’t omit that)
Simple so far, right? This just runs the Meteor build command, which turns your application into a single compressed tarball containing your entire application. Extremely convenient. It’s built specifically for 64-bit Linux.
This is going to set your project name (which you should change), which should always be set before running gcloud commands. Further, you need to have run this command prior:
gcloud auth login
This will authenticate you into the Google Account that was being used in the window of the system default browser that you last used. Super convenient, much easier than setting an environment variable or keeping track of users and passwords. If you’re working with other developers, it’s easy enough to add them to your project using GCP IAM (Identity and Access Management).
Also, we’re copying two files I haven’t outlined yet, startup.sh and nginx.sh. Uploading your bundle takes slightly longer, so I’ve added it last.
If you don’t have HTTPS in mind, comment the pem and key lines out, but seriously, it’s 2016, support HTTPS, FFS. If you need help, there’s lots of resources out there for you, just use the other thing Google’s known for. Be sure to put them in a separate directory, which I’ve called app-secure here.
Now, I’m about to lay down a decent-sized shell script that’s meant to be run only on your application server. This is the script that’s deployed to a GCS bucket, and used to bootstrap your server into running your Meteor app.
I won’t go into every line of this script, but it is commented, and I will tell you that it’s meant to be run on Debian 8 (Jessie) and that it’s worked well for us. Modify it to suit your needs and target architecture. It’s short enough that it’s worth reading every line.
Finally, you’ll need a basic nginx.conf. For that, find and modify the script found in Step 1 here.
Deploy a Meteor.js application on Ubuntu 14.04 with Nginx and MongoDB. This tutorial shows you how to build and deploy…www.digitalocean.com
Be sure to call that nginx.conf and put that in somewhere in your application as well.
With the scripts in hand, now we move on to the GCP console. There’s a lot of documentation for this that Google has provided, so I’ll just provide the steps, and you can fill in the blanks with their docs as needed.
First, create an Instance Template in GCE. In filling the form out to your preferences, be sure that it’s set to use Debian 8.
Be sure to fill out the Metadata section, with environment variables such as these:
The startup-script-url should always be set to gs://your-bucket-name/scripts/meteor_startup.sh . Omit Kadira if you’re not using it, and add anything else you need here. What’s here should be also exist in the Metadata section of your startup script, or it won’t be populated in the instance on startup.
Once you’ve got your Instance Template, now create an Instance Group with that selected. And once you finish those two things, the Instance Group should instantiate GCE Instances.
Finally, you can SSH into your server using the SSH button on the main GCE screen, and tail -f /var/log/startupscript.log and see your server work. If anything goes wrong with this process, that’s where you’ll see it. You can then fix it and reset your instance. If you’re running multiple instances, you shouldn’t experience an outage. You will also need to reset the instance if you run your deploy script and want to update the application bundle.
So, that’s about the extent of what you’ll need to do to get GCE to run your Meteor application, or at least, that should get you started. Have fun exploring all that GCP offers, and be sure to provide feedback, comments, and hearts!