Unable to dockerize a nodeapp - javascript

Created the docker file as following:
FROM node:boron
ADD package.json package.json
RUN npm install
ADD . .
EXPOSE 4500
CMD ["node","main.js"]
Building the app:
docker build -t "appname"
Running the app:
docker run -it "appname"
Inside main.js, I have:
var express = require("express");
var app = express();
var path = require('path');
var http = require('http');
var https = require('https');
var nodemailer = require('nodemailer');
var bodyParser = require('body-parser');
var request = require("request");
var port = process.env.PORT || 3001;
app.set('port', (port));
app.listen(app.get('port'), function () {
console.log('Node app is running on port', app.get('port'));
});
//app.use('/', express.static(path.join(__dirname, '/public_html')))
app.use('/', express.static(__dirname + '/public_html'));
app.use(bodyParser.json({limit: '5mb'}));
app.use(bodyParser.urlencoded({
limit: '5mb',
extended: false
}));
app.get('/', function(request, response) {
response.render('public_html/');
});
//app.get('/', function (req, res, next) {
// res.sendFile('/index.html');
//});
app.use('*', function (req, res, err) {
// console.log('error: ', err);
});
when I run the app using docker command 'docker run -it "appname"`, I get the out to console:
Node app is running on port 3001
But when I browse, page is empty or nothing is loaded in the browser/output/view. It is supposed to pick up index.html from response.render('public_html/');

You need to explicitly expose the port which your app is supposed to run on:
docker run -p 3001:3001 your-node-image
Then you can access your container's service on your docker host under http://localhost:3001, because -p 3001:3001 binds the host port 3001 (the first 3001 in the argument) to the container's port 3001 (the second 3001).
EXPOSE from your Dockerfile only describes which ports are exposed by your application (which is in your Dockerfile 4500 and in your program port 3001...? Why are they different?). Publishing ports with -p is also necessary to access the container, see the docs:
The EXPOSE instruction informs Docker that the container listens on the specified network ports at runtime. EXPOSE does not make the ports of the container accessible to the host. To do that, you must use either the -p flag to publish a range of ports or the -P flag to publish all of the exposed ports.
Additionally, the flags -it appear to be useless with your service. You need these flags when you want to have an interactive session, e.g. when you're starting a shell in your container.
See here some more information about port exposal in the official documentation

Related

How to structure docker container ports? Use --net or --link?

I have 2 docker containers. One contains a simple node.js web app which contains server information and MongoDB connection details. The second contains a running instance of MongoDB.
I am attempting to run the web app container to connect to the MongoDB container like so:
docker run --link mongodb2:mongodb2 -p 49160:8080 -it --name web node-web-app
Doing this I can successfully access and view the hosted page at http://hostname:49160/ but I cannot connect to MongoDB.
Another method I have tried is:
docker run --net container:mongodb2 -ti --name web node-web-app
Here I can successfully connect to MongoDB, but I cannot access my hosted page at http://hostname:27017/. Instead I receive the message:
It looks like you are trying to access MongoDB over HTTP on the native driver port.
I have also attempted to pass port details like so using the --net method:
docker run --net container:mongodb2 -p 49160:8080 -ti --name web node-web-app
but I receive a docker error:
docker: Error response from daemon: conflicting options: port publishing and the container type network mode.
See 'docker run --help'.
I believe there is an issue with the way I am configuring my ports, but I am new to both docker and setting up web servers.
Here is my web app code:
'use strict';
const express = require('express');
// App
const app = express();
// Constants
const PORT = 8080;
const HOST = '0.0.0.0';
const MongoClient = require('mongodb').MongoClient;
// Connect URL
const url = 'mongodb://127.0.0.1:27017';
var db;
var ticket;
MongoClient.connect(url, {
useNewUrlParser: true,
useUnifiedTopology: true
}, (err, client) => {
if (err) {
return console.log(err);
}
// Specify database you want to access
db = client.db('DB');
console.log(`MongoDB Connected: ${url}`);
ticket = db.collection('ticket');
ticket.find().toArray((err, results) => {
console.log(results);
});
});
//Routes
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html')
});
app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`)
You should use a named Docker network to connect between containers. Once you do, the other containers' names will be usable as host names.
docker network create some-network
docker run -d --net some-network --name mongodb2 mongo
docker run -d --net some-network --name app -p 49160:8080 node-web-app
In your source code, you can't hard-code the location of the database, since it's somewhat likely it won't be on the same machine or in the same container when you deploy it. localhost could be a reasonable developer default but the option needs to be configurable.
const mongoHost = process.env.MONGO_HOST || 'localhost';
const url = `mongodb://${mongoHost}:27017`;
docker run ... -e MONGO_HOST=mongodb2 ...
If you're using Docker Compose to launch things, it provides a default network for you (different from the "default bridge network" in the core Docker documentation) and you need to do very little setup; just use the other container's Compose service name as a host name.
version: '3.8'
services:
mongodb2:
image: mongo
app:
build: .
ports: ['49160:8080']
environment:
- MONGO_HOST=mongodb2
Of the other options you propose, --link is considered obsolete now that named networks have essentially replaced it. Setting one container to run in another's network namespace is also a very unusual setup, and it comes with limitations like what you show.

