Console.log not working in a dockerized Node.js / Express app - node.js

I have built a Node.js app within a docker container with the following Dockerfile:
FROM node:carbon
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 8080
CMD [ "npm", "start" ]
I am trying to console.log within an express route, however after docker run -p 49160:8080 -d, the console is not interactive and logs are not being echoed at all.
'use strict';
// Requires
const express = require('express');
// Constants
const PORT = 8080;
const HOST = '0.0.0.0';
// App
const app = express();
// Routes
app.get('/', (req, res) => {
// This isn't being printed anywhere
console.log(req);
});
// Start
app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`);
What am I doing wrong?

Remove the -d from the command you're using to run the container:
docker run -p 49160:8080
The -d option runs the container in the background, so you won't be able to see its output in your console.
If you want to keep the container running in the background and you want to access that container's shell, you can run the following command once your container is up and running:
docker exec -it <container-name> bash

Adding this comment as I was searching for the same thing and this was first result on Google.
docker logs <container-name>
https://docs.docker.com/engine/reference/commandline/logs/

Related

Error: connect ECONNREFUSED 0.0.0.0:8000 when hitting Docker containerised Node.js app endpoint

I'm just starting with Docker and dough I succeed in creating an image and a container from it
I'm not succeeding in connecting to the container's port with postman and I get Error: connect ECONNREFUSED 0.0.0.0:8000.
In my server.js file I have:
const app = require('./api/src/app');
const port = process.env.PORT || 3000; // PORT is set to 5000
app.listen(port, () => {
console.log('App executing to port ', port);
});
in my index.js I have :
const express = require('express');
const router = express.Router();
router.get('/api', (req, res) => {
res.status(200).send({
success: 'true',
message: 'Welcome to fixit',
version: '1.0.0',
});
});
module.exports = router;
so if I run my app with either npm start or nodemon server.js the localhost:3000/api endpoint works as expected.
I then build a docker image for my app with the command docker build . -t fixit-server with this Dockerfile:
FROM node:15.14.0
# Create app directory
WORKDIR /usr/src/app
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm#5+)
COPY package.json package.json
COPY package-lock.json package-lock.json
RUN npm install
# If you are building your code for production
# RUN npm ci --only=production
# Bundle app source
COPY . .
EXPOSE 5000
# CMD ["npm", "start"]
CMD npm start
# CMD ["nodemon", "server.js"]
and run the container with the command docker run -d -p 8000:5000 --name fixit-container fixit-server tail -f /dev/null
and listing the containers with docker ps -a shows it running :
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
da0e4ef12402 fixit-server "docker-entrypoint.s…" 9 seconds ago Up 8 seconds 0.0.0.0:8000->5000/tcp fixit-container
but when I hit the endpoint 0.0.0.0:8000/apiI get the ECONNREFUSED error.
I tried both CMD ["npm", "start"]and CMD npm start but I get the error both ways.
Can you what I'm doing wrong?
Update:
#Vincenzo was using docker-machine and to be able to check whether the app was working properly, we needed to execute the following command in the terminal:
docker-machine env
The result was:
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.102:2376"
export DOCKER_CERT_PATH="/Users/vinnytwice/.docker/machine/machines/default"
export DOCKER_MACHINE_NAME="default"
Then based on the DOCKER_HOST value, we hit 192.168.99.102:8000/api and it was working.
I believe the problem is you're never setting the PORT environment variable to 5000.
EXPOSE docker command is a no op. Meaning that it will do nothing but is only for the developer to know that you're exposing the port 5000. You can read it in Docker documentation.
You need to either set an environment variable or pass an environment variable at runtime to the container to specifically tell it that PORT is 5000.
Method 1:
You can change your Dockerfile like below:
FROM node:15.14.0
# Create app directory
WORKDIR /usr/src/app
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm#5+)
COPY package.json package.json
COPY package-lock.json package-lock.json
RUN npm install
# If you are building your code for production
# RUN npm ci --only=production
# Bundle app source
COPY . .
ENV PORT=5000
EXPOSE $PORT
# CMD ["npm", "start"]
CMD npm start
# CMD ["nodemon", "server.js"]
Method 2:
Simply use the following command to run your container:
docker run -d -p 8000:5000 --name fixit-container --env PORT=5000 fixit-server

node js docker is not running on heroku

Node js project in Docker container is not running on Heroku.
Here is the source code.
Docker file
FROM node:14
WORKDIR /home/tor/Desktop/work/docker/speech-analysis/build
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 8080
CMD [ "node", "server.js" ]
server.js
'use strict';
const express = require('express');
const PORT = process.env.port||8080;
const app = express();
app.get('/', (req, res) => {
res.send('Hello World');
});
app.listen(PORT);
console.log("Running on http://:${PORT}");
You don't need to expose anything when having a container for Heroku. It takes care of it automatically. If you are running the same Docker locally, you can do:
docker build -t myapp:latest .
docker run -e PORT=8080 -p 8080:8080 -t myapp:latest
I think that the environment variables are case-sensitive on Linux systems - so you need to change the
const PORT = process.env.port||8080;
... to:
const PORT = process.env.PORT||8080;
... as Heroku sets an environment variable PORT (and not port).
According to this answer you just need to use the port 80 in your expose or inside of nodejs:
app.listen(80)
Heroku at run, will generate a random port and bind it to 80
docker run ... -p 46574:80 ...
So if your nodejs app is running at port 80 inside of container, everything will be fine

Creating a Docker Container to deploy to a prod env

I'm having some problems with building my application through Jenkins and running the container on a extrernal tomcat.
Dockerfile:
FROM node:10.16.3
RUN ls -al
WORKDIR /app
COPY /package/repo/package.json /app/package.json
RUN npm install
COPY /package/repo /app
RUN npm run build
EXPOSE 8080
CMD ["npm", "start]
npm start calls node server.js
server.js:
const express = require('express');
const app = express();
const port = 8080;
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(port, () => {
console.log(`Example app listening on port ${port}!`);
console.log(__dirname+'/client/build/index.html');
});
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
docker build -t reacttest .
docker run reacttest
I'm trying to access the container using localhost:8080, however, whenever I access that port, I'm getting error not found. Is there a step I'm missing. Sorry, i'm very new to docker.
You need to map a port from your machine to the container. Use the p flag for this.
docker run reacttest -p 8080:8080
In general the syntax is:
docker run <image> -p <host port>:<container port>
You can read more in the documentation
EXPOSE does not accually publish the port. You should run you container with -p flag to map ports from container to your host system. See the documents.

Can we use http package in nodejs with docker

I am researching about docker and I have code a demo nodejs with docker. I use HTTP package in nodejs instead of express, the app is built with docker, but when I go to localhost:80, the return is
ERR_EMPTY_RESPONSE
I have code a demo with nodejs and use express, it can run, and I cannot find any example using HTTP package.
I do not clear what EXPOSE port in docker for, that is port call to browser or port for app?
Docker file
FROM node:8
RUN mkdir -p /home/node/app && chown -R node:node /home/node/app
WORKDIR /home/node/app
COPY package*.json ./
USER node
RUN npm install
COPY --chown=node:node . .
EXPOSE 80
CMD ["npm", "start"]
index.js
const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end("Hello world \n");
});
server.listen(port, hostname, () => {
console.log(`server is running at abcxyz http://${hostname}:${port}/`);
});
Have you published the port at your docker run command?
docker run -p 80:3000 ...
Your hostname if you run it without docker is localhost (127.0.0.1)
But if you run it in docker it have to be:
const hostname = '0.0.0.0';
In your code, server listens to PORT 3000 and you have exposed PORT 80 to HOST which means PORT 80 has nothing corresponding running inside docker container, you actually have to EXPOSE PORT 3000 from docker container and use that.
You can use this command to map to a port usable in host where port number before : represents port to be exposed in host and port number after : represents port in docker container that's exposed AFAIK.
docker run -p 80:80

