Development of NodeJS application with Docker and Typescript [Part 2]

Vincent Schoener
5 min readJun 18, 2019

--

This is the second of the series describing, as a developer, how we can build a great application with NodeJs under TypeScript and using Docker to work locally and deploy the image.

Just before we dive into this part, I recommend you to have some knowledge with Docker or, if you can, take time to train yourself building image because I’m not gonna explain each basics command I’ll use here. Still, don’t worry, this is really easy to use after all and I’ll go through each block I wrote down here :).

Part 2— Creating the image from Dockerfile

Ok let’s go, there are few steps we need to tackle together!

This part is available here if you need https://github.com/vschoener/Docker-TS-development/tree/master/medium_part2

Edit: I changed the slim image by the alpine because I thought it will be smaller but it was the inverse. 🙄

Create a Multi-Stage Docker image

Yes, you read it! Multi-Stage! This is a better and smarter way to create the Dockerfile because it enables you to create smaller images with better caching and smaller security footprint. It can also be used with docker-compose and the CI.

Let’s start now and create a Dockerfile at the root directory of the project. Then add the following block

Dockerfile builder stage

This is the first stage (step) building our code, we use a complete Node image in case we need to debug. Here we are just getting the packages, ts config file, and the source directory, we are not on the production step (node NODE_ENV and whatsoever) meaning all the packages will be installed.

Then add the following code to the file containing the last stage

Dockerfile production stage

This block is the production step, it just required to install the production package, and retrieving the distribution file (compiled TypeScript file)
We would also add an EXPOSE and other settings you may require, but most of the time it should be sufficient.
As you noticed, we use a fresh and new folder /app to put the build folder.

In this configuration, the package.json file is also available and you can run production command from npm if you are willing to. I don’t put a CMD here cause you can decide from your platform configuration how to start the process but most of the time you find a CMD ["node", "/app/build/boot.js”] at the end or an entrypoint.

Ok, enough talking, let’s try this docker image and see how it goes.

Test our fresh and newly Docker file

Add the following command in your package.json

"build": "tsc"

And build the image usingdocker build -t "docker-medium" ..
Once done, you can check your image with the following command

~
❯ docker images | grep “docker-medium”
dockermedium latest 3fa00f5c0961 9 seconds ago 131MB# With a slim image, you will have this size
dockermedium latest 293b6e498ae9 2 minutes ago 204MB

Did you notice the image size? Only 131 MB!
Ok just to remind you a bit, usually, the image can easily reach over 900MB. You can check it yourself if you want by creating another Dockerfile.big as an exercise without using multi-stage :)
The image size may vary depends of the packages at a time, but it’s a node project and you need them on production.

Alright, now we have this image, we can run it with the following command

~
❯ docker run --rm docker-medium node build/boot.js
Ready fox! I'm listening, 2

Awesome! It works! The code is running in our container.

--rm ? Yes don’t forget to add this one when running your image locally, you will quickly end with a tone of container on your machine eating all your storage

Ok, last but not least, to finish this part, you can go in your container and check the files or run the app by using this command

~
❯ docker run --rm -ti docker-medium bash
root@8d8ea289fd80:/app# ls
build node_modules package-lock.json package.json
root@8d8ea289fd80:/app# node build/boot.js
Ready fox! I'm listening, 2
root@8d8ea289fd80:/app#

--ti is a combination of 2 options, -t to allocate a pseudo-TTY and -i keeps STDIN open even if not attached. Finally, the bash to run our custom command instead of the one described in the Dockerfile.

Now we have the Dockerfile ready to be used, we can move on the third part, The use ofdocker-compose to customize our development environment and also connect external service and mount volume inside with ease.

Hope you enjoyed this part even if it’s a small one, but I feel it was better to go with the basics of building each step of the app with you before going to the last part in one shot.
Feel free to comment your feedback if anything is wrong, not working, ununderstandable and so whatever :)

If you need to go on the previous part (1) here is the link

Bonus

This come a bit late but I’ve made an article explaining how to go further optimizing the image when you still need to install packages in the production build. Don’t let them eat the space! We can still optimize the build!

--

--

Vincent Schoener

Love High tech, computer, and gaming. Senior Developer ready for Business perspective, MBA in progress #sport #moto #game #photo #travel