How to convert local server to online server Node.js

I've been developing this game for a school project. It is supposed to be online multiplayer, but this far i have online used it locally. I can figure out how to change my server code for it to be able to act as a "real" online server.
The server code:
// Dependencies
var express = require('express');
var http = require('http');
var path = require('path');
var socketIO = require('socket.io');
var app = express();
var server = http.Server(app);
app.set('port', 5000);
app.use('/static', express.static(__dirname + '/static'));
// Routing
app.get('/', function(request, response)
{
response.sendFile(path.join(__dirname, 'index.html'));
});
// Starts the server.
server.listen(5000, function()
{
console.log('Starting server on port 5000');
});
// Add the WebSocket handlers
io.on('connection', function(socket)
{
console.log('New player arrived');
});
Would appreciate any help greatly.
Most of the shared servers run at port 8080
so you may change the port then upload it into the hosting, If you just need it to be live u can use https://heroku.com/ so u can deploy it there
also here's quick option
npm install -g localtunnel
lt --port 8000
You will receive a URL, for example, https://school.localtunnel.me, that you can share with anyone for as long as your local instance of lt remains active. Any requests will be routed to your local service at the specified port
For more info: https://localtunnel.github.io/www/

getting node port is undefined even though i don't see anything listening on the ports

I currently have a node.js backend going with express to serve my routes. I have the port in my .env file as shown below
NODE_ENV = development
port = 7000
Now when I try to run my backend, the port is not available. I run the commands below to check but I don't get any output from the terminal
lsof -i:7000
lsof -i:8080
I am not sure what's holding the ports. I will paste my server.js below for reference also.
import express from 'express'
import dotenv from 'dotenv'
import colors from 'colors'
dotenv.config()
const app = express();
const PORT = process.env.PORT || 8080;
if (!process.env.PORT) {
console.log(`Port is unavailalbe ${PORT}`)
process.exit(1);
} else {
app.listen(PORT, console.log(`Server is running in ${process.env.NODE_ENV} on port ${PORT}`.yellow.bold));
}
You have variable port in .env but you're checking if PORT is defined (which is not). Change port to PORT in .env.
Edit: I also recommend removing spaces in .env.

Stuck in Mean Stack

