How do I handle multiple apps running on a single server? - node.js

I am new to Chef. I just finished creating a cookbook that deploys a node.js app, configures Nginx, and then starts the app as 1 or more workers that are "load balanced" by Nginx. It works great. I made sure to keep it pretty generic, and all the app level config is done via attributes.
Now I am trying to think about an instance where I have multiple node.js apps running on the same server. For example, the primary API app, and another app that registered itself as a Gearman worker.
How would I go about doing this? Would I simply create another cookbook that is specific to that app, make sure it includes the generic cookbook's recipe, and then do attribute overrides just for that app's recipe?
Or, would it be better if I moved away from using attributes for the app config, and used data_bags instead?
Any help is appreciated.

I would have separated nginx and node.js installation/configuration into separate cookbooks.
If you must have several different applications running on node.js, I think it's ok to add a recipe for every application inside node.js cookbook and make sure each of them includes installation of node.js itself.
If you must have several instances of 1 and the same application/service running, then it is better to use one recipe with different attributes or data bags to introduce differences among instances.
Any more specific questions?

You should use roles Roles to manage multiple cookbooks on a server.
I'm not exactly sure of your scenario, but from your description, I would create 3 cookbooks. One that installs nginx, one that installs your app, and one that does node specific configuration and deployment. Bundle these into a role 'app_server' and put the role in the run_list.
This makes your app more composable, and it's easier to change out any of the pieces in the future.

Related

What is the production deployment / runtime architecture of ResolveJS backend systems?

Does the reSolveJS generally run as a single NodeJS application on the server for production deployment?
Of course, event store and read models may be separate applications (e.g. databases) but are the CQRS read-side and write-side handled in the same NodeJS application?
If so, can / could these be split to enable them to scale separately, given the premise of CQRS is that the read-side is usually much more active than the write-side?
The reSolve Cloud Platform may alleviate these concerns, given the use of Lambdas that can scale naturally. Perhaps this is the recommended production deployment option?
That is, develop and test as monolith (single NodeJS application) and deploy in production to reSolve Cloud Platform to allow scaling?
Thanks again for developing and sharing an innovative platform.
Cheers,
Ashley.
reSolve app can be scaled as any other NodeJS app, using containers or any other scaling mechanisms.
So several instances can work with the same event store, and it is possible to configure several instances to work with the same read database, or for every instance to have its own read database.
reSolve config logic is specified in the app's run.js code, so you can extend it to have different configurations for different instance types.
Or you can have the same code in all instances and just route command and queries to the different instance pools.
Of course, reSolve Cloud frees you from these worries, in this case you use local reSolve as dev and test environment, and deploy there.
Please note that reSolve Cloud is not yet publicly released. Also, local reSolve can not have all required database adapters at the moment, so those yet to be written.

Use Google App Engine or Google Cloud Compute VM to Test Run My App?

I'm moving my Three.js app and its customized node.js environment, which I've been running on my local machine to Google Cloud. I want to test things out there, and hopefully soon get some early alpha testing going with other people.
I'm not sure which is the wiser way to go... to upload the repo I've been running locally as-is onto a VM which users would then access via the VM's external IP until I get a good name to call this app... or merge my local node.js environment with what's available via the Google App Engine and run it on GAE.
Issues I'm running into with the linux VM approach... I'm not sure how to do the equivalent on the VM of what I've been doing locally. In Windows Powershell I cd into the app directory and then enter node index.js. I'm assuming by this method of deployment that I can get the app running as soon as the browser hits the external IP. I should mention too that the app will allow users to save content as well as upload images, and eventually, 3D models as well as json datasets.
Issues I'm running into with the App Engine approach: it looks like I only have access to a linux-based command line, and have to install all the node.js modules manually. Meanwhile I have a bunch of files to upload, both the server-side node files and all the frontend stuff. I don't see where to upload those files, and ultimately what I'd like to do is have access to a visual, editable file-tree interface, as I have in Windows and FileZilla, so I can swap files in and out, etc. Alternatively I suppose I could import a repo from Github? Github would be fine as long as I can visually see what's happening. Is there a visual interface for file structure available in GAE somewhere? Am I missing something?
I went through the GAE "Hello World" tutorial and that worked fine, but was left scratching my head afterward regarding how to actually see and edit the guts of the tutorial app, or even where to look for the files.
So first off, I want to determine what's the better approach, and then if possible, determine how to make the experience of getting my app up there and running a more visual, user-friendly experience.
Thanks.
There are many things to consider when choosing how to run an app, but my instinct for your use case is to simply use a VM on GCE. The most compelling reason for this is that it's the most similar thing to what you have now. You can SSH into the machine and run nohup node index.js & (or node index.js inside tmux/screen if you prefer) and it will start the app and not stop it when you log out of SSH. You can use SCP / SFTP with whatever GUI client you want to upload files. You don't have to learn anything new! If you wanted to, you could even use a Windows VM (although I think you have to pay a little more than for a comparable Linux VM due to the licensing fees).
That said, the other way is arguably more "correct" by modern development standards, but it will involve a lot more learning that will prevent you from getting your app running somewhere other than your laptop in the short term:
First, you'll need to learn about Docker and stateless containers, which is basically what your app runs inside of on AppEngine.
Next, you'll need to learn how to hook up a separate stateful service (database, file server, ...) to your app's container so you can store your files, etc. in it, and then probably rewrite your app somewhat to use it to store stuff.
Next, you'll probably want some way to automatically deploy this from code instead of manually doing it, which gets you into build systems, package managers, artifact storage, continuous integration systems, and on and on and on.
This latter path is certainly what you should choose for a long-running production service if you work with a big team of developers -- but that doesn't mean that it's necessarily the right path for your project today. If you don't care about scaling up automatically, load balancing between nodes, redundant copies of your app running in different regions in case there's a natural disaster, etc., then go with the easy way for now, and you can learn new ways to improve the service when they're actually needed.

