I created a node.js (with express) application and have been unsucessfully trying to deploy to OpenShift from github. I am attempting to deploy from the web interface (providing the URL to the github repository root and "master" in the branch/tag field) and am getting an error I'm having trouble understanding:
The initial build for the application failed:
Shell command '/sbin/runuser -s /bin/sh 5724c3b42d5271363b000191 -c "exec /usr/bin/runcon 'unconfined_u:system_r:openshift_t:s0:c4,c687' /bin/sh -c \"gear postreceive --init >> /tmp/initial-build.log 2>&1\""' returned an error. rc=255 .
Last 10 kB of build output: Stopping NodeJS cartridge
Repairing links for 1 deployments
Building git ref 'master', commit a5ca0f7
Building NodeJS cartridge Preparing build for deployment
Deployment id is c2527992
Activating deployment
Starting NodeJS cartridge Sat Apr 30 2016 10:41:09 GMT-0400 (EDT):
Starting application 'profile' ...
Script = server.js
Script Args = Node Options = !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! It is highly recommended that you add a package.json file to your application. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Waiting for application port (8080) become available ...
Application 'profile' failed to start (port 8080 not available) -------------------------
Git Post-Receive Result: failure
Activation status: failure
Activation failed for the following gears: 5724c3b42d5271363b000191
(Error activating gear: CLIENT_ERROR: Failed to execute: 'control start' for /var/lib/openshift/5724c3b42d5271363b000191/nodejs #<IO:0x000000019b0298> #<IO:0x000000019b0220> )
Deployment completed with status: failure postreceive failed
I read a couple of posts about some errors above like port 8080 not available and failed to execute control start but the directives I was able to follow did not solve my issue. I am finding the line that says "using a package.json file is highly recommended" strange as I do have one. My package.json file is:
{
"name": "Portfolio_Memoria",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node server.js"
},
"main": "server.js",
"description": "Portfolio_Memoria",
"author": {
"name": "gorra",
"email": ""
},
"dependencies": {
"express": "~4.9.0",
"body-parser": "~1.8.1",
"cookie-parser": "~1.3.3",
"morgan": "~1.3.0",
"serve-favicon": "~2.1.3",
"debug": "~2.0.0",
"jade": "~1.6.0",
"stylus": "0.42.3"
}
}
And server.js file is:
#!/usr/bin/env node
var debug = require('debug')('Portfolio_Memoria');
var app = require('./app');
if(typeof process.env.OPENSHIFT_NODEJS_PORT === 'undefined'){
app.set('port', process.env.PORT || 3000);
var server = app.listen(app.get('port'), function() {
debug('Express server listening on port ' + server.address().port);
});
} else {
app.set('port', process.env.OPENSHIFT_NODEJS_PORT || 3000);
app.set('ip', process.env.OPENSHIFT_NODEJS_IP || '127.0.0.1');
var server = app.listen(app.get('port'), app.get('ip'), function() {
debug('Express server listening on port ' + server.address().port);
});
}
Of course, the application runs without issue locally. I don't know what I am missing here.
EDIT:
I got it to work by creating a blank application in OpenShift, cloning the repository OpenShift creates via command line, copying my whole project to it and pushing it back. This is a workaround and not a solution to the original problem, though.
Related
So I'm somewhat new to the whole web development thing with node.js and I'm wondering if someone could help me out with understanding how to implement my application correctly.
So the app is a simple landing page with an email form that takes an email and sends it to the API. I designed this functionality without issue except when I launched my website i'm getting a required not defined error.
I understand that this is because node.js is a server side technology so that when the application goes live, the client doesn't understand what required means.
Through further research, I figured out that I had two options and that's to either implement synchronous dependencies via something like Browserify or take things asynchronously and use something like RequireJS.
Right now I've decided on using Browserify, (unless someone can convince me otherwise) I just need help with figuring out how to implement it for my specific app.
app.js
//The dependenices my node js app needs (also where the require bug occurs)
//------------------------------------------------------------------------------------------------------------------------
const express = require('express'); //Require the express package that we installed with npm install express
const request = require('request'); //Require the express package that we installed with npm install request
const bodyParser = require('body-parser'); //Require the express package that we installed with npm install bodyParser
const path = require('path'); //Require the express package that we installed with npm install path
//------------------------------------------------------------------------------------------------------------------------
const app = express(); //Creates the application with express
//Middleware
app.use(express.json()); //Tells express to use JSON as it's input
app.use(bodyParser.urlencoded({ extended: false })); //Prevents XSS, only will return if the url has specified enconding
app.use(express.static(path.join(__dirname, '/site'))); //Tells the app to use the current path D:\Gaming Galaxy\Website\Website\main\site as the dir for the website
console.log("The directory used is", express.static(path.join(__dirname, '/site')));
app.post('/subscribe', (req, res) => { //Makes a post request to express req is the request and res is the response
const { email, js } = req.body; //Create a constant that makes up of the request's body
const mcData = { //Create a constant JSON object mcData, that contains the email from the above constant and a status message
members: [
{
email_address: email,
status: 'pending'
}
]
}
const mcDataPost = JSON.stringify(mcData); //Turns the JSON object into a string
const options = { //Sets a JSON object of a bunch of options that mailchimp will use
url: 'https://us20.api.mailchimp.com/3.0/lists/f10300bacb',
method: 'POST',
headers: {
Authorization: 'auth f24c3169da044653d1437842e39bece5-us20'
},
body: mcDataPost
}
if (email) { //If there's an email that exists
request(options, (err, response, body) => { //Send a request to mail chimp
if (err) { //If there's an error
res.json({ error: err }) //Print said error
} else { //If there's not an error
if (js) { //If javascript is enabled (boolean)
res.sendStatus(200); //Send a success message
} else {
res.redirect('/success.html'); //If it's disabled, send them to a successful HTML page.
}
}
})
} else {
res.status(404).send({ message: 'Failed' }) //If the email doesn't exist, have it fail
}
});
app.listen(5000, console.log('Server started!')) //Console log that confirms the start of the server
package.json
{
"name": "gaminggalaxy",
"version": "1.0.0",
"main": "site/js/app.js",
"dependencies": {
"body-parser": "^1.19.0",
"commonjs": "^0.0.1",
"express": "^4.17.1",
"index": "^0.4.0",
"node-fetch": "^2.6.6",
"prototype": "^0.0.5",
"request": "^2.65.0",
"requirejs": "^2.3.6",
"uniq": "^1.0.1"
},
"devDependencies": {
"nodemon": "^2.0.15"
},
"scripts": {
"serve": "node app",
"dev": "nodemon app"
},
"keywords": [],
"author": "",
"license": "ISC",
"repository": {
"type": "git",
"url": "git+https://github.com/InvertedTNT/Main.git"
},
"bugs": {
"url": "https://github.com/InvertedTNT/Main/issues"
},
"homepage": "https://github.com/InvertedTNT/Main#readme",
"description": ""
}
index.html (the form itself)
<form action="/subscribe" method="POST">
<div class="newsletter-form-grp">
<i class="far fa-envelope"></i>
<input type="email" name="email" id="email"
placeholder="Enter your email..." required>
</div>
<button id="cta">SUBSCRIBE <i class="fas fa-paper-plane"></i></button>
</form>
folder structure
node_modules
site
-index.html
-css
-js
- app.js
-images
app.js
package-lock.json
package.json
Thank you for your help, I would appreciate any sort of advice on how I can use those dependencies and the overall implementation of browserify.
A browser is an HTTP client.
Express is a framework for building HTTP servers.
HTTP clients make requests to HTTP servers which then send responses back.
Express depends on Node.js. It requires features provided by Node.js (like the ability to listen for network requests) which are not available in browsers.
Browserify can bundle up JavaScript which is written using modules into non-module code that can run in a browser but only if that code does not depend on Node.js-specific features. (i.e. if the JS modules are either pure JS or depend on browser-specific features).
Browserify cannot make Express run inside the browser.
When you run your JS program using Node.js you can then type the URL to the server the program creates into the browser’s address bar to connect to it.
I deployed an app on heroku, and I added the Puppeteer Heroku buildpack.
After a succesful redeployment, I tried to run it and it fails. Using heroku logs -t, I get this error message:
2018-09-07T13:16:10.870497+00:00 app[web.1]: Error: Failed to launch chrome!
2018-09-07T13:16:10.870512+00:00 app[web.1]: [0907/131610.045486:FATAL:zygote_ho
st_impl_linux.cc(116)] No usable sandbox! Update your kernel or see https://chro
mium.googlesource.com/chromium/src/+/master/docs/linux_suid_sandbox_development.
md for more information on developing with the SUID sandbox. If you want to live
dangerously and need an immediate workaround, you can try using --no-sandbox.
Here is what worked for me. First, I clear all my buildpacks and then I added the puppeteer-heroku-buildpack and the heroku/nodejs one:
$ heroku buildpacks:clear
$ heroku buildpacks:add --index 1 https://github.com/jontewks/puppeteer-heroku-buildpack
$ heroku buildpacks:add --index 1 heroku/nodejs
Then, add the following args to the puppeteer launch function:
const browser = await puppeteer.launch({
'args' : [
'--no-sandbox',
'--disable-setuid-sandbox'
]
});
Finally, deploy it back to Heroku:
$ git add .
$ git commit -m "Fixing deployment issue"
$ git push heroku master
You should be able to solve this issue by passing the --no-sandbox and --disable-setuid-sandbox flags to puppeteer.launch():
const browser = await puppeteer.launch({
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
],
});
If this does not work, you may want to read the official Puppeteer troubleshooting guide: Running Puppeteer on Heroku.
This answer is fantastic, but in the interests of a minimal, runnable example I thought I'd share my complete code and workflow for getting up and running with a Puppeteer-based web app.
See this answer for a simple scheduler and a clock process version (although all three approaches can coexist in one app without doing anything special).
package.json:
{
"name": "test-puppeteer",
"version": "1.0.0",
"description": "",
"scripts": {
"start": "node index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.17.1",
"puppeteer": "^9.1.1"
}
}
Procfile:
web: node index.js
index.js:
const express = require("express");
const puppeteer = require("puppeteer");
const app = express();
app.set("port", process.env.PORT || 5000);
const browserP = puppeteer.launch({
args: ["--no-sandbox", "--disable-setuid-sandbox"]
});
app.get("/", (req, res) => {
// FIXME move to a worker task; see https://devcenter.heroku.com/articles/node-redis-workers
let page;
(async () => {
page = await (await browserP).newPage();
await page.setContent(`<p>web running at ${Date()}</p>`);
res.send(await page.content());
})()
.catch(err => res.sendStatus(500))
.finally(() => page.close())
;
});
app.listen(app.get("port"), () =>
console.log("app running on port", app.get("port"))
);
Set up
Install Heroku CLI and create a new app with Node and Puppeteer buildpacks (see this answer):
heroku create
heroku buildpacks:add --index 1 https://github.com/jontewks/puppeteer-heroku-buildpack -a cryptic-dawn-48835
heroku buildpacks:add --index 1 heroku/nodejs -a cryptic-dawn-48835
(replace cryptic-dawn-48835 with your app name)
Deploy:
git init
git add .
git commit -m "initial commit"
heroku git:remote -a cryptic-dawn-48835
git push heroku master
Verify that it worked with curl https://cryptic-dawn-48835.herokuapp.com. You should see something like
<html><head></head><body><p>web running at Wed May 19 2021 02:12:48 GMT+0000 (Coordinated Universal Time)</p></body></html>
I have some issue with Visual studio code with Cluster
Edit
If I hit Ctrl + F5 it works correctly, what it's doing other than just F5, do I need to start command always with Ctrl?
---
It seems like workers never starts when started with VS Code Launch command (F5). Do I need to do some changes to .vscode/launch.json file to make Cluster work proberly.
Actual code is copied from Node.js 6 api https://nodejs.org/api/cluster.html#cluster_cluster
npm test Windows Command prompt shows this:
Master started
Listening port 80
Listening port 80
Listening port 80
Listening port 80
VS Code (F5) Debug Console show this:
node --debug-brk=7601 --nolazy index.js
Debugger listening on port 7601
Master started
Debugger listening on port 7602
Debugger listening on port 7603
Debugger listening on port 7604
Debugger listening on port 7605
VS Code launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "node",
"request": "launch",
"program": "${workspaceRoot}/index.js",
"stopOnEntry": false,
"args": [],
"cwd": "${workspaceRoot}",
..........
index.js
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
// Fork workers.
console.log('Master started')
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`worker ${worker.process.pid} died`);
});
} else {
// Workers can share any TCP connection
// In this case it is an HTTP server
http.createServer((req, res) => {
res.writeHead(200);
res.end('hello world\n');
}).listen(80);
console.log('Listening port 80')
}
I had the same issue. The 2nd workaround described by weinand in https://github.com/Microsoft/vscode/issues/3201 works for me:
Launch node from a terminal and attach to it with the VS Code
debugger.
Run in terminal: node --debug app.js
Then select the default 'attach' launch config and
attach to it.
The workaround is the preferred way if you actually want to debug any
worker and not just the first process that is launched.
I have the same problem on Visual studio code with Cluster.
I found that there are some dirty method to make it works.
Mac OS X:
/Applications/Visual Studio
Code.app/Contents/Resources/app/extensions/node-debug/out/node/nodeDebug.js
Windows:
C:\Program Files (x86)\Microsoft VS Code\resources\app\extensions\node-debug\out\node\nodeDebug.js
Change this
if (!this._noDebug) {
launchArgs.push("--debug-brk=" + port);
}
to
if (!this._noDebug) {
launchArgs.push("--debug=" + port);
}
I know it is not the best way to solve it, but it is working so far for me.
I'm building an openshift node js app which has to communicate with youtube data API. Its deployment is a success when I do "git push" with the require commented.
/*
var request = require('request');
*/
When I uncomment it, I get this error :
remote: Waiting for application port (8080) become available ...
remote: Application 'eln' failed to start (port 8080 not available)
remote: -------------------------
remote: Git Post-Receive Result: failure
remote: Activation status: failure
remote: Activation failed for the following gears:
remote: 573c3e177628e146d400004e (Error activating gear: CLIENT_ERROR: Failed to execute: 'control start' for /var/lib/openshift/573c3e177628e146d400004e/nodejs
Am I doing it bad? How can I fix it?
thank you.
Edit 1: Adding listening code, I didn't modify it (it was already here when I've created the app).
self.ipaddress = process.env.OPENSHIFT_NODEJS_IP;
self.port = process.env.OPENSHIFT_NODEJS_PORT || 8080;
/**
* Start the server (starts up the sample application).
*/
self.start = function()
{
// Start the app on the specific interface (and port).
self.app.listen(self.port, self.ipaddress, function()
{
console.log('%s: Node server started on %s:%d ...', Date(Date.now() ), self.ipaddress, self.port);
});
};
This is my app.js basic code that is working on openshift.
#!/bin/env node
ipaddress = process.env.OPENSHIFT_NODEJS_IP;
if (typeof ipaddress === "undefined") {
// Log errors on OpenShift but continue w/ 127.0.0.1 - this
// allows us to run/test the app locally.
console.warn('No OPENSHIFT_NODEJS_IP var, using 127.0.0.1');
ipaddress = "127.0.0.1";
};
var server = app.listen(8080, ipaddress, function() {
console.log('Listening on port %d', server.address().port);
});
Can you try that?
Update
After trying it on openshift with request I also got this error but it was because package.json didn't have request under dependencies.
My dependencies now look like this and it works fine:
"dependencies": {
"ejs": "^2.4.1",
"express": "~3.4.4",
"request": "latest" // this is added
},
Here are the dependencies of my package.json file where i've added "cool-ascii-faces. I then need to update my index.js file to GET the /cool page so that on each reload I would see an ascii face. I'm getting a 404 error and it says 'Cannot GET /cool'
"dependencies": {
"ejs": "2.3.3",
"express": "4.13.3",
"cool-ascii-faces": "~1.3"
}
Below is my index.js file that calls declares cool
var cool = require('cool-ascii-faces');
var express = require('express');
var app = express();
app.set('port', (process.env.PORT || 5000));
app.use(express.static(__dirname + '/public'));
// views is directory for all template files
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.get('/cool', function(request, response) {
response.render('pages/index')
});
app.get('/cool', function(request, response) {
response.send(cool());
});
app.listen(app.get('port'), function() {
console.log('Node app is running on port', app.get('port'));
I then run npm install to update the dependencies and then heroku local, but get the 404 error.
Any help in the right direction would be great!
You're probably getting an exception when you start the node web server, due to a module dependency error.
Check your command/terminal window. If you see a red warning message pointing to your module.js file, you have an exception:
$ heroku local
forego | starting web.1 on port 5000
web.1 | module.js:341
In this case, you need to install the cool-ascii-faces module. In your 'node-js-getting-started' directory, use the following npm command to install:
$ npm i -S cool-ascii-faces
Also... you'll want to convert your index page route back to '/'. Your routes logic should look like this:
app.get('/', function(request, response) {
response.render('pages/index')
});
app.get('/cool', function(request, response) {
response.send(cool());
});
Otherwise, you'll always get the default 'pages/index' page when you hit the '/cool' route instead of a smiley face.
You don't have to include
app.set('port', (process.env.PORT || 5000));
app.listen(app.get('port'), function() {
console.log('Node app is running on port', app.get('port'));
}
Heroku will run "npm start" to start your server and dynamically choose the port. You don't have to specify port explicitly.
this problem happened for me. After I typed "git push heroku master", I typed "heroku open" and it worked.