Develop, Test, and Deploy Scalable Meteor Applications

Written by: Daniël van Gils
7 min read

This article was originally published on Cloud 66 by Daniël van Gils. With their kind permission, we’re sharing it here for Codeship readers.

Let's assume you’ve already devoured every Docker 101 tutorial for breakfast. You’re now ready to work on your Meteor/Node application and go for an all-containerized approach to development and operations.

You're in for a treat. In this blog post, we'll be explaining what a proper Docker workflow looks like and how to manipulate it to make it your own. We'll guide you through the entire Docker development process, test your Meteor application and run your app in production on the cloud provider of your choice using Cloud 66 and Codeship Pro. To wrap things up, we'll also show you how to scale your Meteor app to greater heights.

If you don't like reading, just sit back and relax -- you can watch the recorded webinar we did together with Codeship. The webinar will guide you step-by-step and explain all the example code:

Let's get started.

We Need a Plan!

Our plan follows this five-step approach:

  1. Develop your Meteor app on your local dev machine.

  2. Run your app in a staging environment on any cloud or bring your own server.

  3. Run your tests using a CI/CD solution provided by Codeship.

  4. Run your app in a production and scale.

  5. Start to iterate!

To kickstart the process, we'll need an application to get started. For this example, we are using the official Meteor example app called Todos. Please clone it onto your local dev machine, then check out the source and how the project is structured.

Act Local, Think Global

Before we get started, make sure you have installed the latest Docker Engine and Docker Compose.

In a containerized world, the first thing on your mind is to get the project up and running on your local development box. The preferred way is to create a Dockerfile (Dockerfile.development »), which is responsible for all the dependencies (Node.js packages, Meteor runtime, and so on), and a Docker Compose (docker-compose.yml ») file to make a composit of your Meteor app and the backend MongoDB.

We need to build all the services we need.

docker-compose build

When this process is done, we can run our development environment:

docker-compose run --service-ports meteor

Point your browser to http://localhost:3000, and you can start developing right away.

The app looks like this:

Test First, Ask Questions Later

I'm using the BDD way of testing. Every application exposes a contract/software interface, which can be tested from the outside in.

For the Meteor test, we use the mocha framework for running tests. For those with a Ruby background, mocha has some similarities with rspec.

Here's an overview of what a developer workflow will look like using Codeship Pro and Cloud 66.

First, let's look at what's going on under the hood:

  • Build the container image for the app

  • Run the app and start the dependencies the service relies on. MongoDB in this case.

  • Wait for MongoDB to become ready.

  • WARNING: You'll never know how long it takes for a service to boot. Make sure to check if a service is running before making calls. You can use a generic script ( »).

  • Run the tests against the app when everything is up and running.

  • Notify your Docker stack managed by Cloud 66 using the webhook.

Test Time

Build all the services we need.

* docker-compose build

Run the test suite.

* docker-compose run test

Watch the generic wait scrips to check if MongoDB is up and start firing off those tests. Expected output:

The Works

That's've tested the Todo service. Take a look at our (docker-compose.yml »).

What you want to remember is that only the meteor service will be deployed to the production stack managed by Cloud 66. The rest of the services are for local development and testing and will be running on Codeship Pro.

You notice we use an alias for our links. In a real Docker production setup, you need some kind of service discovery. The Cloud 66 platform uses the very stable DNS for service discovery, ElasticDNS.

After redeploying the service, ElasticDNS automagically updates, providing you with zero downtime. By linking the containers in our local and test environment this way, we don't need to change the code finding the services.

Use Codeship Pro for Running Your Tests

Nice! Does it run on the new Codeship Pro? Codeship released a CLI tool called Jet to test your service locally and in the cloud. Follow this guide to Codeship Docker infrastructure to get Jet installed.

Jet needs a service configuration file called codeship-service.yml. It looks almost the same as docker-compose.yml with a couple of exceptions (you can't use ports, for example).

Also, we need all the steps of our CI/CD workflow. You can define them in the codeship-steps.yml. Ours is as simple as a microservice should be.

The codeship-steps.yml configuration:

You can see two steps: one for the test and the second (after the test is green) to tell to redeploy the code in production.

Ready to rock? Run the test suite using the Jet CLI to test if it works with Codeship:

jet steps

When the test hits green, we're ready to begin the real magic. Follow the steps for creating a project on the Codeship Docker Infrastructure and automagically, a GitHub webhook triggers the tests.

If we edit some code, run the tests:

docker-compose run test

Push the code changes to Git, and our test will run on the Codeship Docker Infrastructure. This is the expected Codeship output:

But wait! You bragged about running this thing in production. So let's throw in some more magic. Check the last step called notifier.

Run Meteor in Production

If you're not familiar with Cloud 66, it's a service that simplifies Ops for developers by building, configuring, and managing your servers on any cloud. Our Node support provides a complete toolset for rolling out Node applications to production on your own infrastructure.

Creating a Meteor Cluster

Register with Cloud 66, dial in the credentials of your cloud provider of choice, and begin using the UI to start a Node stack. Pop in the Git repository, analyze it, and off you go! Grab a coffee and sit back to get those servers provisioned.

Adding the repo:

Select the cloud deployment:

Once Cloud 66 provisions your server(s) and your Node cluster is up and running, sit back and enjoy the view:

Scale to the Moon and Back

So you want to scale? Right then. You can scale vertically to add more Node servers to your cluster to scale horizontally and spawn more Meteor instances.

You're working hard on your Meteor app, so run the test (green! Yeah!) and tell Cloud 66 to redeploy the running services. Let's add a redeploy hook to Codeship and trigger that event at Cloud 66.

Hook Up Codeship to Cloud 66

We use the notifier service running during tests on Codeship. The notifier only runs one simple script:

curl -X POST -d "" ${CLOUD_66_REDEPLOY_HOOK}

The script needs an environment variable called CLOUD66REDEPLOY_HOOK. How do you get one?

Once you’ve deployed your stack with Cloud 66, you’ll see a Redeployment Hook URL on your Stack Information page. To trigger a new deployment via Codeship, simply use the example notifier service (based on the ultra-small alpine base image) to last project step.


With the integration of Codeship Pro and Cloud 66, you get a fast and easy-to-use Node workflow pipeline without having to worry about running Node in production. Let Codeship Pro take care of all the (integration) testing, and don't worry about your infrastructure. Cloud 66 makes Ops simple for Devs.

If you need some more help, remember that the webinar will guide you step-by-step and explain all the example code:

[vimeo 205262877 w=640 h=400]

Stay up to date

We'll never share your email address and you can opt out at any time, we promise.