Skip to main content

How to wrap your Source Code into a Docker Container

Shanghai, China

As an example, we are going to use express-generator to scaffold a Node.js Web App and wrap it's source code into a Docker Container.

Github Repository

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:

Express App in Docker Container

Creating a Dockerfile for our App

The Dockerfile is a text file that contains all the commands that the docker build command uses, in order, to build a our Docker image.

FROM        node:latest
MAINTAINER  Mike Polinowski
ENV         NODE_ENV=production
ENV         PORT=3000
COPY        . /app
WORKDIR     /app
RUN         npm install
EXPOSE      3000
ENTRYPOINT  ['npm', 'start']

FROM

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. node:latest, node:9.10.2

ENV

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

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.

WORKDIR

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.

RUN

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.

EXPOSE

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

ENTRYPOINT

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:

.git
Dockerfile*
node_modules

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.

Express App in Docker Container

You can check if the image was build by typing

docker images

Express App in Docker Container

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:

docker ps

Express App in Docker Container

You now have your app running inside the container and can access it by opening http://localhost:8080 inside your web browser:

Express App in Docker Container

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.

Express App in Docker 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