How to containerize a NodeJS app with cron jobs using Docker? - node.js

I have a NodeJS app consisting of a REST API and an overnight maintenance (cron) job. Currently running on Debian Linux.
What is the best practice do Dockerize it?
I can use the official "node" Docker image, however that doesn't contain a crontab.
I can use the official "alpine" Docker image (and install NodeJS in it) however I lose the possibility of upgrading NodeJS with the easy of pulling a new version of the official image.
What is the best way to achieve this?

Solution #1
Use a node cron package. I added some code example from a real project. Every hour I scrape a website. You can set time and place your recurring task inside cron.schedule. You can use it a separate project or combine with your api code.
import { Scraper } from './controller/scraper.js';
import cron from 'node-cron'
cron.schedule('0 0 */1 * * *', () => {
console.log('running a task every hour');
const scraper = new Scraper()
const data = scraper.getData()
});
Solution #2
Docker official website doesn't advice running process managers with containers. But you can use if you need. I use pm2 as a process manager. It can be used for running an app for some intervals and it can restart your app if it crashes.
Links that will help you:
https://pm2.keymetrics.io/
https://pm2.keymetrics.io/docs/usage/docker-pm2-nodejs/
My use case:
Restart app if it crashes.
Run app.js file for each hour.

Use official nodejs docker image and build docker image with your code.
You need to run two containers, one for Rest API and other for cron job.
For cron job you dont need conrtab inside the docker image but schedule the image run on the host machine like below:
This will ensure to run docker image at required interval.
crontab -e
* */2 * * * docker run -it app/cron-image:v1

Related

How to build docker image without having to use the sudo keyword

I'm building a node.js app which allows people to run code on my server and I'm using Docker to containerise the user's code so that it can't steal data or in general do something they shouldn't. I have a Docker image template that is copied into the user's personal app directory and I want to build the image using this function I've written:
const util = require("util");
const exec = util.promisify(require("child_process").exec);
async function buildContainer(path, dockerUser) {
return await exec(`sudo docker build -t user_app_${dockerUser} ${path}`);
}
However when I go to use it, it requires me to enter my sudo password as if I was executing it manually in a terminal window.
Is there anyway I can run this function without having to include the sudo keyword?
Thanks in advance.
you can use podman instead of docker.
There you donĀ“t need sudo.
You have the most commands like docker.
example:
podman build
podman run
and so on...
hope that helps :)
Regards

Add a job to linux cron list programmatically with Nodejs

I have a job with Nodejs that I want to do it each 30 minutes to scan the Database and Update Products Data in An Ecommerce API with my Nodejs Program, note that the Nodejs Program is serving an REST API (Backend) for a react js web application
So I searched for that and I found that I can do that with Nodejs Cron Library like "node-schedule" but I know that will be more interesting to do it with Linux Cron
var j = schedule.scheduleJob('42 * * * *', function(){
console.log('The answer to life, the universe, and everything!');
});
Is there any library that can let me add Cron jobs to Linux using Nodejs Or would I do it with "fs" only? so I will open the cron job file and add my command?
The command crontab which is part of Vixie Cron allows you to create, edit and delete per-user cron entries.
Or if you are running as the root user, which you should not be doing, you can drop cron files into /etc/cron.d
This is not always supported, and if you're running in a Docker type container environment it is doubtful that you have any cron at all. In that environment you'd want your running Nodejs to handle scheduled jobs for you. Or use some other kind of distributed scheduled work system.
You can put your cron job to a nodejs script. Then adding to the crontab can be done with cronbee module, via API:
import { cronbee } from 'cronbee'
await cronbee.ensure({
taskName: 'do smth',
taskRun: `node my-script`,
cron: '42 * * * *'
})
or you can ensure the cron job via CLI, if the module is installed globally or from npm scripts:
$ cronbee ensure mytasks.json

how to run windows service automatically using nodejs application? [duplicate]