Forbid npm update in Docker environment

guys,
For various projects, I'm creating single Docker environments. Each Docker container consists of Debian, Nginx, Node.js, etc. and is going to use by developers as well as in production via Google Cloud's Kubernetes. Since the Node.js/module version should be everywhere the same, I would like to restrict the access to certain npm commands (somehow). Often developers work with different Node.js and project modules and that caused a lot of trouble in the past. With the Docker containers, I can provide environments with everything you need for a project. To finish this step, I would like to restrict the npm command execution and only allow arguments like install, test, etc.
Please drop me a comment if you know how to resolve this :)
Cheers
It is almost impossible to limit your developers to run some commands in the container if they have an access to Dockerfiles and can somehow change a build flow.
But, because container providing isolation and you can build a custom container for which application based on your basic image, it can be not a big problem if the version of any package for one application will be changed somehow, as an example in a build step, because it will not affect other apps. They just have different containers.
So, you will not have a problem with compatibility like when you using one server with many application which using a shared environment.
The only one thing you need to do - make sure that nobody change container which you using as a base image.

running nodejs app inside go

I have a requirement. Is there a way to run nodejs apps inside golang? I need to wrap the nodejs app inside a golang application and in the end to result a golang binary that starts the nodejs server and then to be able to call nodejs rest endpoints. I need to encapsulate in the golang binary the entire nodejs application with nodem_odules, if necessarily the nodejs runtime.
Well, you could make a Go program that includes e.g. a zipped Node application that it extracts and starts but it will be very hard to do well - you will have huge binaries, delays in extracting files, potential portability problems etc. Usually when you want to call REST endpoints then you host your Node app on some server and you let the client app (the Go app in your example) to connect to that Node app to work correctly. Advantages are that it is much faster, the app is much smaller, you don't have portability issues with Node binaries and addons and you can quickly update your backend any time you want.
It will be a very bad idea to embed a nodejs app into your golang, for various reasons such as: size, security updates pushing, etc.
However, if you so strong feel that they should be together, you could easily create a docker container with these two (a golang server + a node app) and launch them via docker. You can set the entrypoint to a supervisord daemon so that your node server as well as the golang server can be brought up when your container is run.
If you are planning to deploy via kubernetes you can create two individual docker containers (one for the golang server, one for the node server) but deploy them always together as a pod too.
There are multiple projects to embed binary files and/or file system data into your Go application.
Look at 'Alternatives' section of project 'vfsgen':
https://github.com/shurcooL/vfsgen#alternatives

Running and managing nodejs applications on single server

Is there a good way to run and manage multiple nodejs apps on a single server?
I've been looking at haibu and nodester, but they seem a little complex for what I am trying to do.
I also was looking at forever and I think that may work with the config file and web gui, but I am not sure how I am going to handle passing the port information via ENV or arguments.
I use Supervisord & Monit, more details and configuration example here: Process Management at Bringr.
Moreover you can specify environnement variable directly from the supervisord configuration file (see sub-process environment). But I personally prefer to add these variables directly inside a ~/.bashrc on each machine.
If the port number isn't going to change for each application (but change between production & development environment). I'll recommend to specify them inside a config.json (or directly inside package.json). And the config.json will contain a different port number for each application depending on the environnement:
{
myapp:{
production:{port:8080},
development:{port:3000}
}
}
And inside myapp.js:
var config = require('./config');
app.listen(config.myapp[process.env.NODE_ENV].port)
With process.env.NODE_ENV declared in ~/.bashrc.
I wrote an app nodegod that I use for a handful deployments of maybe 10 apps each.
nodegod reads an app list from json. It has an internal state machine for each app that handles the app life cycle in a safe manner including restarts, and the web page features stop/start/debug.
The web interface uses web sockets, so that you can manage remote servers over ssh.
As you deploy over rsync, apps restart automatically.
Because nodegod monitors the stdout of other apps, you can capture an app's final breath like segfault and malloc errors.
I use a fork of http-proxy in front of a slew of express instances, so any number of apps can share a single server port per dns for both http and web sockets.
I wrote a haraldops module to read app configuration from outside the source tree. With that you can monitor and get emails whenever something's up with an app.
App configurations I keep in a git repo in the file system.
It's not rocket science, and it all fits very nicely together. Only node and json: SIMPLE gets more done.
If your server has upstart, just use it. I have no luck with forever and similar.
If you want to proceed with upstart, roco would be nice as deployment solution:
roco deploy:setup:upstart
roco deploy
We're constantly trying to improve forever and haibu at Nodejitsu. Seems like the approach you're looking for here is a .forever configuration file for complex options. This feature has been on our backlog for a while now
https://github.com/nodejitsu/forever/issues/124
Check back. I consider it pretty high priority after the next round of performance improvements.
These days I've taken to using dokku which is a OSS clone of heroku. Deploying is as simple as making sure your package.json contains a start script. For example:
"scripts": {
"start": "node index.js"
}
Sample App

Resources