Nodejs port with docker is unreachable - node.js

I'm trying to run node inside a docker container and to expose externally port 8585.
I just want to test the accessibility of the exposed port.
For now, in order to simplify the problem, I excluded Nginx from this setup, I just want to test the nodejs+docker port.
The setup:
Nodejs:
const PORT = 8585;
const HOST = '127.0.0.1';
app.listen(PORT, HOST);
Dockerfile:
FROM node:11.10.1
ENV NODE_ENV production
WORKDIR /usr/src/app
COPY . .
RUN npm install --production --silent
EXPOSE 8585
CMD node index.js
docker-compose.yml
version: '2.1'
services:
mws-client:
image: mws-client
build: .
environment:
NODE_ENV: production
ports:
- '8585'
Running the docker image:
docker run -p 8585:8585 --expose 8585 1085d876c882
Running output:
$ docker run -p 8585:8585 --expose 8585 1085d876c882
About 2 run on http://127.0.0.1:8585
Running on http://127.0.0.1:8585
Netstat output:
$ netstat -a | grep 8585
tcp46 0 0 *.8585 *.* LISTEN
Docker ps:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
99d032ce1ad2 1085d876c882 "/bin/sh -c 'node in…" 7 minutes ago Up 7 minutes 0.0.0.0:8585->8585/tcp inspiring_hypatia
Still - no connection:
$ curl http://127.0.0.1:8585
curl: (52) Empty reply from server
$ curl http://127.0.0.1:80
<html><body><h1>It works!</h1></body></html>
Please help - clearly I am missing something fundamental (believe me I tested it with so many options..)

The issue is not with Docker or Host, The issue is in the node application.
you should not bind server to listen 127.0.0.1.
change your code and bind to 0.0.0.0 and everything will work fine.
const PORT = 8585;
const HOST = '0.0.0.0';
app.listen(PORT, HOST);
you are good to test
docker run -p 8585:8585 -it 1085d876c882
update compose
ports:
- "8585:8585"

Related

Problems to access a recent a vue app deployed in docker container

This is my second VUE web application deploy which I can't access. Inside Docker host Linux running curl localhost:8081, curl: (56) Recv failure: Connection reset by peer
Dockerfile:
FROM node:12
WORKDIR /app_teste
COPY package*.json ./
RUN npm --version
RUN npm install
COPY . .
EXPOSE 8081
CMD ["npm","run","serve"]
dockercompose.yml:
version: '3'
services:
website:
build: .
ports:
- "8081:8081"
container_name: dexter_g_website
I was reading here some topics similars which says about binding to 0.0.0.0 would work, however it never happens. Anyone can help/suggest anything?
docker port dexter_g_webiste
8081/tcp -> 0.0.0.0:8081
Based on Vue CLI documentation, the default port for serve command is 8080.
If you want to serve it to port 8081, try
CMD npm run serve --port 8081
Some more debugging tips:
You can run curl command inside the docker container to debug your app.
SSH into the running container
docker-compose exec -it <container_id> sh
Install CURL
curl the URL and see which is working
curl http://localhost:8080
curl http://localhost:8081

On what PORT is my docker container with a React app running? Reacts' default PORT or EXPOSE from Dockerfile?

