Why doesn't the container start? - node.js

My docker-compose file is simple:
npm:
image: node
volumes:
- C:\Users\Samir\npm\:/home/dev
container_name: npm
When I run it:
docker-compose up -d
I get:
Starting npm
Then, nothing happens:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Any idea?

Per default the Node image is designed for interactive use and simply starts a Node REPL. When you run docker-compose up -d the Node REPL will start and exit immediately as no interactive terminal is availabe. Try:
docker-compose run -it npm
Note that this is currently not supported on Windows, you will need to use docker run -it -v ... node instead.
If you want to start your application instead simply override the default command in your docker-compose.yml

Related

NPM start script runs from local shell but fails inside Docker container command

I have a Node app which consists of three separate Node servers, each run by pm2 start. I use concurrently to run the three servers, as a start-all script in package.json:
"scripts": {
...
"start-all": "concurrently \" pm2 start ./dist/foo.js \" \"pm2 start ./dist/bar.js \" \"pm2 start ./dist/baz.js\"",
"stop-all": "pm2 stop all",
"reload-all": "pm2 reload all",
...
}
This all runs fine when running from the command line on localhost, but when I run it as a docker-compose command - or as a RUN command in my Dockerfile - only one of the server scripts (a random one each time I try it!) will launch, but then immediately exit. In my --verbose docker-compose output I can see the pm2 panel (listing name, version, mode, pid, etc.), but then this error message:
pm2 start ./dist/foo.js exited with code 0.
N.B: This is all with Docker running locally (on a Mac Mini with 16GB of RAM), not on a remote server.
If I docker exec -it <container_name> /bin/bash into the container and the run npm run start-all manually from the top level of the src directory (which I COPY over in my Dockerfile) everything works. Here is my Dockerfile:
FROM node:latest
# Create the workdir
RUN mkdir /myapp
WORKDIR /myapp
# Install packages
COPY package*.json ./
RUN npm install
# Install pm2 and concurrently globally.
RUN npm install -g pm2
RUN npm install -g concurrently
# Copy source code to the container
COPY . ./
In my docker-compose file I simply list npm run start-all as a command for the Node service. But it makes no difference if I add it to the Dockerfile like this:
RUN npm run start-all
What could possibly be going on? The pm2 logs show report nothing other than that the app has started.
the first reason is pm2 start app.js start the application in background so that is why your container stops as soon as it runs pm2 start.
You need to start an application with pm2_runtime, it starts an application in the foreground. also you do not need concurrently, pm2 process.yml will do this job.
Docker Integration
Using Containers? We got your back. Start today using pm2-runtime, a
perfect companion to get the most out of Node.js in production
environment.
The goal of pm2-runtime is to wrap your applications into a proper
Node.js production environment. It solves major issues when running
Node.js applications inside a container like:
Second Process Fallback for High Application Reliability Process Flow
Control Automatic Application Monitoring to keep it always sane and
high performing Automatic Source Map Discovery and Resolving Support
docker-pm2-nodejs
The second important thing, you should put all your application in pm2 config file, as docker can only run the process from CMD.
Ecosystem File
PM2 empowers your process management workflow. It allows you to
fine-tune the behavior, options, environment variables, logs files of
each application via a process file. It’s particularly useful for
micro-service based applications.
pm2 config application-declaration
Create file process.yml
apps:
- script : ./dist/bar.js
name : 'bar'
- script : ./dist/foo.js
name : 'worker'
env :
NODE_ENV: development
then add CMD in Dockerfile
CMD ["pm2-runtime", "process.yml"]
remove command from docker-compose.
Docker and pm2 provide overlapping functionality: both have the ability to restart processes and manage logs, for example. In Docker it's generally considered a best practice to only run one process inside a container, and if you do that, you don't necessarily need pm2. what is the point of using pm2 and docker together?
discusses this in more detail.
When you run your image you can specify the command to run, and you can start multiple containers off of the same image. Given the Dockerfile you show initially you can launch these as
docker run --name foo myimage node ./dist/foo.js
docker run --name bar myimage node ./dist/bar.js
docker run --name baz myimage node ./dist/baz.js
This will let you do things like restart only one of the containers when its code changes while leaving the rest untouched.
You hint at Docker Compose; its command: directive sets the same property.
version: '3'
services:
foo:
build: .
command: node ./dist/foo.js
bar:
build: .
command: node ./dist/bar.js
baz:
build: .
command: node ./dist/baz.js

How to open remote shell to node.js container under docker-compose (Alpine linux)

