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:
https://fast.wistia.com/embed/medias/hqyw84ryhe.jsonphttps://fast.wistia.com/assets/external/E-v1.js
Let's get started.
We Need a Plan!
Our plan follows this five-step approach:
Develop your Meteor app on your local dev machine.
Run your app in a staging environment on any cloud or bring your own server.
Run your tests using a CI/CD solution provided by Codeship.
Run your app in a production and scale.
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
wait.sh
script (start_test.sh
»).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 it...you'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:
#!/bin/bash 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.
Recap
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]