Node.js app running in docker container is not reachable - node.js

I want to run a node.js app in a docker container using docker-compose. The app is TiddlyWiki, there are other containers and the whole thing runs in a vagrant VM and is set up with ansible, but I don't think any of that matters for this problem.
This is my docker-compose config:
wiki:
image: node:12-alpine
container_name: nodejs
restart: always
working_dir: /home/node/app
environment:
NODE_ENV: production
volumes:
- "/srv/docker_wiki/:/home/node/app"
ports:
- "8080:8080"
command: "node node_modules/tiddlywiki/tiddlywiki.js mywiki --listen debug-level=debug"
The app seems to start up and run without issues:
vagrant#vserver:~$ sudo docker logs nodejs
Serving on http://127.0.0.1:8080
(press ctrl-C to exit)
syncer-server-filesystem: Dispatching 'save' task: $:/StoryList
But I cannot reach it:
vagrant#vserver:~$ curl http://localhost:8080
curl: (52) Empty reply from server
vagrant#vserver:~$ curl http://localhost:8080
curl: (56) Recv failure: Connection reset by peer
It seems random which of the two different error messages comes up.
An interesting detail: If I use the default node image which comes itself with curl, then I can in fact reach the app from within the container itself after running docker exec -it nodejs /bin/bash
I have also tried to use a different port on the host, with the same result.
Any idea what could be going wrong here?

An interesting detail: If I use the default node image which comes
itself with curl, then I can in fact reach the app from within the
container itself after running docker exec -it nodejs /bin/bash
If you are able to access inside the container, it means the application bind with 127.0.0.1 the localhost of the container.
Serving on http://127.0.0.1:8080
(press ctrl-C to exit)
All need to bind it with 0.0.0.0.
so change the command to
command: "node node_modules/tiddlywiki/tiddlywiki.js mywiki --host 0.0.0.0 --listen debug-level=debug"
or
command: "node node_modules/tiddlywiki/tiddlywiki.js mywiki --listen debug-level=debug host=0.0.0.0"
You explore further ListenCommand here.

Related

How to stabilize the port used by docker-compose?

I have an Node.js application that I want to run with docker-compose. Inside the container it listens for port 4321, set by an environment variable.
This port is also exposed by my Dockerfile and I specify it like so in my docker-compose.yml:
version: '3.4'
services:
previewcrawler:
image: previewcrawler
build:
context: .
dockerfile: ./Dockerfile
environment:
NODE_ENV: development
ports:
- 4321:4321
- 9229:9229
command: ['node', '--inspect=0.0.0.0:9229', 'dist/index.js']
I run the app with a VSCode task, which executes this:
docker run -dt -P --name "previewcrawler-dev" -e "DEBUG=*" -e "NODE_ENV=development" --label "com.microsoft.created-by=visual-studio-code" -p "9229:9229" "previewcrawler:latest" node --inspect-brk=0.0.0.0:9229 .
When I choose to open the application in my browser, it has some crazy port like 49171, which also changes every time I start my container.
How can I make this port stable? So that it is 4321 every time, like I specified in my docker-compose.yml
docker run -P (with a capital P) tells Docker to pick a host port for anything the Dockerfile EXPOSEs. You have no control over which host port or interfaces the port uses.
docker run -p 4321:4321 (with a lowercase p) lets you explicitly pick which ports get published, and on which host port. It is exactly equivalent to the Compose ports: option.
This is further detailed in the Docker run reference.
(That link is more specifically to a section entitled "expose incoming ports". However, "expose" as a verb means almost nothing in modern Docker. Functionally, it does only two things: if you use docker run -P then all exposed ports get published; and if you don't have a -p or -P option at all, the port will be listed in the docker ps output anyways. Exposed ports aren't automatically published, and there's not really any reason to use the docker run --expose or Compose expose: options.)
Apparently I started my app with the wrong command. I now use
docker-compose -f "docker-compose.debug.yml" up -d --build
which works great. The port is also correct then.

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'

Run node Docker without port mapping

I am very to new Docker so please pardon me if this this is a very silly question. Googling hasn't really produced anything I am looking for. I have a very simple Dockerfile which looks like the following
FROM node:9.6.1
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
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
COPY . /usr/src/app
RUN npm start
EXPOSE 8000
In the container the app is running on port 8000. Is it possible to access port 8000 without the -p 8000:8000? I just want to be able to do
docker run imageName
and access the app on my browser on localhost:8000
By default, when you create a container, it does not publish any of its ports to the outside world. To make a port available to services outside of Docker, or to Docker containers which are not connected to the container’s network, use the ‍‍--publish or -p flag. This creates a firewall rule which maps a container port to a port on the Docker host.
Read more: Container networking - Published ports
But you can use docker-compose to set config and run your docker images easily.
First installing the docker-compose. Install Docker Compose
Second create docker-compose.yml beside the Dockerfile and copy this code on them
version: '3'
services:
web:
build: .
ports:
- "8000:8000"
Now you can start your docker with this command
docker-compose up
If you want to run your services in the background, you can pass the ‍‍-d flag (for “detached” mode) to docker-compose up -d and use `docker-compose ps to see what is currently running.
Docker Compose Tutorial
Old question but someone might find it useful:
First get the IP of the docker container by running
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name_or_id
Then connect to it from the the browser or using curl using the IP and port exposed :
Note that you will not be able to access the container on 0.0.0.0 because port is not mapped

how to link two docker containers?

I am new to docker.I built a crawler with headless chrome But Now I have to deploy with docker and there is image for https://github.com/yukinying/chrome-headless-browser-docker and it will host remote debugging mode in port 9222 and there is another container my node app is running I don't know how to link these both container .
docker run -it --name nodeserver --link chrome:chrome nodeapp bash
But inside that docker I can't access the localhost:9222
I would suggest using docker-compose, it comes with docker for mac / windows and is made for this kind of simple connection.
You would need a docker compose file something like
version: "3"
services:
headless-browser:
image: yukinying/chrome-headless
ports:
- 9222
crawler:
build:
context: .
dockerfile: Dockerfile
links:
- headless-browser
And then a Docker file in the same folder
e.g. for testing connection use
FROM alpine
RUN apk update && apk add curl
CMD curl http://headless-browser:9222
Use the command docker-compose up
Output would be the console page in text (so you know the connection is working ok)
To avoid any issues with indentation... I've made a repo to copy and paste from: https://github.com/TheSmokingGnu/stackOverflowAnswer

Resources