Docker port forwarding for nodejs app - node.js

I'm having problems configuring docker for my nodejs app.
I have previously set up containers for both php and rails with port forwarding working flawlessly, but for this instance i can't seem to get it to work.
Running: docker ps, i get the following:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a60f9c82d600 29c7d94a8c58 "/bin/sh -c 'npm s..." 5 seconds ago Up 3 seconds 3000/tcp romantic_albattani
As you can see I'm not getting the usual: 0.0.0.0:3000->3000/tcp that I am expecting.
docker-compose ps gives:
Name Command State Ports
------------------------------
My docker-compose.yml:
web:
build: .
volumes:
- .:/app
volumes_from:
- box
ports:
- "3000:3000"
box:
image: busybox
volumes:
- /node_modules
My Docker file:
FROM node:8.7.0
# The base node image sets a very verbose log level.
ENV NPM_CONFIG_LOGLEVEL warn
WORKDIR /tmp
COPY package.json /tmp/
RUN npm install
WORKDIR /app
ADD . /app
RUN cp -a /tmp/node_modules /app/
#ENV PORT=3000
EXPOSE 3000
CMD npm start
I'm running the command: docker-compose up --build
Any help at this point is appreciated.
I don't know if a docker inspect would be useful, but if so, tell me and i will also post it.
Edit: Changed my Dockerfile to follow the answer.

Your docker-compose.yml file has bad formatting, since you are not getting any errors i will assume you pasted it here wrong, here is the version with the fixed indenting:
web:
build: .
volumes:
- .:/app
volumes_from:
- box
ports:
- "3000:3000"
box:
image: busybox
volumes:
- /node_modules
Your Dockerfile has a bug, you are missing the ENTRYPOINT and/or CMD stanzas, instead you are using the RUN stanza with the wrong intent, here is a working Dockerfile with the fix applied:
FROM node:8.7.0
# The base node image sets a very verbose log level.
ENV NPM_CONFIG_LOGLEVEL warn
WORKDIR /tmp
COPY package.json /tmp/
RUN npm install
WORKDIR /app
ADD . /app
RUN cp -a /tmp/node_modules /app/
#ENV PORT=3000
EXPOSE 3000
CMD npm start
Your Dockerfile halted the execution of docker-compose at the docker image building stage because of the RUN npm start which is a process that starts and listens until stopped (because you want it to start your node app and listen for connections) causing docker-compose to never finish the docker image creating step, let alone the other steps like creating the needed containers and finish the entire docker-compose runtime process.
In short:
When you use RUN it is meant to run a command do some work and return sometime to continue the building process, it should return and exit code of 0 and the process will move on to the next Dockerfile stanza, or return another exit code and the building process will fail with an error.
When you use CMD you tell the docker image what is the starting command of all the containers started from this image (it can also be overridden at run time with docker run). It is tightly related to the ENTRYPOINT stanza, but for basic usage you are safe with the default.
Further reading: ENTRYPOINT, CMD and RUN

Related

NPM not found when using npm run start command within shell script from a docker container

