How to test node heroku tasks in local environment - node.js

How do I test a heroku node task on my local machine using the heroku runtime environment (foreman?)
I can successfully run my task like so: node my_task.js. Now I need to (a) make it an executable in the bin directory, which will make it dependent on the location of the node binary on the system, and (b) I need this specific task to use environment variables defined in my .env file, which I can't mimic by just running it with node unless I hard code them, but that would defeat the purpose.
Is there a way to use foreman or heroku cli to run a task as it would be run in the heroku environment?

I spoke with Heroku support and figured this out. I didn't realize you can use foreman to run other processes:
foreman run node bin/my_task works for me. That way I can also keep the shebang node path as app/bin/node instead of having to switch it to usr/bin/node for my Ubuntu box.

Related

Check whether React application is running in a Docker container

For Node servers I am able to figure out whether they are running in a Docker container using the is-docker package. This obviously doesn't work for React applications which run in the browser rather than the command line which makes fs unavailable. Is there any other way to let a web application figure out whether it is running in a Docker container?
I noticed that create-react-app supports injecting environment variables into process.env during build time using .env files. Thus I created a .env.development file which contains REACT_APP_DOCKERENV=false and a .env.production file which contains REACT_APP_DOCKERENV=true. Those variables are then injected when running yarn start and yarn build respectively.
Of course this assumes my development builds are always executed locally while the production builds are always executed in Docker which works in my particular scenario.

deploying production mode with Vue-cli created project

Bit of a n00b question:
I created project with vue-cli using webpack.
On my windows machine I run "npm un dev" and I get a frontend server with HMR and so on.
Now I want to deploy my app to a production machine - ubuntu on DigitalOcean.
What are the steps I must take? I'm not very familiar with the logic of how it's supposed to work. If my ubuntu machine has NODE_ENV set to production, it won't install any of the devDependancies and i'm not able to build anything. So I guess I'll have to change that? If yes then it doesn't make any sense since it's a production machine.
And do I have to create another node/express server to serve index.html? Won't it supposed to work out-of-the-box somehow?
Thanks :)
TL;DR Build on your local machine and everything you need will be outputted in the ./dist/ directory, just copy the contents over to the webroot on your production server and you're good to go.
The webpack template handles most of the stuff for you.
Step you need to take to release:
Run npm run build on your local machine
Copy the contents of the generated ./dist/ directory to your server webroot
That's it!
When you run npm run build, the pre-configured build script sets the node environment to production, and builds with only the stuff that should be in production, it also optimizes the code and removes debug capabilities. When it comes to dependencies webpack takes care of that and includes them in the generated javascript files located in the ./dist/js/, so you need not concern yourself with copying over the node_modules/ directory either.
It also copies over everything in your static directory and src/assets directory to the ./dist/ directory to be prepare for a release. And resolves all the references to the new path generated by webpack.
The production server should not be concerned with building the vue app, run the build command on your local machine to keep dev dependencies away from your production server. I recommend against installing webpack and other dev tools on your production server. It just pollutes the server with things not needed there.
Some development tools could potentially produce alot of issues on production servers. So best practice is to never install them.
You could optionally create your own release script that uses ftp or rsync, whatver you prefer to copy everything in the ./dist/ directory to the production server webroot. This could be a script in bash, if on windows, run it in git bash or something similar for example.
Hope that cleared things up, congrats on your first vue release!

What is the correct way to handle the ecosystem deployment file in terms of version control and file system?

I have a ecosystem.json file for PM2 that handles apps, deployment, and environment variables. very similar to the example scripts on the deployment documentation page.
I'm curious about best practices involving storing this file in version control and on the server's file system; seeing as it contains things like password and keys.
I have considered ignoring it from version control, however doing that means the deployment PM2 process won't work. Deploying without the ecosystem file in the repository means the post deploy script won't find it as it wasn't cloned to the machine.
npm install && pm2 startOrRestart ecosystem.json --env production
This means I am now using a private repository and checking in the ecosystem file. Is it possible to have a public repository and still use pm2 deployment?
Finally what are the best practices about having the ecosystem file on the file system? It seems that PM2 requires that it be there.
My understanding of env variables was that only the running processes know about them. Is this a misunderstanding? Is a file containing sensitive env variables okay to be left in the application code directory?
Should I add another line to the post-deploy script to delete the ecosystem file after running the application? Would that cause problems with things like restarting the processes or anything else?
npm install && pm2 startOrRestart ecosystem.json --env production && rm ecosystem.json

Deploy NodeJS server on production server with grunt

