- Create a Node.js Web App
- Creating a Dockerfile for our App
- Building our custom Docker Image
Create a Node.js Web App
We want to use express-generator to generate a basic Node Web App. We first need to install the generator globally on our machine:
npm install -g express-generator
We then run express-generator to scaffold an app for use, using the EJS Templating Engine - check out their website for more options - and put the source code into a folder named express-generator-app-docker:
express --view=ejs express-generator-dockerrized
To install dependencies we need to enter the created directory and run npm install :
cd express-generator-dockerrized & npm install
We can test our web app by running npm start and accessing http://localhos:3000 with a web browser:
Creating a Dockerfile for our App
MAINTAINER Mike Polinowski
COPY . /app
RUN npm install
ENTRYPOINT ['npm', 'start']
We are using the node Docker image as a base for our app. By just writing FROM node we will use the @latest version of Node.js available on the Docker Hub - specify a version when required - e.g.
The Environment Variable can be used to set, e.g. the Node Envrionment. Our app, as created by express-generator, also allows to change the port, the application is running on, to a different value, depending on the environment port defined here (see ./bin/www for how this is done).
Copy copies the source code into a folder inside the container. The given example . /app copies everything from the current directory into an /app directory, that is generated inside the container.
The Working Directory sets the context where scripts are run. We are going to add an
npm install step, that needs to be run in the directory that contains our package.json.
The most common use-case for RUN is a Node Application of
npm install, to install our app dependencies, once our source code is copied into the container.
This exposes a port that our app will be reached through, once the container is running. When a PORT was defined as a Environment Variable (s. above), you can also use this value, by settings EXPOSE $PORT
The Entrypoint allows you to configure a container that will run as an executable. Point it to the images main command. Since we installed our app through express-generator, the main file to run would be ./bin/www. In our case, the file will be executed by
node ./bin/www. But checking the generated package.json file, we can see that we already have an NPM Script for that, that allows us to simply call npm start instead.
Building our custom Docker Image
First we need to make sure that our Docker Image does not get unnecessary file - especially the node_modules and .git folder should be excluded. Just like with a .gitignore file, that excludes folders and files from git commits, we can create a .dockerignore file:
Now we can run the docker build command.
docker build -f Dockerfile -t expressapp/node .
This will run the
build function of Docker using the our Dockerfile (Note: you don't have to add the
-f flag when naming your file Dockerfile. The flag is useful when you have more then one Dockerfiles for different scenarios and have to give them different names accordingly.). The
-t flag adds a tag to the Docker image - this can be your docker hub username, or a build version, for internal use. The
. in the end signifies that docker should search for your code in the current work directory.
You can check if the image was build by typing
And run the container by typing:
docker run -d -p 8080:3000 expressapp/node
This command will run your container in
-d daemon mode in the background and set the external port of your app to 8080 (the internal port is set by the express app to 3000). You can verify that your app is running by typing:
You now have your app running inside the container and can access it by opening http://localhost:8080 inside your web browser:
You can stop and delete the container (the docker image stays in place - so you can always restart it) by:
docker stop c165
docker rm c165
The c165 are the first characters of the Container ID and can be used as a selector - of course, the ID will differ every time you rerun the container.
If you want to remove the complete image, you first have to check the image ID (just as shown above, you just need to type the first few characters to select the image - e.g. 9190) by typing
docker images, then delete it with
docker rmi 9190