Docker Container exits upon running with "sh -c" - node.js

I am trying to run a webserver (right now still locally) out of a docker container. I am currently going step by step to understand the different parts.
Dockerfile:
FROM node:12.2.0-alpine as build
ENV environment development
WORKDIR /app
COPY . /app
RUN cd /app/client && yarn && yarn build
RUN cd /app/server && yarn
EXPOSE 5000
CMD ["sh", "-c","NODE_ENV=${environment}", "node", "server/server.js"]
Explanation:
I have the "sh", "-c" part in the CMD command due to the fact that without it I was getting this error:
docker: Error response from daemon: OCI runtime create failed:
container_linux.go:346: starting container process caused "exec:
\"NODE_ENV=${environment}\": executable file not found in $PATH":
unknown.
Building the container:
Building the container works just fine with:
docker build -t auth_example .
It takes a little while since the build context is (even after excluding all the node_modules) roughly 37MB, but that's okay.
Running the container:
Running the container and the app inside works like a charm if I do:
MyZSH: docker run -it -p 5000:5000 auth_example /bin/sh
/app # NODE_ENV=development node server/server.js
However, when running the container via the CMD command like this:
MyZSH: docker run -p 5000:5000 auth_example
Nothing happens, no errors, no nothing. The logs are empty and a docker ps -a reveals that the container was exited right upon start. I did some googling and tried different combinations of -t -i -d but that didn't solve it either.
Can anybody shed some light on this or point me into the right direction?

The problem is you're passing three arguments to sh -c whereas you'd usually pass one (sh -c "... ... ...").
It's likely you don't need the sh -c invocation at all; use /usr/bin/env to alias that environment variable instead (or just directly pass in NODE_ENV instead of environment):
FROM node:12.2.0-alpine as build
ENV environment development
WORKDIR /app
COPY . /app
RUN cd /app/client && yarn && yarn build
RUN cd /app/server && yarn
EXPOSE 5000
CMD /usr/bin/env NODE_ENV=${environment} node server/server.js

Related

how to run feedconsumers and consumers multiple for kafka in docker?