Can any node.js experts tell me how I might configure node JS to autostart a server when my machine boots?
I'm on Windows
This isn't something to configure in node.js at all, this is purely OS responsibility (Windows in your case). The most reliable way to achieve this is through a Windows Service.
There's this super easy module that installs a node script as a windows service, it's called node-windows (npm, github, documentation). I've used before and worked like a charm.
var Service = require('node-windows').Service;
// Create a new service object
var svc = new Service({
name:'Hello World',
description: 'The nodejs.org example web server.',
script: 'C:\\path\\to\\helloworld.js'
});
// Listen for the "install" event, which indicates the
// process is available as a service.
svc.on('install',function(){
svc.start();
});
svc.install();
p.s.
I found the thing so useful that I built an even easier to use wrapper around it (npm, github).
Installing it:
npm install -g qckwinsvc
Installing your service:
> qckwinsvc
prompt: Service name: [name for your service]
prompt: Service description: [description for it]
prompt: Node script path: [path of your node script]
Service installed
Uninstalling your service:
> qckwinsvc --uninstall
prompt: Service name: [name of your service]
prompt: Node script path: [path of your node script]
Service stopped
Service uninstalled
If you are using Linux, macOS or Windows pm2 is your friend. It's a process manager that handle clusters very well.
You install it:
npm install -g pm2
Start a cluster of, for example, 3 processes:
pm2 start app.js -i 3
And make pm2 starts them at boot:
pm2 startup
It has an API, an even a monitor interface:
Go to github and read the instructions. It's easy to use and very handy. Best thing ever since forever.
If I'm not wrong, you can start your application using command line and thus also using a batch file. In that case it is not a very hard task to start it with Windows login.
You just create a batch file with the following content:
node C:\myapp.js
and save it with .bat extention. Here myapp.js is your app, which in this example is located in C: drive (spcify the path).
Now you can just throw the batch file in your startup folder which is located at C:\Users\%username%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
Just open it using %appdata% in run dailog box and locate to >Roaming>Microsoft>Windows>Start Menu>Programs>Startup
The batch file will be executed at login time and start your node application from cmd.
This can easily be done manually with the Windows Task Scheduler.
First, install forever.
Then, create a batch file that contains the following:
cd C:\path\to\project\root
call C:\Users\Username\AppData\Roaming\npm\forever.cmd start server.js
exit 0
Lastly, create a scheduled task that runs when you log on. This task should call the batch file.
I would recommend installing your node.js app as a Windows service, and then set the service to run at startup. That should make it a bit easier to control the startup action by using the Windows Services snapin rather than having to add or remove batch files in the Startup folder.
Another service-related question in Stackoverflow provided a couple of (apprently) really good options. Check out How to install node.js as a Windows Service. node-windows looks really promising to me. As an aside, I used similar tools for Java apps that needed to run as services. It made my life a whole lot easier. Hope this helps.
you should try this
npm forever
https://www.npmjs.com/package/forever
Use pm2 to start and run your nodejs processes on windows.
Be sure to read this github discussion of how to set up task scheduler to start pm2: https://github.com/Unitech/pm2/issues/1079
Here is another solution I wrote in C# to auto startup native node server or pm2 server on Windows.
I know there are multiple ways to achieve this as per solutions shared above. I haven't tried all of them but some third party services lack clarity around what are all tasks being run in the background. I have achieved this through a powershell script similar to the one mentioned as windows batch file. I have scheduled it using Windows Tasks Scheduler to run every minute. This has been quite efficient and transparent so far. The advantage I have here is that I am checking the process explicitly before starting it again. This wouldn't cause much overhead to the CPU on the server. Also you don't have to explicitly place the file into the startup folders.
function CheckNodeService ()
{
$node = Get-Process node -ErrorAction SilentlyContinue
if($node)
{
echo 'Node Running'
}
else
{
echo 'Node not Running'
Start-Process "C:\Program Files\nodejs\node.exe" -ArgumentList "app.js" -WorkingDirectory "E:\MyApplication"
echo 'Node started'
}
}
CheckNodeService
Simply use this, install, run and save current process list
https://www.npmjs.com/package/pm2-windows-startup
By my exp., after restart server, need to logon, in order to trigger the auto startup.
Need to create a batch file inside project folder.
Write this code in batch file
#echo off
start npm start
save batch file with myprojectname.bat
Go to run command and press window + R
Enter this command :- shell:common startup
Press ok then folder will be open.
Folder path like as C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp
You will be paste your myprojectname.bat file.
You can check also. Need to system restart.
Copied directly from this answer:
You could write a script in any language you want to automate this (even using nodejs) and then just install a shortcut to that script in the user's %appdata%\Microsoft\Windows\Start Menu\Programs\Startup folder