I'm a newbie to Docker so please correct me if anything I'm stating is wrong.
I created a React app and wrote a following Dockerfile in the root repository:
# pull official base image
FROM node:latest
# A directory within the virtualized Docker environment
# Becomes more relevant when using Docker Compose later
WORKDIR /usr/src/app
# Copies package.json and package-lock.json to Docker environment
COPY package*.json ./
# Installs all node packages
RUN npm install
# Copies everything over to Docker environment
COPY . .
# Uses port which is used by the actual application
EXPOSE 8080
# Finally runs the application
CMD [ "npm", "start" ]
My goal is to run the docker image in a way, that I can open the React app in my browser (with localhost).
Since in the Dockerfile I'm Exposing the app to the PORT: 8080. I thought I can run:
docker run -p 8080:8080 -t <name of the docker image>
But apparently the application is accessible through 3000 in the container, cause when I run:
docker run -p 8080:3000 -t <name of the docker image>
I can access it with localhost:8080.
What's the point of the EXPOSE port in the Dockerfile, when the service running in its container is accessible through a different port?
When containerizing a NodeJS app, do I always have to make sure that process.env.PORT in my app is the same as the EXPOSE in the Dockerfile?
EXPOSE is for telling docker what ports from inside the application can be exposed. It doesn't mean anything if you do not use those port inside (container -> host).
The EXPOSE is very handy when using docker run -P -t <name of the docker image> (-P capital P) to let Docker automatically publish all the exposed ports to random ports on the host (try it out. then run docker ps or docker inspect <containerId> and checking the output).
So if your web Server (React app) is running on port 3000 (inside the container) you should EXPOSE 3000 (instead of 8080) to properly integrate with the Docker API.
It's kind of weird.
Its just documentation in a sense.
https://docs.docker.com/engine/reference/builder/#:~:text=The%20EXPOSE%20instruction%20informs%20Docker,not%20actually%20publish%20the%20port.
The EXPOSE instruction does not actually publish the port. It
functions as a type of documentation between the person who builds the
image and the person who runs the container, about which ports are
intended to be published. To actually publish the port when running
the container, use the -p flag on docker run to publish and map one or
more ports, or the -P flag to publish all exposed ports and map them
to high-order ports.
do I always have to make sure that process.env.PORT in my app is the
same as the EXPOSE in the Dockerfile?
Yes. You should.
And then you also need to make sure that port actually gets published, when you use the docker run command or in your docker-compose.yml file, or however you plan on running docker.
Actually react app runs the default port 3000. so you must to mention ports and expose in docker-compose.yml. Now I'm changing the 3000 port to 8081
frontend:
container_name: frontend
build:
context: ./frontend/app
dockerfile: ../Dockerfile
volumes:
- ./frontend/app:/home/devops/frontend/app
- /home/devops/frontend/app/node_modules
ports:
- "8081:3000"
expose:
- 8081
command: ["npm", "start"]
restart: always
stdin_open: true
And run the docker
$ sudo docker-compose up -d
Then check the running containers for find the running port
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
83b970baf16d devops_frontend "docker-entrypoint..." 31 seconds ago Up 30 seconds 8081/tcp, 0.0.0.0:8081->3000/tcp frontend
It's resolved. check your public port
$ curl 'http://0.0.0.0:8081'

Containerized NodeJS application on podman not reachable