I am new to MEAN Stack. and i am using Ubuntu. i installed ejs, express, node etc via Terminal. i made a folder in Documents>NodeTuts and then in in terminal i wrote npm init after the progress i got package.json in nodeTuts and server.js and than i made a folder in nodeTuts named client and then in client>views and in views i made a file index.ejs.
In server.js i wrote:
var express = require('express');
var app = express();
var path = require('path');
var port = process.env.PORT;
app.set('view engine','ejs');
app.set('views', path.resolve(__dirname, 'client', 'views'));
app.get('/', function (req, res){
res.render('index.ejs');
});
app.listen(port, function (){
console.log('SERVER RUNNING... PORT: ' + port);
})`
and in index.js i wrote:
simply HELLO WORLD
but when i opened server.js in Chrome i thought there will be HELLO WORLD but there was server.js code as a text This is what i got
I am learning from Brent Aureli's Tutorials. he is doing all this on windows usng cloudy and i am doing this on Ubuntu!
Please help me It's been 3 days i am stuck in this. Thanks!
You must run server.js via node command like this:
PORT=8080 node server.js
Since you haven't specified port on your server file, you must write it with your node command.
Then, open Chrome and type into address bar localhost:8080 (or other port).
If you don't want to write port every time you run node command, change this line:
var port = process.env.PORT || 8080 // or any other port number

Node.js/Express.js App Only Works on Port 3000

I have a Node.js/Express.js app running on my server that only works on port 3000 and I'm trying to figure out why. Here's what I've found:
Without specifying a port (app.listen()), the app runs but the web page does not load.
On port 3001 (app.listen(3001)) or any other port that is not in use, the app runs but the web page does not load.
On port 2999, the app throws an error because something else is using that port.
On port 3000, the app runs and the web page loads fine.
I know that Express apps default to port 3000. But strangely, my app only runs when I explicitly make it run on port 3000 (app.listen(3000)).
I found this on line 220 of /usr/bin/express:
app.set(\'port\', process.env.PORT || 3000);
Which is doing as previously stated: setting the port to what is specified or to 3000 if nothing is specified.
How could I make my app work on a different port such as 8080 or 3001?
Thanks!
Edit: Code Sample (Very Simple Node/Express App)
var express = require("express");
var app = express();
app.get('/', function(req, res){
res.send('hello world');
});
// Only works on 3000 regardless of what I set environment port to or how I set [value] in app.set('port', [value]).
app.listen(3000);
The following works if you have something like this in your app.js:
http.createServer(app).listen(app.get('port'),
function(){
console.log("Express server listening on port " + app.get('port'));
});
Either explicitly hardcode your code to use the port you want, like:
app.set('port', process.env.PORT || 3000);
This code means set your port to the environment variable PORT or if that is undefined then set it to the literal 3000.
Or, use your environment to set the port. Setting it via the environment is used to help delineate between PRODUCTION and DEVELOPMENT and also a lot of Platforms as a Service use the environment to set the port according to their specs as well as internal Express configs. The following sets an environment key=value pair and then launches your app.
$ PORT=8080 node app.js
In reference to your code example, you want something like this:
var express = require("express");
var app = express();
// sets port 8080 to default or unless otherwise specified in the environment
app.set('port', process.env.PORT || 8080);
app.get('/', function(req, res){
res.send('hello world');
});
// Only works on 3000 regardless of what I set environment port to or how I set
// [value] in app.set('port', [value]).
// app.listen(3000);
app.listen(app.get('port'));
In bin/www, there is a line:
var port = normalizePort(process.env.PORT || '3000');
Try to modify it.
Try this
$ PORT=8080 node app.js
Try to locate the bin>www location and try to change the port number...
The default way to change the listening port on The Express framework is to modify the file named www in the bin folder.
There, you will find a line such as the following
var port = normalizePort(process.env.PORT || '3000');
Change the value 3000 to any port you wish.
This is valid for Express version 4.13.1
Just a note for Mac OS X and Linux users:
If you want to run your Node / Express app on a port number lower than 1024, you have to run as the superuser:
sudo PORT=80 node app.js
In the lastest version of code with express-generator (4.13.1) app.js is an exported module and the server is started in /bin/www using app.set('port', process.env.PORT || 3001) in app.js will be overridden by a similar statement in bin/www.
I just changed the statement in bin/www.
Noticed this was never resolved... You likely have a firewall in front of your machine blocking those ports, or iptables is set up to prevent the use of those ports.
Try running nmap -F localhost when you run your app (install nmap if you don't have it). If it appears that you're running the app on the correct port and you can't access it via a remote browser then there is some middleware or a physical firewall that's blocking the port.
Hope this helps!
The line you found just looks for the environmental variable PORT, if it's defined it uses it, otherwise uses the default port 3000. You have to define this environmental variable first (no need to be root)
export PORT=8080
node <your-app.js>
If you want to show something you're connected on 3000
var express = require('express')
var app = express()
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
})
I hope that will be helpful to you
Answer according to current version of express
If you talk about the current version of express, if you run app.listen() to start listening without specifying port, Express will chose a random port for your application, to find out about which port it is currently running on use
app.listen(0, () => {
console.log(app.address().port)
}
should output the port of your app. Moreover that first parameter 0 can be totally ignored but is not recommended
In app.js, just add...
process.env.PORT=2999;
This will isolate the PORT variable to the express application.
I am using the minimist package and the node startup arguments to control the port.
node server.js --port 4000
or
node server.js -p 4000
Inside server.js, the port can be determined by
var argv = parseArgs(process.argv.slice(2))
const port = argv.port || argv.p || 3000;
console.log(`Listening on port ${port}...`)
//....listen(port);
and it defaults to 3000 if no port is passed as an argument.
You can then use listen on the port variable.
Make sure you are running from that folder of your application, where you have the package.json.
I think the best way is to use dotenv package and set the port on the .env config file without to modify the file www inside the folder bin.
Just install the package with the command:
npm install dotenv
require it on your application:
require('dotenv').config()
Create a .env file in the root directory of your project, and add the port in it (for example) to listen on port 5000
PORT=5000
and that's it.
More info here
If you are using Nodemon my guess is the PORT 3000 is set in the nodemonConfig.
Check if that is the case.

Categories

Resources