X

Docker for NodeJS application using VSCode

nodejs-vscode-docker-logo

In this post, we will continue our previous nodejs weather application and introduce Docker for NodeJS application using VSCode. We will build our application and host it in docker by adding a Dockerfile. We will modify our code to take the APIKEY from an environment variable.

Create Dockerfile

Let’s launch our editor VSCode again with our solution and add the .dockerignore file first, since there are things that we do not want in our Docker image, kind of like gitignore.

node_modules
npm-debug.log
.vscode

Next add a Dockerfile with vscode so that we can build our image, we will use the carbon-alpine image which is v8 of nodejs, the reason we choose alpine is because its small and has minimal size and is secure.

Carbon is the latest LTS (long term support) version of node
#base image to use
FROM node:carbon-alpine

#the app directory
WORKDIR /usr/src/app

#copy package.json and package-lock.json
COPY package*.json ./

#build the code for production, and install app dependencies
RUN npm install --only=production

#bundle source code inside the Docker image
COPY . .

#Bind port to 3000
EXPOSE 3000

#RUN the application
CMD ["npm", "start"]

Above we will create a working directory and copy our package*.json then we run npm to install our packages. We also expose the default port 3000 and we run our application with npm start.

Note: using –only=production will run npm in production (will not download devDependencies)

Modify our source code

Before we build our image, we need to modify our app.js such that the APIKEY is no longer in the source code. Let’s make it so that it takes it from an environment variable. In doing so we will need to pass our APIKEY in our environment when we start to run our docker image, more on this later.

let apiKey = process.env.APIKEY;
app.set('apiKey', apiKey);

Build our NodeJS Image

Now that we modified app.js we can now go back to our docker file and build our image. Hit Ctrl+` in your vscode to launch terminal.

$docker build -t /myweatherapp .

Once finished building you can see your docker image by this command

$docker images 

taswar/myweatherapp         latest              d6abb08fcf9f        7 seconds ago       76.1MB

Run the image

Since we modified app.js we now need to inject the APIKEY into our docker image, we can do so with this command in vscode terminal using powershell. You need to use the proper APIKEY that you have got from openweather. We are also exposing the inside port 3000 to our local machine port of 8080

$docker run -p 8080:3000 -e APIKEY=1234 -d taswar/myweatherapp

Now we should be able to view our application on http://localhost:8080

weatherapp-8080

Security Issue

So you may think that now that we pass our APIKEY through the environment we are all good, but there is still a security issue here. If someone hacks into your machine that runs docker they are still able to see your secrets. Say What???

Say What?

Lets try to inspect our docker container by using the following commands, first lets find out the container id that docker is running under

$ docker ps
CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                    NAMES
e1fe8eb2d995        taswar/myweatherapp   "npm start"              35 minutes ago      Up 35 minutes       0.0.0.0:8080->3000/tcp   romantic_jennings

Now we can inspect the container by using this command, we don’t have to type the entire id, the first 3 characters would do the trick.

$ docker inspect e1f

If we look at the config section of the inspect we will see our APIKEY is in plain text

 "Config": {
            "Hostname": "e1fe8eb2d995",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "3000/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "APIKEY=1234", // 

Now you may say someone needs to have root access to view this information but maybe there is a better way we can mitigate this by maybe using a Token. This is where a secret key management comes in to help in storing your secrets. In the next blog post we will go over what Vault is and how it helps us in storing secrets and exposing a token for our docker container to consume without us exposing the APIKEY.

The source code of this can be found at https://github.com/taswar/nodejs-weather-app

Taswar Bhatti:
Related Post