I'm running a nodejs app in a pod (together with a mongo container)
Nodejs app listens on port 3000, which I expose from the container.
I have published port 3000 on the pod.
The container starts successfully (logs verified), but I can't reach my application on the host. When I curl to my app from within the pod it works.
Containers run rootfull, OS: CentOS Linux release 8.0.1905 (Core).
What am I missing?
curl http://localhost:3000
curl: (7) Failed to connect to localhost port 3000: No route to host
podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
30da37306acf registry.gitlab.com/xxx/switchboard:master node main.js 34 minutes ago Up 34 minutes ago 0.0.0.0:3000->3000/tcp switchboard-app
acc08c71147b docker.io/library/mongo:latest mongod 35 minutes ago Up 35 minutes ago 0.0.0.0:3000->3000/tcp switchboard-mongo
podman port switchboard-app
3000/tcp -> 0.0.0.0:3000
app.listen(3000, "0.0.0.0",function () {
console.log('App is listening on port 3000!');
});
FROM node:13
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY /dist/apps/switchboard .
EXPOSE 3000
CMD [ "node", "main.js" ]
If you want to create production docker build, you can go another way. It's not a good idea to do npm install inside container, because it will be too large. Run npm run build first, and then copy builded statics into docker container, created with nginx image.
So your Dockerfile shoud look like:
FROM nginx:1.13.0-alpine
COPY build/* /usr/share/nginx/html/
also specify exposed ports correctly with docker run. So, if you want expose 3000, your steps is:
cd /project/dir
docker build -t switchboard-app .
docker run -d -p 3000:80 --name switchboard-app switchboard-app

Dockerizing a React App: The app starts inside the container, but it not accessible from the exposed port

This is a question specifically for the tutorial at: http://mherman.org/blog/2017/12/07/dockerizing-a-react-app/#.Wv3u23WUthF by Michael Herman
Problem: The app starts inside the container, but it is not accessible from the port I just exposed -p 3000:3000. When Browse to localhost:3000 get a This site can’t be reached error
docker-compose.yaml
version: '3.5'
services:
sample-app:
container_name: sample-app
build:
context: .
dockerfile: Dockerfile
volumes:
- '.:/usr/src/app'
- '/usr/src/app/node_modules'
ports:
- '3000:3000'
environment:
- NODE_ENV=development
Dockerfile
# base image
FROM node:9.6.1
# set working directory
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
# add `/usr/src/app/node_modules/.bin` to $PATH
ENV PATH /usr/src/app/node_modules/.bin:$PATH
# install and cache app dependencies
COPY package.json /usr/src/app/package.json
RUN npm install --silent
# RUN npm install react-scripts#1.1.1 -g --silent # Uncomment to silent logs
RUN npm install react-scripts#1.1.1 -g
# start app
CMD ["npm", "start"]
#CMD tail -f /usr/src/app/README.md
###################################
# To Run sample app:
# docker run -it -v ${PWD}:/usr/src/app -v /usr/src/app/node_modules -p 3000:3000 --rm sample-app
Docker logs : https://docs.google.com/document/d/14LRCgjMLAkmdMiuedxAW2GWUAtxmWeJQCNQB2ezdYXs/edit
After running either the compose or single container. It shows successful startup, but nothing thereafter.
When I docker exec into the container, $ curl localhost:3000 returns the proper index.html page
I start up the container with either:
$ docker run -it -v ${PWD}:/usr/src/app -v /usr/src/app/node_modules -p 3000:3000 --rm sample-app
<- (The image sample-app exists )
or
$ docker-compose up
After eliminating all other factors I assume that your application is listening on localhost. Localhost is scoped to the container itself. Therefore to be able to connect to it, you would have to be inside the container.
To fix this, you need to get your application to listen on 0.0.0.0 instead.
The problem is your are exposing the app on localhost strictly.
You have to modify your package.json to change that:
"start": "http-server -a localhost -p 3000"
into:
"start": "http-server -a 0.0.0.0 -p 3000"
if your contents of package.json differ strongly from that what's above, the important part is the -a option - it has to point to 0.0.0.0 as it means the http-server will listen on all incoming connections.
If you are not sure what to change, just post the essential part of package.json here in your question so we can check it.
I had the same issue when I was using create-react-app but I managed to solve it by not exposing the docker port in the Dockerfile and running the following command docker container run -p ANY_PORT_YOU_WANT:**3000** -d image_name. It so happens that by default react-server runs on PORT 3000 in the docker container and by exposing any other port other than 3000, that connection flow is killed. The start script uses 0.0.0.0 by default. See Issue

Docker EXPOSE. Can't get it

this past two day I'm having trouble with docker and i can get it. Following to the docker doc you can expose the ports on which a container will listen for connections with EXPOSE. So far, so good!
If my app listen on port 8080 I should expose my docker container with EXPOSE 8080 and bind it to port 80 of the main host with docker run -p 80:8080.
Here is my Dockerfile:
# DOCKER-VERSION 0.0.1
FROM ubuntu:14.10
# make sure apt is up to date
RUN apt-get update
# install nodejs and npm
RUN apt-get install -y nodejs-legacy npm git git-core
ADD package.json /root/
ADD server.js /root/
# start script
ADD start.sh /root/
RUN chmod +x /root/start.sh
EXPOSE 8080
CMD ./root/start.sh
And my start.sh just runan cd /root/ & npm install & node server.js.
I got a simple express nodejs app:
var express = require('express');
// Constants
var PORT = 8080;
// App
var app = express();
app.get('/', function (req, res) {
res.send('Hello world\n');
});
app.listen(PORT);
console.log('Running on http://localhost:' + PORT);
Here is how i build my docker image: docker build -t app1 .
And how i launch my docker: docker run -it -p 80:8080 --name app1 app1
What is really wired, this is not working. To make it work i have to change EXPOSE 8080 to EXPOSE 80. I don't get it.
Any explanation?
Thanks for reading,
Tom
In your nodejs app, you have the instruction app.listen(PORT); which tells nodejs to start a server listening for connections on the loopback interface on port PORT.
As a result your app will only by able to see connections originating from localhost (the container itself).
You need to tell your app to listen on all interfaces on port PORT:
app.listen(PORT, "0.0.0.0");
This way it will see the connections originating from outside your Docker container.

Resources