{"id":1364,"date":"2019-02-24T16:20:39","date_gmt":"2019-02-24T16:20:39","guid":{"rendered":"https:\/\/www.appservgrid.com\/paw93\/?p=1364"},"modified":"2019-03-07T20:28:13","modified_gmt":"2019-03-07T20:28:13","slug":"build-nodejs-app-using-mongodb-and-rancher","status":"publish","type":"post","link":"https:\/\/www.appservgrid.com\/paw93\/index.php\/2019\/02\/24\/build-nodejs-app-using-mongodb-and-rancher\/","title":{"rendered":"Build NodeJS App Using MongoDB and Rancher"},"content":{"rendered":"<p>In the <a href=\"http:\/\/rancher.com\/building-a-nodejs-app-using-mongodb-and-rancher-part-1\/\">first part of<br \/>\nthis post<\/a>,<br \/>\nI created a full Node.js application stack using MongoDB as the<br \/>\napplication\u2019s database and Nginx as a load balancer that distributed<br \/>\nincoming requests to two Node.js application servers. I created the<br \/>\nenvironment on Rancher and using Docker containers.<\/p>\n<p>In this post I will go through setting up Rancher authentication with<br \/>\nGitHub, and creating a webhook with GitHub for automatic<br \/>\ndeployments.<\/p>\n<h2>[]Rancher Access Control<\/h2>\n<p>Starting from version 0.5, Rancher can be configured to restrict<br \/>\naccess to a set of GitHub users and organization members (you can read a<br \/>\nblog about it<br \/>\n<a href=\"http:\/\/rancher.com\/rancher-now-supports-github-oauth\/\">here<\/a>).<br \/>\nUsing this feature ensures that no one other than authorized users can<br \/>\naccess Rancher server through the web UI.<\/p>\n<p>After setting up the rancher server, you should see message that says<br \/>\n\u201cAccess Control is not configured\u201d :<\/p>\n<p><a href=\"http:\/\/cdn.rancher.com\/wp-content\/uploads\/2015\/03\/10145411\/Raccesscontrol.png\"><img decoding=\"async\" src=\"http:\/\/cdn.rancher.com\/wp-content\/uploads\/2015\/03\/10145411\/Raccesscontrol-300x58.png\" alt=\"Raccesscontrol\" \/><\/a><\/p>\n<p>Click on settings and on the Access Control panel you will be<br \/>\ninstructed on how to setup and register new application with GitHub. The<br \/>\ninstructions will provide you with a<br \/>\n<a href=\"https:\/\/github.com\/settings\/applications\">link<\/a> to GitHub application settings.<\/p>\n<p>Now on GitHub Application Settings page, click on Register new<br \/>\napplication:<\/p>\n<p><a href=\"http:\/\/cdn.rancher.com\/wp-content\/uploads\/2015\/03\/10145411\/R2.png\"><img decoding=\"async\" src=\"http:\/\/cdn.rancher.com\/wp-content\/uploads\/2015\/03\/10145411\/R2.png\" alt=\"Auth_1\" \/><\/a><\/p>\n<p>Now you will put some information about Rancher\u2019s server:<\/p>\n<p>Application name: any name you choose<\/p>\n<p>Homepage URL: Rancher server url<\/p>\n<p>Application description: any description<\/p>\n<p>Authorization callback URL: also Rancher server url.<\/p>\n<p><a href=\"http:\/\/cdn.rancher.com\/wp-content\/uploads\/2015\/03\/10145411\/R3.png\"><img decoding=\"async\" src=\"http:\/\/cdn.rancher.com\/wp-content\/uploads\/2015\/03\/10145411\/R3.png\" alt=\"Auth_2\" \/><\/a><\/p>\n<p>After clicking on Register Application, you will be provided with<br \/>\na Client ID and Client Secret, which are both used to register the user<br \/>\nto the Rancher server:<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/cdn.rancher.com\/wp-content\/uploads\/2015\/03\/10145411\/R4.png\" alt=\"Auth_3\" \/><\/p>\n<p>Now add the Client ID and Client Secret to the Rancher management<br \/>\nserver, click on Authenticate with Github:<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/cdn.rancher.com\/wp-content\/uploads\/2015\/03\/10145411\/R5.png\" alt=\"Auth_4\" \/><\/p>\n<p>If everything went well, you should see something like the<br \/>\nfollowing:<\/p>\n<p><a href=\"http:\/\/cdn.rancher.com\/wp-content\/uploads\/2015\/03\/10145411\/R6.png\"><img decoding=\"async\" src=\"http:\/\/cdn.rancher.com\/wp-content\/uploads\/2015\/03\/10145411\/R6.png\" alt=\"Auth_6\" \/><\/a><\/p>\n<p>Now you have authorized a GitHub user account to your Rancher<br \/>\nmanagement server, and can start adding users and organizations from<br \/>\nGitHub to Rancher projects.<\/p>\n<h2>[]Automatic Deployment Using Webhooks<\/h2>\n<p>Webhooks can provide an efficient way for changing the application\u2019s<br \/>\ncontent using HTTP callbacks for specific events, in this configuration<br \/>\nI will register a couple of webhooks with GitHub to send a POST request<br \/>\nto a custom URL.<\/p>\n<p>There are a number of ways to create an automatic deployment setup for<br \/>\nyour app, I decided to use the following approach:<\/p>\n<ul>\n<li>Create a webhook on Github for each push.<\/li>\n<li>Modify the Node.js Docker instances with:<\/li>\n<li>A webhook handler in Node.js. &#8211; A script that pulls the new<br \/>\npushed repo.<\/li>\n<li>Start the Application with Nodemon, supervisor, or PM2 to restart on<br \/>\neach modification.<\/li>\n<li>Start the Handler with any port, and proxy this port to the<br \/>\ncorresponding port of the host machine.<\/li>\n<\/ul>\n<p><a href=\"http:\/\/cdn.rancher.com\/wp-content\/uploads\/2015\/03\/10145411\/R7.png\"><img decoding=\"async\" src=\"http:\/\/cdn.rancher.com\/wp-content\/uploads\/2015\/03\/10145411\/R7.png\" alt=\"WebHooks\nModel\" \/><\/a><\/p>\n<p>Let\u2019s go through our solution in more detail:<\/p>\n<h3>The new Node.js Application Container<\/h3>\n<p>First we need to modify the Node.js Docker image which i created in the<br \/>\nfirst post. Now it has to contain the Hook handler program plus the<br \/>\nre-deploy script, also we should start the main application using<br \/>\nNodemon, the new Dockerfile:<\/p>\n<p># Dockerfile For Node.js App<br \/>\nFROM ubuntu:14.04<br \/>\nMAINTAINER hussein.galal.ahmed.11@gmail.com<br \/>\nENV CACHED_FLAG 1<\/p>\n<p># Install node and npm<br \/>\nRUN apt-get update -qq &amp;&amp; apt-get -y upgrade<br \/>\nRUN apt-get install -yqq nodejs npm git git-core<\/p>\n<p># Install nodemon<br \/>\nRUN npm install -g nodemon<br \/>\nVOLUME [ &#8220;\/var\/www\/nodeapp&#8221; ]<\/p>\n<p># Add redeploy script and hook handler<br \/>\nADD .\/run.sh \/tmp\/run.sh<br \/>\nADD .\/redeploy.sh \/tmp\/redeploy.sh<br \/>\nADD .\/webhook.js \/tmp\/webhook.js<br \/>\nWORKDIR \/var\/www\/nodeapp<br \/>\n# Expose both ports (app port and the hook handler port)<br \/>\nEXPOSE 8000<br \/>\nEXPOSE 9000<\/p>\n<p># Run The App<br \/>\nENTRYPOINT [&#8220;\/b2in\/bash&#8221;, &#8220;\/tmp\/run.sh&#8221;]<\/p>\n<p>You should notice that a two new files were added to this Dockerfile:<br \/>\nthe webhook.js which is the hook handler, and redeploy.sh script which<br \/>\nis basically a git pull from the GitHub repo.<\/p>\n<h3>The webhook.js handler<\/h3>\n<p>I wrote the webhook handle in NodeJS:<\/p>\n<p>var http = require(&#8216;http&#8217;)<br \/>\nvar createHandler = require(&#8216;github-webhook-handler&#8217;)<br \/>\nvar handler = createHandler({ path: &#8216;\/&#8217;, secret: &#8216;secret&#8217; })<br \/>\nvar execFile = require(&#8216;child_process&#8217;).execFile;<br \/>\n\/\/Create Server That Listen On Port 9000<br \/>\nhttp.createServer(function (req, res) {<br \/>\nhandler(req, res, function (err) {<br \/>\nres.statusCode = 404<br \/>\nres.end(&#8216;no such location&#8217;)<br \/>\n})<br \/>\n}).listen(9000)<\/p>\n<p>\/\/Hook Handler on Error<br \/>\nhandler.on(&#8216;error&#8217;, function (err) {<br \/>\nconsole.error(&#8216;Error:&#8217;, err.message)<br \/>\n})<\/p>\n<p>\/\/Hook Handler on Push<br \/>\nhandler.on(&#8216;push&#8217;, function (event) {<br \/>\nconsole.log(&#8216;Received a push event for %s to %s&#8217;,<br \/>\nevent.payload.repository.name,<br \/>\nevent.payload.ref)<br \/>\nexecFile(&#8216;\/tmp\/redeploy.sh&#8217;, function(error, stdout, stderr) {<br \/>\nconsole.log(&#8216;Error: &#8216;+error)<br \/>\nconsole.log( &#8216;Redeploy Completed&#8217; );<br \/>\n});<br \/>\n})<\/p>\n<p>I won\u2019t go into the details of the code, but here are some notes that<br \/>\nyou should consider:<\/p>\n<ul>\n<li>I used<br \/>\n<a href=\"https:\/\/github.com\/rvagg\/github-webhook-handler\">github-webhook-handler<\/a> library.<\/li>\n<li>The handler will use a secret string that will be configured later<br \/>\nusing GitHub.<\/li>\n<li>The handler will listen on port 9000.<\/li>\n<li>The handler will execute redeploy.sh.<\/li>\n<\/ul>\n<p>The redeploy.sh script:<\/p>\n<p>sleep 5<br \/>\ncd \/var\/www\/nodeapp<br \/>\ngit pull<\/p>\n<p>The last script is the run script which used to start the handler and<br \/>\nthe application:<\/p>\n<p>MONGO_DN=mongo<br \/>\nif [ -n &#8220;$MONGO_IP&#8221; ]<br \/>\nthen<br \/>\necho &#8220;$MONGO_IP $MONGO_DN&#8221; &gt;&gt; \/etc\/hosts<br \/>\nfi<br \/>\nln -s \/usr\/bin\/nodejs \/usr\/bin\/node<br \/>\nchmod a+x \/tmp\/redeploy.sh<\/p>\n<p>#fetch the app<br \/>\ngit clone https:\/\/github.com\/galal-hussein\/hitcntr-nodejs.git .<br \/>\ncd \/tmp<br \/>\nnpm install github-webhook-handler<br \/>\nnodejs webhook.js &amp;<\/p>\n<p># Run the Application<br \/>\ncd \/var\/www\/nodeapp<br \/>\nnodemon index.js<\/p>\n<p>Now build and push the image like I did in the previous post.<\/p>\n<h3>Add Webhook With Github<\/h3>\n<p>To create a webhook on Github, open the repository \u2192 settings \u2192<br \/>\nWebhooks &amp; Services then Add Webhook:<\/p>\n<p><a href=\"http:\/\/cdn.rancher.com\/wp-content\/uploads\/2015\/03\/10145411\/hooks1.png\"><img decoding=\"async\" src=\"http:\/\/cdn.rancher.com\/wp-content\/uploads\/2015\/03\/10145411\/hooks1.png\" alt=\"hooks_1\" \/><\/a><\/p>\n<p>Now add a custom url which will be notified when the specified events<br \/>\nhappen:<\/p>\n<p><a href=\"http:\/\/cdn.rancher.com\/wp-content\/uploads\/2015\/03\/10145411\/hooks3.png\"><img decoding=\"async\" src=\"http:\/\/cdn.rancher.com\/wp-content\/uploads\/2015\/03\/10145411\/hooks3.png\" alt=\"hooks_3\" \/><\/a><\/p>\n<p>You should add the secret token which we specified previously in the<br \/>\nhandler\u2019s code. Add a second webhook but this time with the url of<br \/>\nthe second application, then build the application stack like we did in<br \/>\nthe previous post, but this time proxy port 9000 at the Node container:<\/p>\n<p><a href=\"http:\/\/cdn.rancher.com\/wp-content\/uploads\/2015\/03\/10145411\/hooks35.png\"><img decoding=\"async\" src=\"http:\/\/cdn.rancher.com\/wp-content\/uploads\/2015\/03\/10145411\/hooks35.png\" alt=\"hooks35\" \/><\/a><\/p>\n<p>After building the stack check the Github webhooks, and you should see<br \/>\nsomething like this:<\/p>\n<p><a href=\"http:\/\/cdn.rancher.com\/wp-content\/uploads\/2015\/03\/10145411\/hooks4.png\"><img decoding=\"async\" src=\"http:\/\/cdn.rancher.com\/wp-content\/uploads\/2015\/03\/10145411\/hooks4.png\" alt=\"hooks_4\" \/><\/a><\/p>\n<p>Now let\u2019s test the webhooks, if you accessed the url of the Nginx web<br \/>\nserver you will see something like this:<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/cdn.rancher.com\/wp-content\/uploads\/2015\/03\/10145411\/hooks5.png\" alt=\"hooks5\" \/><\/p>\n<p>Now commit any changes to your code and push it on Github, and the<br \/>\nchanges will be applied immediately to the app servers, in our case I<br \/>\nchanged the \u201chits\u201d to be \u201cWebhooks Worked, Hits\u201d:<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/cdn.rancher.com\/wp-content\/uploads\/2015\/03\/10145411\/hooks6.png\" alt=\"hooks6\" \/><\/p>\n<h2>Conclusion<\/h2>\n<p>In this two post series, I created a simple Node.js application with<br \/>\nMongoDB as a NoSQL database and used Rancher to build the whole stack<br \/>\nwith Docker containers. In the second post I used the authentication<br \/>\nfeature of Rancher with GitHub accounts, then I used webhooks to build<br \/>\nan automatic deployment solution.<\/p>\n<p>I hope this helps you understand how to leverage Rancher, Docker and<br \/>\nGitHub to better manage application deployments.<\/p>\n<p>If you\u2019d like to learn more about using Rancher, please don\u2019t hesitate<br \/>\nto schedule a demo and discussion with one of our<br \/>\nengineers.<\/p>\n<p><a href=\"https:\/\/rancher.com\/nodejs-mongodb-application-with-rancher-part-2\/\" target=\"_blank\" rel=\"noopener\">Source<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the first part of this post, I created a full Node.js application stack using MongoDB as the application\u2019s database and Nginx as a load balancer that distributed incoming requests to two Node.js application servers. I created the environment on Rancher and using Docker containers. In this post I will go through setting up Rancher &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.appservgrid.com\/paw93\/index.php\/2019\/02\/24\/build-nodejs-app-using-mongodb-and-rancher\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Build NodeJS App Using MongoDB and Rancher&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-1364","post","type-post","status-publish","format-standard","hentry","category-kubernetes"],"_links":{"self":[{"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/posts\/1364","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/comments?post=1364"}],"version-history":[{"count":1,"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/posts\/1364\/revisions"}],"predecessor-version":[{"id":1441,"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/posts\/1364\/revisions\/1441"}],"wp:attachment":[{"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/media?parent=1364"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/categories?post=1364"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/tags?post=1364"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}