How to execute non-global npm binary in docker - node.js

Suppose I have following Dockerfile
WORKDIR $APP_DIR
ENTRYPOINT ["npm", "run"]
CMD ["start"]
The start is mapped to babel-node bin/server, where babel-node is a nodejs non-global dependency binary file (installed inside $APP_DIR/node_modules by default)
On my mac, without any set up, this works fine. But when I run it inside docker, it shows command not found, which is not surprise.
So the same command npm run start works on my host machine but inside Docker.
sh: 1: babel-node: not found
error Command failed with exit code 127.

you can try in this way: CMD [./node_modules/babel-node/bin/babel-node your app.js];
or try to use another way:
// you can rename this file to bin.js
const fs = require('fs');
const babelrc = fs.readFileSync('.babelrc', 'utf-8');
let config = {};
try {
config = JSON.parse(config);
} catch(err) {
console.error('==> ERROR: Error parsing your .babelrc.');
}
require("babel-polyfill");
require('babel-register')(config);
// then require your app.js
require('./app.js);
then you Dockerfile will be look like as follow:
...other codes
CMD [node bin.js]

Related

Selenium on a Docker container

I have a simple javascript file that uses selenium to launch Chrome, open some website, and collect some data from that website. Now, I want to put that file and run it inside a Docker container.
To do this I wrote the following Dockerfile:
FROM alpine
RUN apk add --update nodejs npm chromium
COPY . /src
WORKDIR /src
RUN npm install -g chromedriver
RUN npm install
ENTRYPOINT ["node", "index.js"]
The image builds with no errors, but when I attempt to run the container from it I get:
/src/node_modules/selenium-webdriver/remote/index.js:248
reject(Error(e.message))
^
Error: Server terminated early with status 1
at /src/node_modules/selenium-webdriver/remote/index.js:248:24
at processTicksAndRejections (node:internal/process/task_queues:96:5)
There's only one dependency for my index.js file - "selenium-webdriver": "^4.1.1", and the file itself looks like this:
index.js
const {Builder, By} = require('selenium-webdriver');
(async function example() {
let driver = await new Builder().forBrowser('chrome').build();
try {
// Navigate to Url
await driver.get('https://www.example.com');
// Get all the elements available with tag 'p'
let elements = await driver.findElements(By.css('p'));
for(let e of elements) {
console.log(await e.getText());
}
}
finally {
await driver.quit();
}
})();
What am I doing wrong? How can I make the container run successfully?
I think the problem is with selenium-webdriver/chrome,
since the builder is getting stuck on mine.

NPM and NodeJS Compatibility: NodeJS works from PM prompt, but not script

I am attempting to get a lighthouse script running in Node.JS (which I am new to). I followed the intial instructions here https://github.com/GoogleChrome/lighthouse/blob/master/docs/readme.md#using-programmatically. I was able to complete the prior steps in the package manager console (Visual Studio 2017):
npm install -g lighthouse
lighthouse https://airhorner.com/
//and
lighthouse https://airhorner.com/ --output=json --output-path=./report/test1.json
However, I do get an initial warning that NPM only supports Node.JS in versions 4 through 8 and recommends a newer version. The problem is I am running Node v12 and NPM v5 - both the latest.
When I create a script version like below (app.js)
const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');
const config = {
extends: 'lighthouse:default',
settings: {
emulatedFormFactor: 'desktop',
onlyCategories: 'performance',
output: 'json',
outputPath: './report.json'
}
};
function launchChromeAndRunLighthouse(url, opts = null, config) {
return chromeLauncher.launch().then(chrome => {
opts.port = chrome.port;
return lighthouse(url, opts, config).then(results => {
return chrome.kill().then(() => results.lhr);
});
});
}
// Usage:
launchChromeAndRunLighthouse('https://airhorner.com/', config).then(results => {
// Use results!
});
And run the command
C:\src\project> node app.js
I get the error - Cannot find module 'lighthouse'
don't install lighthouse locally use it inside your working dir .
first start by running npm init that will create the package.json file inside the current working dir
then npm install --save lighthouse will download it and save it to node_modules now you can use it locally inside your working dir
it should look something like this
app.js
package.json
node_modules/
then run node app.js

Passing an argument to npm run script

I am creating a script in npm package.json.
The script will run yeoman to scaffold my template and then I want to run a gulp task to do some more stuff to a specific file (inject using gulp-inject)
The npm task looks like this:
"scaffolt": "scaffolt -g scaffolt/generators template && gulp inject"
Now, i need to be able to call the command from the command line giving a name to my template.
The command I need to run is the following:
npm run scaffolt {templateName}
but if I do this, then I try to run a gulp task called the same as the typed {templateName}.
A quick example: If I run npm run scaffolt myTemplate then the second part of this will try to run a task called gulp myTemplate, failing.
Is there any way to pass the {myTemplate} name as an argument to the second part of the script so that it can be used in the gulptask?
The gulp task currently only console.log the process.argv.
You can pass arguments to the npm run-script. Here is the documentation.
Make gulp tasks for these operations.
//gulpfile.js
const gulp = require('gulp');
const commandLineArgs = require('command-line-args');
const spawn = require('child_process').spawn;
gulp.task('inject', ['scaffolt'], () => {
console.log('scaffolt complete!');
});
gulp.task('scaffolt', (cb) => {
const options = commandLineArgs([{ name: 'templateName' }]);
//use scaffolt.cmd on Windows!
spawn('scaffolt', ['-g', 'scaffolt/generators', options.templateName])
.on('close', cb);
});
And in your package
//package.json
"scripts": {
"scaffolt": "gulp inject "
}
And to run it npm run scaffolt -- --templateName=something
Tip: npm run-script appends node_modules/.bin directory in the PATH so we can spawn executables just like they are on the same folder!
You can use magical $npm_config_<exampleVarName> in script definition and then pass the value of it either from env variable named match exampleVarName or pass it in command line you add --exampleVarName=ValueHere
in your case
//package.json
"scripts": {
"scaffolt": "scaffolt -g scaffolt/generators $npm_config_templateName && gulp inject"
}
then run it as
npm run scaffolt --templateName=whatever

docker > run two nodejs scripts using gulp and nodemon

I'm trying whole day to find some solution how to run two scripts written in nodejs parallel in docker.
I've two files:
app/index.js - express app using port 8080
app/rabbit.js - script is connection to rabbitmq only as consumer and processing messages
I'm trying to use gulp and nodemon ( I've found solution on the stackoverflow, but id doesn't work )
var gulp = require('gulp')
var gulputil = require('gulp-util');
var child_process = require('child_process');
var nodemon = require('gulp-nodemon');
var processes = {server1: null, server2: null};
gulp.task('start:server', function (cb) {
processes.server1 = nodemon({
script: "app/index.js",
ext: "js"
});
processes.server2 = nodemon({
script: "app/rabbit.js",
ext: "js"
});
cb(); // For parallel execution accept a callback.
// For further info see "Async task support" section here:
// https://github.com/gulpjs/gulp/blob/master/docs/API.md
});
process.on('exit', function () {
// In case the gulp process is closed (e.g. by pressing [CTRL + C]) stop both processes
processes.server1.kill();
processes.server2.kill();
});
gulp.task('run', ['start:server']);
gulp.task('default', ['run']);
This is always runs second script "app/rabbit.js" twice. I'm open to any solution, but I need to run two nodejs script at once in one docker instance.
Any Ideas?
Thanks in advance!
For anyone who will have same problem, I've found solution.
Step 1:
Create two docker files Dockerfile-api, Dockerfile-messages
As command RUN in the dockerfile use
a. CMD ["npm", "run", "start-api"]
b. CMD ["npm", "run", "start-messages"]
Step 2:
In the package.json add lines:
"scripts": {
"start-api": "gulp --gulpfile app/gulpfile-api.js",
"start-messages": "gulp --gulpfile app/gulpfile-messages.js"
}
Step 3:
Obviously create two gulp files, each gulp file will have his own script.
Step 4:
Create two services in docker-compose.yml file each witch different DockerFile
Step 5:
Run docker-compose up

Run Node Package + Arguments from another script

I've found myself in a situation where I'm having to run a single command e.g. node compile.js
that .js file needs to run the following
browserify -t jadeify client/app.js -o bundle.js
All the dependencies are installed, and by running this command in the CLI works fine, just need to figure out how to execute it from within a node script.
We've also got inside our package.json the following which contains something similar to
"script" : [ "compile": "browserify -t jadeify client/app.js -o bundle.js" ]
this works perfectly when you execute cd /project && npm run compile via ssh however not via exec
Thanks
You should be able use the api-example and extend it with the transform as suggested by the jadeify setup paragraph.
var browserify = require('browserify');
var fs = require('fs');
var b = browserify();
b.add('./client/app.js');
// from jadeify docs
b.transform(require("jadeify"));
// simple demo outputs to stdout, this writes to a file just like your command line example.
b.bundle().pipe(fs.createWriteStream(__dirname + '/bundle.js'));
You can access script arguments via process.argv.
An array containing the command line arguments. The first element will be 'node', the second element will be the name of the JavaScript file. The next elements will be any additional command line arguments.
You can then use the browserify api together with jadeify to get what you need.
var browserify = require('browserify')();
var fs = require('fs');
var lang = process.argv[2];
console.log('Doing something with the lang value: ', lang);
browserify.add('./client/app.js');
browserify.transform(require("jadeify"));
browserify.bundle().pipe(fs.createWriteStream(__dirname + '/bundle.js'));
Run it with $ node compile.js enGB

Resources