How to run a nodejs script every second

I need to run my nodejs script for every second ,Similar to PHP cron jobs. I have tried some nodejs cron libraries like https://github.com/ncb000gt/node-cron but the issue was first run should be manual i:e I have to run the file with cron script for first time manually.
But in php cron jobs, they run by the server so if the apache server running script will automatically start and even if the script return an error for a cycle then script will run again from the beginning from the next cycle
So is there any way to achieve this in nodejs ?
You have two options:
using Node as a daemon, with something like Supervisord to run your node-cron script. This alternative is wasteful on resources such as RAM because Node and Supervisord are running all the time.
using the system's crontab, you can run your script like calling Node on the command line, such as * * * * node /path/to/your/script.js. This alternative is highly efficient but lacks some control, like being able to log the output in case of an error, although you could just pipe the output to a file: node script.js > logfile

Cannot run nodejs app and mongo within a docker container

I'm setting up a container with the following Dockerfile
# Start with project/baseline
FROM project/baseline # => image with mongo / nodejs / sailsjs
# Create folder that will contain all the sources
RUN mkdir -p /var/project
# Load the configuration file and the deployment script
ADD init.sh /var/project/init.sh
ADD src/ /var/project/ # src contains a list of folder, each one being a sails app
# Compile the sources / run the services / run mongodb
CMD /var/project/init.sh
The init.sh script is called when the container runs.
It should start a couple of webapp and mongodb.
#!/bin/bash
PROJECT_PATH=/var/project
# Start mongodb
function start_mongo {
mongod --fork --logpath /var/log/mongodb.log # attempt to have mongo running in daemon
}
# Start services
function start {
for service in $(ls);do
cd $PROJECT_PATH/$service
npm start # Runs sails lift on each service
done
}
# start mongodb
start_mongo
# start web applications defined in /var/project
start
Basically, there is a couple of nodejs (sailsjs) application in /var/project.
When I run the container, I got the following message:
$ sudo docker run -t -i projects/test
about to fork child process, waiting until server is ready for connections.
forked process: 10
and then it remains stuck.
How can mongo and the sails processes can be started and the container to remain in a running state ?
UPDATE
I now use this supervisord.conf file
[supervisord]
nodaemon=false
[program:mongodb]
command=/usr/bin/mongod
[program:process1]
command=/bin/bash "cd /var/project/service1 && node app.js"
[program:process2]
command=/bin/bash "cd /var/project/service2 && node app.js"
it is called in the Dockerfile like:
# run the applications (mongodb + project related services)
CMD ["/usr/bin/supervisord"]
As my services are dependent upon mongo starting correctly, supervisord does not wait that long and the services are not started then. Any idea to solve that ?
By the way, it that a so best practice to use mongo in the same container ?
UPDATE 2
I went back to a service.sh script that is called when the container is running. I know this is not clean (but I'll say it's temporary so I can fix the pb I have in supervisor), but I'm doing the following:
run nohup mongod &
wait 60 sec
run my node (forever) processes
The thing is, the container exit right after the forever processes are ran... how can it be kept active ?
If you want to cleanly start multiple services inside a container, one option is to use a process supervisor of some sort. One option is documented here, in the official Docker documentation.
I've done something similar using runit. You can see my base runit image here, and a multi-service application image using that here.

Resources