Run NodeJS and NGINX

Hi guys

As part of learning docker, I’ve built an image (Ubuntu 14.04 LTS) with NodeJS and NGINX installed.
On my Dockerfile I create an app with express, install angular and then I have a problem

NGINX is not running when the container is created (maybe because it configured to pass traffic to port 3000, and no process listens to it), and for the app to run I have to write:
CMD npm start on my Dockerfile

Without NGINX running, the app won’t work
I’ve tried to create /etc/init/nginx.conf making upstart to run it on boot, but it doesn’t work

What can I do to create my app, and still make both nginx and npm to run?

Thanks : )

Does NGINX run and then exit, or does it simply not start? I’m also in the learning phase, and I found in my Apache containers, Apache would start and exit right away. This was because the CMD I was passing, apachectl start or service apache start would run and exit…at which point the container exited. :slightly_smiling: The resolution was to simply run Apache in the foreground with -DFOREGROUND…or a simple ps -e | grep apache sleep loop.

It looks like you are doing something similar with npm start. Can you run it in the foreground or build a sleep loop around it?

EDIT:
In your case, since you need both process running, writing a wrapper script might be the better way to go since they both cannot be in the foreground. I am curious though if there is a “better” way to manage this scenario.

Hi Tim
Thanks for the answer

I haven’t searched deeply in nginx or upstart logs, but I think I’m having the same thing you have described

The dockerfile had:
RUN service nginx start
CMD npm start
The result - npm on, nginx off

Then I’ve tried:
RUN npm start &
CMD service nginx start
The result - npm off, nginx on

Then I’ve tried to use some ‘daemon off’ on nginx command - didn’t work
I read that some things won’t run because the container is attached, so I used - d on ‘docker build’ command

What do you mean in wrapper script? On which level should I write it?
I think this scenario should have an elegant solution

Here is what I use for an Apache container.

startApache.sh

'#!/bin/bash
apachectl -DFOREGROUND

Dockerfile

FROM debian

RUN apt-get update && apt-get install -y
apache2
&& rm -rf /var/lib/apt/lists/*

ENV APPDIR myapp
RUN mkdir -p “$APPDIR/bin” “$APPDIR/etc”
COPY *.sh “$APPDIR/bin/”
WORKDIR $APPDIR

EXPOSE 80 443
CMD “/$APPDIR/bin/startApache.sh”

Now, in startApache.sh, I could have done something like this:

while ps -e | grep apache2
do
sleep 5
done

This script runs indefinitely as long as the apache2 process is running, therefore the container will not exit until this script exits. In reality, you would want better error trapping, etc. in a script like this, but it get the point across. You should be able to use something similar to this for your use case.

I know it isn’t the most elegant solution, but it is workable.

I don’t think I will implement this kind of a solution on production : ))

EDIT:

I do believe that 2 containers, one contains NGINX and the other NodeJS, is a better solution, but I prefer one container for both

Have you tried this as the CMD?

nginx -g ‘daemon off;’

In your first post, you did mention you tried a daemon-off option, but wanted to confirm if you specified it like this or in the conf file…

Did it in the Dockerfile
I don’t remember if it was CMD, RUN or maybe tried both options one way or another

Something like this should work. The container started with nginx in the foreground so it didn’t exit. To test, I was able to bring up the welcome page on port 80.

Of course, you’ll need to tweak to add npm, etc…

Dockerfile

FROM ubuntu

RUN apt-get update && apt-get install -y
nginx
&& rm -rf /var/lib/apt/lists/*

COPY nginx.conf /

ENTRYPOINT /usr/sbin/nginx -g ‘daemon off;’

Run

docker run -d -p 80:80 tcrockett/nginx

I am wondering what was the solution for the problem. I also wanted to use nginx as reverse proxy on the same server. I dont want to create reverse proxy container

May I ask why you want to run Nginx and Node in one container? It’ll save you a lot of time if you go with the industry default and run each in a separate container, instead of banging your head on making it work in a single container.

Hi Maxim,

I am creating containers in Azure container instance and wanted run a simple site (rather than hosting it via app service)

Even though not standard approach i was able to achieve running a shell command in docker file

#copy the reverse proxy file which redirects port 3000 traffic to port 80 nginx server

COPY reverse_proxy.app /etc/nginx/sites-available/default
CMD [ “sh”,"./start.sh" ]

start.sh

#restart the service

service nginx --full-restart

#Run to start the node instance on container

node ./bin/www

reverse_proxy.app

server{
listen 80;
location / {

    proxy_pass  "http://localhost:3000";
}

}