Running forever script from Google Cloud Platform App Engine startup script - node.js

I have edited the startup-script variable for one of my instances running on the Google Cloud Platform App Engine. I'd like it to call a forever script to make sure my node app is running. So I added:
cd /opt/bitnami/apps/myapp
forever start --workingDir /opt/bitnami/apps/myapp/ --sourceDir /opt
/bitnami/apps/myapp/ app.js
after the #!/bin/bash line (also tried without the cd as it's not really necessary based on my command). But once the vm is started, running a forever list doesn't list my forever task as having ever started. If I copy and paste that forever command into a gcloud terminal and run, the task shows up fine and my app starts no problem.
Am I not calling this correctly somehow within the bash script?

The simple answer is that GAE does this by default. No need for forever or PM2. There are certain health checks that GAE does on the Docker container holding your app, and if they do not pass the instance is automatically restarted
If you want granular control over these checks (called Legacy Health Checks) you can add this to your app.yaml file:
health_check:
enable_health_check: True
check_interval_sec: 5
timeout_sec: 4
unhealthy_threshold: 2
healthy_threshold: 2
There is also updated mechanisms (called Updated Health Checks) that are still in beta, but can be used instead

The proper way to start your nodejs app on appengine is to specify the "scripts" field in your package.json, as the documentation
Below is an example borrowed from this sample
"scripts": {
"start": "node ./bin/www",
"test": "cd ..; npm run t -- appengine/analytics/test/*.test.js"
},
If you however, are only interested in running a node script, and not interested in the features that come with Google app engine, then you may simply run it on a Google Compute Engine instance.

Related

Integrating PM2 on Google Cloud app engine

I am trying to integrate PM2 to Google Cloud App Engine but I just couldn't work it around. I am using PM2 for my site's staging site and I am very impressed with it. I use Digital Ocean droplet for staging. I realized that Google Cloud App Engine is not that flexible.
This is my package.json:
"main": "server.js",
"scripts": {
"start": "NODE_ENV=production npm run server:prod",
"server:prod": "node server.js",
"server:stage": "NODE_ENV=stage pm2 start server.js --exp-backoff-restart-delay=100 -i max",
"dev": "nodemon server.js",
"gcp-deploy-stage": "gcloud app deploy app.backend.stage.yaml --project=xxxxx",
"gcp-deploy-prod": "gcloud app deploy app.backend.prod.yaml --project=xxxx -v=alpha-16"
},
When I set production script start as staging like this:
"server:prod":"pm2 start server.js --exp-backoff-restart-delay=100 -i max"
and deploy this Google Cloud App Engine normally crashes because there is no global PM2 installed via NPM to start PM2.
Is there anybody went through this and made it work? Or any piece of code or any documentation that could lead me to the right solution?
Or the only option is migrating this to Google Cloud Compute Engine?
Thank you for reading this and your help.
If you want to use any module, you're going to have to include it in your package.json. Have you tried running npm install --save-dev pm2, and then redeploying your site? My guess is, that's going to get you where you want to go.
All of that aside - this probably isn't a good idea :) pm2 does a lot to manage processes on the machine, specifically dealing with crashes. App Engine Flexible does a lot of this at the infrastructure layer, automatically looking at instance health. It uses docker under the hood, which has it's own restart strategy. And then on top of that, if the the docker retry strategy doesn't work, the Google Load Balancer kicks in and will start a new compute instance for you. It's entirely possible doing process level monitoring and restarting like this will work, I just want to make sure you understand everything else that's happening under the hood.
Curiosity killed the cat - why did you end up going with App Engine Flexible over App Engine Standard?

How to run a node app after production build by WebPack when output is index.html?