I am not sure what I may be doing wrong but I have the following script.sh file sitting at the root of my project:
script.sh
#!/bin/sh
npm run start
envsubst '\$PORT' < /etc/nginx/conf.d/configfile.template > /etc/nginx/conf.d/default.conf
nginx -g 'daemon off;'
Then I referenced the above script in my Dockerfile as shown below:
Dockerfile
# Build environment
FROM node:16.14.2
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --only=production
COPY . ./
# server environment
FROM nginx:alpine
COPY nginx.conf /etc/nginx/conf.d/configfile.template
ENV HOST 0.0.0.0
ENV NODE_ENV production
EXPOSE 8080
COPY script.sh /
RUN chmod +x /script.sh
ENTRYPOINT ["/script.sh"]
After building the Docker image successfully, I attempted to run it as a container but all I keep getting back is the following error:
/script.sh: line 2: npm: not found
I expect that the script should be able to pick up the already installed npm from the environment.
What can I do differently to make this work?
You're trying to run two separate programs, so run them in two separate containers.
# Dockerfile.app
FROM node:16.14.2
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --only=production
COPY . ./
ENV HOST 0.0.0.0
ENV NODE_ENV production
EXPOSE 8080
CMD npm run start
# Dockerfile.nginx
FROM nginx:alpine
COPY nginx.conf /etc/nginx/conf.d/configfile.template
You might use a system like Docker Compose to run the two parts together:
# docker-compose.yml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile.app
nginx:
build:
context: .
dockerfile: nginx
ports:
- 8080:80
Running docker-compose up -d will start both containers together. In your Nginx configuration, make sure to proxy_pass http://app:8080, using the Compose service name and the port number the service is listening on, to forward requests to the other container.
(The Nginx Dockerfile looks short, but it's correct. The Docker Hub nginx image already knows how to run the envsubst line from your script in its own entrypoint script and it has a correct default command already.)
There's two basic problems in the setup you show in the question, both related to trying to run two programs in the same container. The first is that you can't merge images, having a second FROM line makes Docker start over from the new base image. (So your final image contains only Nginx, not Node or your built application, hence the npm not found error.) The second you'll run into is that your script will start your application, but not start the Nginx proxy until after the application exits. There are some common workarounds to this (like using a background process) but it essentially results in one process or the other being unmonitored by Docker, so your application could potentially fail and Docker wouldn't notice it to be able to restart it.

Docker container running but not being listed and cannot be stopped

I'm relatively new to docker and I've been having a really strange problem.
The docker setup I have below runs perfectly, however though there seems to be an instance that is always running even after stopping and removing all containers and quitting the docker application.
When I access localhost in my browser, My app is always live and running.
I've tried running docker-compose stop ; docker-compose rm to stop and remove all container.
'docker-compose ps' and 'docker ps' both show no containers running at all. But whenever I access localhost, my app is there live and running.
Like i said i have tried quitting the docker application (I'm running on mac). i tried restarting the machine and the app would still be running.
The weird thing is when i check to see which if any processes are using port 80 (thus making my app accessible via localhost) by running 'sudo lsof -i tcp:80' the list is empty.
I'm new to docker and I know there must be something I'm overlooking.
Thanks in advance, any help and ideas are welcomed.
Here is my folder structure: screenshot
The Dockerfile for my app:
FROM node:10
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
EXPOSE 3000
ENV NUXT_HOST=0.0.0.0
ENV NUXT_PORT=3000
CMD [ "npm", "start" ]
docker-compose.yml
version: '3'
services:
nuxt:
build: ./app/
container_name: nuxt
restart: always
ports:
- '1880:1880'
command: 'npm run start'
nginx:
image: nginx:1.13
container_name: nginx
ports:
- '80:80'
volumes:
- ./nginx:/etc/nginx/conf.d
depends_on:
- nuxt

Docker with nodemon does not reload my api when code changes

I've been working with docker some weeks ago and I was able to hold this issue, stop docker containers and start them over again to see the changes that I had made in my code but now is really anoying because every single change I do have to kill docker and then "docker-compose up".
However my friend is using the same container on his apple machine but when he makes changes to any server side code he does not have to restart his app.
I can see the changes when I go into the container but those changes are not reflected on live(browser).
My Dockerfile
FROM node:8.11.3
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
# Copy application files
COPY tools ./tools/
COPY migrations ./migrations/
COPY seeds ./seeds/
# Attempts to copy "build" folder even if it doesn't exist
COPY .env build* ./build/
RUN npm install -g nodemon
RUN git clone https://github.com/vishnubob/wait-for-it.git
EXPOSE 8080
CMD ["nodemon", "-L", "server"]
My docker-compose.yml
api:
build: ./
hostname: api
container_name: api
ports:
- "${APP_PORT}:3000"
volumes:
- ./:/usr/src/app
env_file:
- ".env"
command: node tools/run.js
Any sugestion?

Node.js web application not running properly in Docker stack

I have a web application written in Node.js that I'm trying to get into Docker. Running the image with docker run -p 80:80 image works just fine; I'm able to access the webpage it's hosting. However, when I try to run it in a stack, I'm unable to access the page, and Chrome just sits "Waiting for localhost..." forever.
Dockerfile:
FROM readytalk/nodejs
WORKDIR /app
ADD . /app
RUN npm i
EXPOSE 80
CMD []
ENTRYPOINT ["/nodejs/bin/npm", "start"]
docker-compose.yml:
version: "3"
services:
web:
image: image_name
deploy:
replicas: 5
resources:
limits:
cpus: "0.1"
memory: 50M
restart_policy:
condition: on-failure
ports:
- "80:80"
networks:
- webnet
networks:
webnet:
Any help would be greatly appreciated.
EDIT: Added some logging and it seems that the HTTP request is never actually making it to the Node.js app. It seems like Docker has recieved the request, but hasn't routed it to the running app.
Some time your docker container run your IP address.
you can check it by running this command docker info
second option
Go to terminal and write
in window
ipconfig
and see preferred IP then access your container with that IP with specifying port
in Ubuntu
ifconfig
Hope this will solve your problem and try to access using 127.0.0.1:port
You can check this slide which shows and run hello world node+docker
docker-node-hello-world-application
And I will recommend using this Docker file.
Node_DockerFile
FROM alpine
RUN apk update && apk upgrade
RUN apk add nodejs
RUN mkdir -p /app
ADD app/package.json /app
WORKDIR /app/
ENV HOME /app
ENV NODE_ENV development
RUN npm install
ADD app /app
EXPOSE 3000
CMD npm start

Docker compose not finding my index.js

I'm following this guide and use my low docker knowledge to get a dev environment up and running. I've hit a wall I cannot solve. This is my docker-compose.yml:
version: '2'
services:
redis:
image: redis:3.2
mongo:
image: mongo:3.2
app:
build: .
ports:
- '3000:3000'
command: './node_modules/.bin/nodemon ./index.js'
environment:
NODE_ENV: development
volumes:
- .:/home/app/cardcreator
- /home/app/cardcreator/node_modules
depends_on:
- redis
- mongo
links:
- redis
- mongo
and this is my Dockerfile:
FROM node:6.3.1
RUN useradd --user-group --create-home --shell /bin/false app
ENV HOME=/home/app
COPY package.json npm-shrinkwrap.json $HOME/cardcreator/
RUN chown -R app:app $HOME/*
USER app
WORKDIR $HOME/cardcreator
RUN npm install
USER root
COPY . $HOME/cardcreator/
RUN chown -R app:app $HOME/*
USER app
CMD ["node", "index.js"]
When I try to start the app via docker-compose up, I get the error
app_1 | Usage: nodemon [nodemon options] [script.js] [args]
app_1 | See "nodemon --help" for more.
I then removed the command line of my docker-compose.yml, only leaving node index.js to start. I get an error saying index.js cannot be found.
The file is in my project folder, it is there and it has content. I can't figure out why this setup doesn't work, I did similar setups for tails and it worked fine.
Can anyone tell me what I'm doing wrong here?
Whatever you are mounting in your compose file here:
- .:/home/app/cardcreator
Is going to mount on top of whatever you built in $HOME/cardcreator/ in your Dockerfile.
So basically you seem to have conflicting volumes -- it's an order of operations issue -- the build is going to happen first and the volume mount happens later when the container runs, so your container will no longer have access to the files built in the Dockerfile.
You could try to use
docker exec -it app_1 bash
to go into the container, trying to execute the
node index.js
command manually and see what's going on. Not 100% sure if the 'node' docker images have bash installed though..

Resources