How to update configuration file (.env file) while running docker container

I have created a nodejs app and built docker image as per this link
Dockerizing a Node.js web app
But, I am also using configuration file (.env file) where I can maintain all the environment variables and access them with process.env.<Variable_name>.
My server.js file looks like this.
'use strict';
const express = require('express');
require('dotenv').config()
// Constants
const PORT = process.env.PORT | 8080;
const HOST = process.env.HOST;
// App
const app = express();
app.get('/', (req, res) => {
res.send('Hello world\n');
});
app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`);
And My .env file is this.
HOST=10.20.30.40
PORT=8080
I can change my IP address and port to anything with out changing any code in server.js. As similar as this, I want update the .env when I am building it as a docker image.
This is my Dockerfile
FROM node:carbon
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
COPY .env .
EXPOSE 8080
CMD [ "npm", "start" ]
I know I can update the .env file while building image by giving --build-args. But every time if need to make change in .env, I have to rebuild the image and deploy it. So, I want to update the .env file while running the image or container.
In the below command is there any way to give some arguments so it will update the .env file in the docker.
docker run -p 49160:8080 -d <your username>/node-web-app
You can add a directory to the docker using -v
docker run -v /Path/To/The/Env/file:/env-file-directory -p ...
Then target the file in the linked directory inside of your docker using the name /env-file-directory

Resources