***Updated for further clarification:
Thanks much for taking the time to reply. Running 'npm run build' (I'm using the Vuetify/Webpack template) created an index.html and a directory named 'static' with the respective html, css, and js (in 'dist' directory). The question is - how can I run this in production using node or pm2 (for example, 'pm2 start myapp.js')?
Doing some further research and testing, the 'npm run build' built as static. It was my lack of understanding how vue-cli was to build for production (via WebPack) (vue-cli builds static meant to be served via web server). Doing further testing, I can load and bring up my app on a couple local Linux servers (the static content running on one servers, while MongoDB and API running on another server (API running with pm2)). Also, I was able to bring it up on AWS S3 (as static). I think I have my answer now. Thanks much for your time.
***From Original Post:
How to run the following node app in production? Webpack build produced an index.html (I assume as it's using html-webpack-plugin). I can view the site if I run under a web server (e.g., nginx), but I want to run my final app using pm2, or running node process.
I am using the Vuetify WebPack template (I'm using Vue.js), when I run the npm run build for production (in package.json: “build”: “node build/build.js”) the output is as follows:
$ ls
index.html static/
and
$ ls static/js/
app.f7301c212bc5fefd6563.js manifest.2ae2e69a05c33dfc65f8.js vendor.1aae36aa0dc798d4d36d.js
app.f7301c212bc5fefd6563.js.map manifest.2ae2e69a05c33dfc65f8.js.map vendor.1aae36aa0dc798d4d36d.js.map
So, how do I run this via node (npm start) or pm2 (pm2 start) (can't use index.html or static/js files).
When I run the webpack build I was expecting a .js output (for example ‘build.js’) to run via node or pm2 (npm start that runs ‘node build.js’ or pm2 start build.js). I suppose this will work for serverless, but was looking to run via pm2 (with nginx as proxy) as the app will have other factors (e.g., MongoDB) that won’t allow running in serverless (e.g., AWS Lambda).
Would this be a matter of just re-configuring WebPack to output to a .js file (for example, build.js), or will the static files (served via a webserver, nginx/Apache/http-server) allow for the same functionality? That is, will there be any factors that would limit my app by running as static verses via ‘node build.js’ or ‘pm2 start build.js’, (for example, will my API connects to the back-end still work (back-end being node/JS))?

Running Meteor Build under Node with settings argument

Typically when developing I would use meteor run --settings settings.json. This works fine and can view the settings in the browser with Meteor.settings on the console.
I am now build for production, using meteor build, I've looked at the documentation and there is nowhere to add settings during the build process.
So the build runs and I have my .tar.gz file, it's loaded to production and then I untar/compress the folder and run the start script.
It enters the program with npm start and the package.json section looks like this (ignore the stop script);
{
"name": "myapp",
"scripts": {
"start": "node main.js --settings settings.json",
"stop": "killall node"
}
}
When I look at my app it is not collecting these settings. It is as if when bundled it doesn't expect the arguements. I also tried using forever beforehand, but I had no joy with this either.
Any help would appreciated, start to wish I never bothered with Meteor :)
You can refer to Meteor Guide > Production > Deployment and Monitoring > Environment variables and Settings
Settings. These are in a JSON object set via either the --settings Meteor command-line flag or stringified into the METEOR_SETTINGS environment variable.
As for setting environment variables, if you use a 3rd party host, you may have a GUI or CLI to define them.
Otherwise, you should have plenty resources including on SO:
Node.js: Setting Environment Variables
How can I set an environmental variable in node.js?
https://themeteorchef.com/snippets/making-use-of-settings-json/
In short, it should look like:
METEOR_SETTINGS='{"key":"value"}' node main.js
You can also try the bash cat command to extract the content of a file: $(cat settings.json)

Redeploying NAR (node.js) archive with PM2

There is node.js app built with Typescript, so it needs to be first "compiled" to JS before it gets run. I'm planning to use NAR (https://github.com/h2non/nar) to build ready-to-deploy package to avoid fiddling with npm install and compiling it on production. I also use PM2 as process manager for node apps.
However as far as I know PM2 can only deploy from git (fetching sources and calling npm install etc. later on), but I couldnt find a way to easily deploy application that is already pre-built.
This is my deploy.yml file contained within archive that I extract with nar extract <package>:
apps:
- script: dist/app.js
merge_logs: true
name: server
instances: 1 # 0 => max, depending on CPU cores
exec_mode: cluster
node_args: --harmony --harmony_destructuring --harmony_default_parameters
log_file: deploy/logs/server.log
pid_file: deploy/pids/server.pid
source_map_support: true
env:
NODE_ENV: production
It works fine when run for the first time, but then when I try to redeploy it (replacing application content with new version) and call pm2 reload all I get errored processes saying they either cannot load ProcessManager from PM2 or cannot find my .env file (which is in place).
As soon as I kill PM2 daemon with pm2 kill and start apps again with pm2 start all deploy.yml it clicks. But this is probably not how PM2 should be used, right?
Do you have any experience with such setup and had similar issues? Or maybe can you point me to another way of running my deployment?

How to start nodejs application automatically on openwrt - Arduino Yun -

I am trying to have a nodejs application start automatically on system boot. Basically all I need is to run the command node /dir/app.
I am using openwrt on an Arduino Yun. And have tried a couple things.
On the openwrt website it said I can do this. https://wiki.openwrt.org/inbox/procd-init-scripts :
#!/bin/sh /etc/rc.common
USE_PROCD=1
start_service() {
procd_open_instance
procd_set_param command node ///www/www-blink.js
procd_close_instance
}
I have also tried changing the dir to /www/www-blink.js not ///
However i'm not sure what i'm doing wrong as nothing comes up when I try run it with /etc/init.d/node-app start I am obviously writing the code wrong but i'm not sure what it should exactly look like.
The other thing I have tried is the node modules forever and forever-service.
I downloaded them on my computer using npm install -g forever and forever-service aswell. I transfered them to usr/lib/node_modules on my arduino yun. However when I try to use and forever(-service) commands it says
-ash: forever: not found
I have tried a couple other things, however nothing has worked. Any help would be greatly appreciated.
-- I also need to be able to start my express script with npm start not node app but I guess the first thing is getting it to work at all.
you can put the starting command (node /dir/app &)in the /etc/rc.local script. This will start your nodejs application automatically on system boot.
OpenWRT procd has a "respawn" parameter, which will restart a service that exits or crashes.
# respawn automatically if something died, be careful if you have an
# alternative process supervisor if process dies sooner than respawn_threshold,
# it is considered crashed and after 5 retries the service is stopped
procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}
So, you cold just add:
procd_set_param respawn 60 5 5
or something like that to your OpenWRT procd initscript. This 60 5 5 means it will wait 5s between respawns (middle parameter), and if it respanws more than 5 times (last parameter) in 60s (first parameter), it will disable the service ("restart loop" detected).
Refer to this page for more information:
https://openwrt.org/docs/guide-developer/procd-init-scripts
You need to execute your node application like a Linux Service.
Upstart is perfect for this task
Upstart is an event-based replacement for the /sbin/init daemon which handles starting of tasks and services during boot, stopping them during shutdown and supervising them while the system is running.
If you have an app like this (for example):
// app.js
var express = require('express')
var app = express()
var port = process.env.PORT
app.get('/', function(req, res) {
res.send('Hello world!')
})
app.listen(port)
With a package.json like this:
{
"name": "my-awesome-app",
"version": "1.0.0",
"dependencies": {
"express": "^4.13.3"
},
"scripts": {
"start": "node app.js"
}
}
We create a upstart configuration file called myAwesomeApp.conf with the following code:
start on runlevel [2345]
stop on runlevel [!2345]
respawn
respawn limit 10 5
setuid ubuntu
chdir /opt/myAwesomeApp.conf
env PORT=3000
exec npm start
To finish, put your application (app.js and package.json) in the /opt/myAwesomeApp.conf and copy the configuration file myAwesomeApp.conf in /etc/init/
This is all, now you just need to run service myAwesomeApp start to run your node application as a service
I've never used procd before, but it likely needs the full path to node (e.g., /usr/bin/node). You'd need to make the line something like procd_set_param command /usr/bin/node /www/www-blink.js, assuming the file you want to run is /www/www-blink.js. You can locate node by running which node or type -a node.

Resources