I'm currently developing a web application with NodeJS.
Grunt is used for deployment and I used to run the server using following shell command.
NODE_ENV="development" grunt
This automatically merges, minifies and starts the node server.
On production server, I run following command to start the server in production environment.
NODE_ENV="production" grunt
This starts the server, but when I disconnect from the server (from ssh), it stops after sometime.
Is it possible to keep the NodeJS server running using grunt-deploy npm?
You will have to daemonize the node process. There are a lot of ways to do this and a lot of libraries out there that will handle this for you such as forever and pm2.
As for how you do this specifically, it depends on many factors like what grunt is actually doing, the availability of libraries, etc. etc. You could use grunt-forever to use forever within Grunt (this seems to be an old library, though).
PM2 also has documentation on deployments. You can update the script to be /path/to/grunt and pass the tasks to run as arguments.
The simplest solution may be to use
nohup NODE_ENV=production grunt &
...but this has not worked consistently for me in the past.

How to package & deploy Node.js + express web application?

I am new to Node.js programming and I have recently created a sample working web application using (express, backbone & other complimentary view technologies, with mongoDB). Now i am at a point where I want to deploy the same on a staging environment and I am not sure how to package this application and distribute the same. [I can take care of mongoDb and setting it up seperately]
I am from Java world and in there we create jars for reusable libs and war/ear packages for web applications which is deployed in a servlet container. Now in this case since node.js itself acts as a web container as well, how do i package my webapp?
Is there any standard format/guidelines of packaging node webapps built using express? (Is there a similar jar/war packaging systems for node apps?)
How do I deploy it once packaged? Would it become an exe, since it is also its own container?
PS: As of now I am thinking of just manually copying all the required source files into the staging environment and run npm commands to download all dependencies on that machine and then use 'forever' or some other mechanism to run my server.js. (Also, add some sort of monitoring, just in case app crashes and forever fails) I am not sure if that is the right way? I am sure there must be some standardized way of addressing this problem.
Deploying Node.js applications is very easy stuff. In maven, there is pom.xml. Related concept in Node.js is package.json. You can state your dependencies on package.json. You can also do environmental setup on package.json. For example, in dev environment you can say that
I want to run unit tests.
but in production;
I want to skip unit tests.
You have local repositories for maven under .m2 folder. In Node.js, there is node_modules folder under your Node.js project. You can see module folders with its name.
Let's come to the grunt part of this answer. Grunt is a task manager for your frontend assets, html, javascript, css. For example, before deployment you can minify html, css, javascript even images. You can also put grunt task run functions in package.json.
If you want to look at a sample application, you can find an example blog application here. Check folder structure and package.json for reference.
For deployment, I suggest you heroku deployment for startup applciations. You can find howto here. This is simple git based deployment.
On project running part, simply set your environment NODE_ENV=development and node app.js. Here app.js is in your project.
Here is relative concept for java and nodejs;
maven clean install => npm install
.m2 folder => node_modules(Under project folder)
mvn test => npm test(test section on package.json)
junit, powermock, ... => mocha, node-unit, ...
Spring MVC => Express.JS
pom.xml => package.json
import package => require('module_name')
There is no standardized way, but you're on the right track. If your package.json is up to date and well kept, you can just copy/zip/clone your app directory to the production system, excluding the node_modules.
On your production system, run
npm install to install your dependencies, npm test if you have tests and finally NODE_ENV=production node server.js
Some recent slides I considered to be quite helpful that also include the topic of wrappers like forever, can be found here.
Hope this might be helpful for somebody looking for the solution,Packaging of Node js apps can be done using "npm pack" command.It creates a zip file of your application which can be run in production/staging environment.
Is there any standard format/guidelines of packaging node webapps
built using express? (Is there a similar jar/war packaging systems for
node apps?)
Yes, the CommonJS Packages specification:
This specification describes the CommonJS package format for
distributing CommonJS programs and libraries. A CommonJS package is a
cohesive wrapping of a collection of modules, code and other assets
into a single form. It provides the basis for convenient delivery,
installation and management of CommonJS components.
For your next question:
2. How do I deploy it once packaged? Would it become an exe, since it is also its own container?
I second Hüseyin's suggestion to deploy on Heroku for production. For development and staging I use Node-Appliance with VirtualBox and Amazon EC2, respectively:
This program takes a Debian machine built by build-debian-cloud or
Debian-VirtualBox-Appliance and turns it into a Node.js "appliance",
capable of running a Node application deployed via git.
Your webapp will not become an exe.
few ways to approach this:
Push your code into Git repository, excluding everything that isn't your code (node_modules/**), then pull it in your staging environment, run npm install to restore all dependencies
create an NPM package out of it , install it via npm in your staging environment (this should also take care of all of the dependencies)
manual copy/ssh files to your staging environment (this can be automated with Grunt), than restore your dependencies via npm
I used zeit's pkg module. It can create cross platform deliverables for linux/win/macos. Actually used it in production and works fine without any issues.
It takes in all the js scripts and packages it into a single file.
The reason I used it is because it helps in securing your source code. That way in production at customers environment they will have access to application but not the source code.
Also one of the advantages is that at production environment, you do not actually need to have the customer install node.js as the node binaries also get packaged inside the build.
https://www.npmjs.com/package/pkg

Resources