So I have this docker file and i want to run feed-consumers and consumers multiple times and i tried to do so. We have a node.js application for feed-consumers and consumer and pass user_levels to it.
I just want to ask is this the right approach?
FROM ubuntu:18.04
# Set Apt to noninteractive mode
ENV DEBIAN_FRONTEND noninteractive
# Install Helper Commands
ADD scripts/bin/* /usr/local/bin/
RUN chmod +x /usr/local/bin/*
RUN apt-install-and-clean curl \
build-essential \
git >> /dev/null 2>&1
RUN install-node-12.16.1
RUN mkdir -p /usr/src/app
COPY . /usr/src/app
WORKDIR /usr/src/app
#RUN yarn init-cache
#RUN yarn init-temp
#RUN yarn init-user
RUN yarn install
RUN yarn build
RUN node ./feedsconsumer/consumer.js user_level=0
RUN for i in {1..10}; do node ./feedsconsumer/consumer.js user_level=1; done
RUN for i in {1..20}; do node ./feedsconsumer/consumer.js user_level=2; done
RUN for i in {1..20}; do node ./feedsconsumer/consumer.js user_level=3; done
RUN for i in {1..30}; do node ./feedsconsumer/consumer.js user_level=4; done
RUN for i in {1..40}; do node ./feedsconsumer/consumer.js user_level=5; done
RUN for i in {1..10}; do node ./consumer/consumer.js; done
ENTRYPOINT ["tail", "-f", "/dev/null"]
Or is there any other way around?
Thanks
A container runs exactly one process. Your container's is
ENTRYPOINT ["tail", "-f", "/dev/null"]
This translates to "do absolutely nothing, in a way that's hard to override". I typically recommend using CMD over ENTRYPOINT, and the main container command shouldn't ever be an artificial "do nothing but keep the container running" command.
Before that, you're trying to RUN the process(es) that are the main container process. The RUN only happens during the image build phase, the running process(es) aren't persisted in the image, the build will block until these processes complete, and they can't connect to other containers or data stores. These are the lines you want to be the CMD.
A container only runs one processes, but you can run multiple containers off the same image. It's somewhat easier to add parameters by setting environment variables than by adjusting the command line (you have to replace the whole thing), so in your code look for process.env.USER_LEVEL. Also make sure the process stays as a foreground process and doesn't use a package to daemonize itself.
Then the final part of the Dockerfile just needs to set a default CMD that launches one copy of your application:
...
COPY package.json yarn.lock .
RUN yarn install
COPY . .
RUN yarn build
CMD node ./feedsconsumer/consumer.js
Now you can start a single container running this process
docker build -t my/consumer .
docker run -d --name consumer my/consumer
And you can start multiple containers to run the whole set of them
for user_level in `seq 5`; do
for i in `seq 10`; do
docker run -d \
--name "feed-consumer-$user_level-$i" \
-e "USER_LEVEL=$user_level" \
my/consumer
done
done
for i in `seq 10`; do
docker run -d --name "consumer-$i" \
my/consumer \
node ./consumer/consumer.js
done
Notice this last invocation overrides the CMD to run the alternate script; this becomes a more contorted invocation if it needs to override ENTRYPOINT instead. (docker run --entrypoint node my/consumer ./consumer/consumer.js)
If you're looking forward to cluster environments like Kubernetes, it's often straightforward to run multiple identical copies of a container, which is what you're trying to do here. A Kubernetes Deployment object has a replicas: count, and you can kubectl scale deployment feed-consumer-5 --replicas=40 to change what's in the question, or potentially configure a HorizontalPodAutoscaler to set it dynamically based on the topic length (this last is involved, but possible and rewarding).

docker port mapping ignored when adding volumes to the run command

When I start my docker container with:
docker run -it -d -p 8081:8080 --name ${APP_CONTAINER_NAME} ${APP_IMAGE}
I can access my web application just fine in my browser on: localhost:8081
But if I instead run it with the two volumes below:
docker run -it -d -p 8081:8080 -v ${PWD}:/app -v /app/node_modules --name ${APP_CONTAINER_NAME} ${APP_IMAGE}
The port mapping is ignored - I cannot access it at localhost:8081 but I can access it at localhost:8080.
My dockerfile has:
FROM node:8-alpine
RUN apk update && apk add bash
RUN npm install -g http-server
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
EXPOSE 8080
CMD [ "http-server", "dist" ]
Why does adding the volumes to the second docker run command ignore the port mapping from 8081 to 8080?
As suggested below running without -d (but with volumes):
docker run -it -p 8081:8080 -v ${PWD}:/app -v /app/node_modules --name ${APP_CONTAINER_NAME} ${APP_IMAGE}
gives:
Starting up http-server, serving dist
Available on:
http://127.0.0.1:8080
http://172.17.0.2:8080
Hit CTRL-C to stop the server
But I cannot access it on localhost:8080 or localhost:8081 even though the container is indeed running:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
603b1bf02d58 app-image "http-server dist" 11 seconds ago Up 5 seconds 0.0.0.0:8081->8080/tcp app-container
When I instead run it without volumes but still map to 8081 it works:
Starting up http-server, serving dist
Available on:
http://127.0.0.1:8080
http://172.17.0.2:8080
Hit CTRL-C to stop the server
and I can access it on localhost:8081. So something in the application must be messed up when adding the volumes just not sure what. I have also tried to run:
docker volume prune
before starting the container but it has no effect. Any ideas why creating the volumes prevents the application from being accessed?

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.

docker: Command "/bin/sh" not found

ENV PORT=3000
ENV NODE_ENV=production
EXPOSE $PORT
WORKDIR $APP_DIR
COPY yarn.lock package.json $APP_DIR/
RUN ["/usr/local/bin/yarn"]
COPY . $APP_DIR
ENTRYPOINT ["/usr/local/bin/yarn", "run"]
CMD ['dev']
Was running this using this command
docker run --rm -p 3000:3000 my-app:latest
And the console outputs
yarn run v0.17.9
error Command "/bin/sh" not found.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
I expect /usr/local/bin/yarn run dev to be executed inside docker, am I missing something?
Try switching to double quotes, single quotes aren't valid for a json string:
CMD ["dev"]

Docker cannot run on build when running container with a different user

I don't know the specifics why the node application does not run. Basically I added a dockerfile in a nodejs app, and here is my Dockerfile
FROM node:0.10-onbuild
RUN mv /usr/src/app /ghost && useradd ghost --home /ghost && \
cd /ghost
ENV NODE_ENV production
VOLUME ["/ghost/content"]
WORKDIR /ghost
EXPOSE 2368
CMD ["bash", "start.bash"]
Where start.bash looks like this:
#!/bin/bash
GHOST="/ghost"
chown -R ghost:ghost /ghost
su ghost << EOF
cd "$GHOST"
NODE_ENV={$NODE_ENV:-production} npm start
EOF
I usually run docker like so:
docker run --name ghost -d -p 80:2368 user/ghost
With that I cannot see what is going on, and I decided to run it like this:
docker run --name ghost -it -p 80:2368 user/ghost
And I got this output:
> ghost#0.5.2 start /ghost
> node index
Seems, like starting, but as I check the status of the container docker ps -a , it is stopped.
Here is the repo for that but, the start.bash and dockerfile is different, because I haven't committed the latest, since both are not working:
JoeyHipolito/Ghost
I manage to make it work, there is no error in the start bash file nor in the Dockerfile, it's just that I failed to build the image again.
With that said, you can checkout the final Dockerfile and start.bash file in my repository:
Ghost-blog__Docker (https://github.com/joeyhipolito/ghost)
At the time I write this answer, you can see it in the feature-branch, feature/dockerize.

Resources