If you need to put express.js in docker, that is, dockerize your Express.js app, look no further. For the ones who are familiar with docker, just use the following dockerfile. Otherwise, we have an explanation of it line-by-line below.
FROM node:12
WORKDIR /usr/src/app
COPY package*.json ./
COPY index.js ./
COPY .babelrc ./
COPY src ./src
COPY node_modules ./node_modules
EXPOSE 80
CMD ["npm", "run", "start"]
Express.js in Docker Explained
We have three main parts in this dockerfile that realize help us dockerize our express.js app. First, we need to prepare the container from the right parent. Then, we need to copy all the files of our application. Finally, we expose it for external access.
Prepare the Container
With the first two lines, we prepare the container.
FROM node:12
WORKDIR /usr/src/app
Here, we start by extending the Node.js container – a Debian-based Linux image that comes with Node.js included. We can pick the version of Node that we prefer, as the version of the image corresponds to the Node.js version. So, in this example, we are going with Node.js version 12.
The other line is about specifying the working directory, the place where we will execute any other command from here onward. We are specifying /usr/src/app
because this is where the Node.js server would like to have the files of our applications. In other words, the original container image with Node expects us to put the application there. Even if, technically, we could place it somewhere else, this is the recommended practice.
Copying the Express.js app inside Docker
Now, we need to copy our app inside the container image. All the following lines, combined, will do so.
COPY package*.json ./
COPY index.js ./
COPY .babelrc ./
COPY src ./src
COPY node_modules ./node_modules
We expect to build this container image on a machine that has Node.js also installed, and that also has installed our Express.js application (with npm install
). We start by copying both package.json
and package-lock.json
, thanks to the star wildcard character in the first line. We then proceed to copy our entry-point index.js
, and since in our case we are using Babel also our .babelrc
file. Then, we copy all our source folder and all our node_modules
folder.
This is why it’s important to have installed our app in the local machine before building the container image. Otherwise, the node_modules
folder will be empty and our container will lack dependencies.
Alternatively, we could run npm install
inside the container as a command, but this would not work in case we use private NPM registries. To make it work in that case, we would need to ship authentication credentials inside our docker image and remove them later, a cumbersome and risky process.
Exposing the Container
Now, the container image contains our app. We need to take just one final step to expose it.
EXPOSE 80
CMD ["npm", "run", "start"]
With these two lines, we first say that the container will listen on port 80, enabling incoming HTTP. Then, we say that, by default, when we launch the container it should run npm run start
, which in our package.json
must be defined as the command that starts express.js.
Our best practice here is to expose containers and internal services on port 80. Then, we can put an NGINX load balancer in front of them to expose them over the Internet using HTTPS. In this way, our container will be more lightweight and will not have to deal with SSL certificates.
In a Nutshell
Express.js and Docker are two powerful technologies. Combining them together is a no-brainer way to success.
As we just saw, it is easy to put Express.js in Docker. With that simple dockerfile, you can do that literally in seconds. Obviously, you will need an existing Express.js app to dockerize. If you are starting out, we have a good tutorial on Express.js as well that you should check out.