Run your Node.js app from a Docker Container
01 Create your Node App
Keeping it simple - create a folder and use Node.js to npm install Express.js
npm init
npm install express
The init will create a package.json file - we can add a start script to it to start our Express Webserver:
'scripts': {
'start': 'node ./index.js'
}
Then configure your webserver by adding the index.js file to the root directory:
//Load express module with `require` directive
var express = require('express')
var app = express()
//Define request response in root URL (/)
app.get('/', function (req, res) {
res.send('Hello World!')
})
//Launch listening server on port 3000
app.listen(3000, function () {
console.log('app listening on port http://localhost:3000!')
})
You can test the webserver by running the npm script from your console:
npm start
And access http://localhost:3000 in your preferred web browser - you should be greeted by:
02 Dockerizing your Node.js application
If you did not so far, first install Docker on your computer.
The Docker container is launched on the basis of a Docker image, a template with the application details. The Docker image is created with instructions written in the Dockerfile. Let’s add Dockerfile to the directory with our application:
FROM node:latest
# Create app directory
WORKDIR /usr/src/app
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./
RUN npm install
# If you are building your code for production
# RUN npm install --only=production
# Bundle app source
COPY . .
EXPOSE 8080
CMD [ 'npm', 'start' ]
- The first thing we need to do is define from what image we want to build from. Here we will use the latest version of node available from the Docker Hub: FROM node:latest
- Next we create a directory to hold the application code inside the image, this will be the working directory for your application: WORKDIR /app
- This image comes with Node.js and NPM already installed so the next thing we need to do is to install your app dependencies using the npm binary: COPY package*.json ./, RUN npm install
Note that, rather than copying the entire working directory, we are only copying the package.json file.
- To bundle your app's source code inside the Docker image, use the COPY instruction: COPY . /app
- Your app binds to port 3000 so you'll use the EXPOSE instruction to have it mapped by the docker daemon: EXPOSE 3000
- Last but not least, define the command to run your app using CMD which defines your runtime. Here we will use the basic npm start which will run node server.js to start your server: CMD [ 'npm', 'start' ]
Create a .dockerignore file in the same directory as your Dockerfile with following content:
node_modules
npm-debug.log
This will prevent your local modules and debug logs from being copied onto your Docker image and possibly overwriting modules installed within your image.
Building your image
Go to the directory that has your Dockerfile and run the following command to build the Docker image. The -t flag lets you tag your image so it's easier to find later using the docker images command:
docker build -t hello-world .
You can now list the Docker image:
docker images
Running the Container
Running your image with -d runs the container in detached mode, leaving the container running in the background. The -p flag redirects a public port to a private port inside the container. Run the image you previously built:
docker run -p 8080:3000 hello-world
The Container is now running and listening on Port 3000 - to access the container we have to use the exposed Port 8080 on localhost or the local IP address of the machine we running it on.
Running the Container with Kitematic
Alternatively, we can use the graphical user interface Kitematic. First install the Docker Toolbox for Windows and macOS and start Kitematic. Choose My Images and Create on our hello-world container:
Our container is now running:
Be aware that the Port 3000 that we defined is only the internal Docker Port. You can check (and change) the exposed port under Settings in the Hostname/Ports tab:
As seen above, our container is exposed on Port 32772.
And can be accessed on http://localhost:32772 as well as on the local network IP (in this case the 192.168.1.112):
Further Readings:
https://medium.com/statuscode/dockerising-a-node-js-and-mongodb-app-d22047e2806f