I have a docker-compose.yml configuration file with several containers and one of the containers is node.js docker instance.
By some reason the docker instance returns error during start. In the result it's not possible to connect to the node.js container and investigate issue.
What is the simplest way to connect to the broken node.js under Alpine linux?
Usually in my docker-compose.yml
I just replace the command or entrypoint by :
command: watch ps
It's a bit hackish, but that keeps the container up.
Alternatively, once the image has been built, you can run it using docker. But then you have to do what you did in your docker-compose.yml file in your command, like mount volumes and open ports manually.
FOR DOCKER-COMPOSE
In case if you use docker-compose the simplest way is to add the following command line into your docker-compose.yml file.
services:
api:
build: api/.
command: ["/bin/sh", "-c", "while sleep 3600; do :; done"]
depends_on:
- db
- redis
...
also it need to comment line by line from bottom up inside the Dockerfile for node.js until the container will be able to start.
After the node.js container will be able to start you can easy connect to your container via
docker exec -it [container] sh
FOR DOCKER
You can simply add at the end of Dockerfile the following line
CMD echo "^D for exit" && wc -
and comment line by line (from bottom up) above this line until the container will be able to start.
You can docker-compose run an alternate command. This requires no changes in your Dockerfile or docker-compose.yml. For example,
docker-compose run --rm web /bin/sh
This creates a new container which is configured identically to what is requested in the docker-compose.yml (with environment variables and mounted volumes), except that ports: aren't published by default. It is essentially identical to docker run with the same options, except it defaults to -i -t being on.
If your Dockerfile uses ENTRYPOINT instead of CMD to declare the main container command, you need the same --entrypoint option. For example, to get a listing of the files in the image's default working directory, you could
docker-compose run --rm --entrypoint /bin/ls web -l
(If your ENTRYPOINT is a wrapper script that ultimately exec "$#" you don't need this.)

running docker container is not reachable by browser

I started to work with docker. I dockerized simple node.js app. I'm not able to access to my container from outside world (means by browser).
Stack:
node.js app with 4 endpoints (I used hapi server).
macOS
docker desktop community version 2.0.0.2
Here is my dockerfile:
FROM node:10.13-alpine
ENV NODE_ENV production
WORKDIR /usr/src/app
COPY ["package.json", "package-lock.json*", "npm-shrinkwrap.json*", "./"]
RUN npm install --production --silent && mv node_modules ../
RUN npm install -g nodemon
COPY . .
EXPOSE 8000
CMD ["npm","run", "start-server"]
I did following steps:
I run from command line from my working dir:
docker image build -t ares-maros .
docker container run -d --name rest-api -p 8000:8000 ares-maros
I checked if container is running via docker container ps
Here is the result:
- container is running
I open the browser and type 0.0.0.0:8000 (also tried with 127.0.0.1:8000 or localhost:8000)
result:
So running docker container is not rechable by browser
I also go into the container typing docker exec -it 81b3d9b17db9 sh and try to reach my node-app inside of container via wget/curl and that's works. I get responses fron all node.js endpoints.
Where could be the problem ? Maybe my mac can blocked connection ?
Thanks for help.
Please check the order of the parameters of the following command:
docker container run -d --name rest-api -p 8000:8000 ares-maros
I faced a similar. I was using -p port:port at the end of the command. Simply moving it to after 'Docker run' solved it for me.

Why app in docker container doesn't restart?

I've deployed some docker containers with golang apps. One of them I need to start by this command:
docker run --restart unless-stopped -it myapp /bin/bash
The next step I enter the container and edit some config files, then I run
go build main.go
and ./main
After that I press ctrl+q and leave it out.
Everything works perfectly and all my containers restart perfectly after restarting server. But there is one issue, when myapp container restarts, the golang application doesn't run while container still works. I have to enter this again and run ./main. How can I fixed it?
Dockerfile
FROM golang:1.8
WORKDIR /go/src/app
COPY . .
RUN go-wrapper download # "go get -d -v ./..."
RUN go-wrapper install # "go install -v ./..." RUN ["apt-get","update"]
RUN ["apt-get","install","-y","vim"]
EXPOSE 3000
CMD ["app"]
When you create a container and pass in /bin/bash as the command, that's as far as Docker cares. When the container restarts, it will start up another instance of /bin/bash.
Docker doesn't watch your shell session and see what things you do after it starts the command. If you want to actually run ./main as the command of the container, then you'll need to pass in /go/src/app/main as the command instead of /bin/bash.
Additionally, compiling code is something better done during the image build phase instead of at container runtime.

Start node app when running docker container from cli

I'm relatively new to Docker and have a node web server which I have added to a docker image. My image is built using packer, so I don't have a Dockerfile.
My question is when running the docker container on the command line with docker run -it -d <imageId> is there a way to pass in the command to run my web server that resides in the container?
So something like docker run -it -d <imageId> npm start
Got it working with
docker run -it -d -w /path/to/code/folder <imageName:version> node server.js 'daemon off;'

Resources