I recently switched all applications for my company to Yarn because it is just so fast. However, integrating with Docker is a little more complicated. Here, I’ll walk through the Dockerfile (and two other files that you need) to build an efficient and fast Docker deployment.

The three files you need

I’ve seen a lot of Node.js Dockerfile examples, but what a lot of them miss is that if you want to build a Docker image that includes modules with native components, you need three files:

1) build.sh

The final file is your build bash script. This file is important so that you only have to type one command (i.e. ./build.sh) to build your container and upload it.

2) Dockerfile

You need the actual Dockerfile which will manage building your application.

3) .Dockerignore

If you have any native modules, such as the popular bcrypt, you’ll need a .Dockerignore file as well.

So let’s get started…

The build script

Here is the structure of my build script:

#!/bin/bash # install node_modules and deploy application to production

yarn

npm run deploy # build your docker image

docker build... # push your docker image

docker push... # run cleanup commands so you don't amass images that you don't need

docker rm -v $(docker ps -a -q -f status=exited) 2>&1

docker rmi $(docker images -f "dangling=true" -q) 2>&1

What’s important is the order of things. Unlike some other Docker setups that I’ve seen, I prefer to deploy the application to production from my bash script rather than the Dockerfile. The big reason for this is that I don’t need to install global build modules in my Dockerfile. I simply deploy from my computer and add the final files to my Docker image. The other important piece is to run the cleanup at the end. Otherwise, you’ll have gigs of Docker images taking up space on your computer.

The Dockerfile

Here is the structure of my Dockerfile:

# Set the base image

FROM node:X.X.X # File Author / Maintainer

MAINTAINER XXXXXXXXX # Define working directory

WORKDIR /var/www/api

RUN apt-get update && apt-get install -y apt-transport-https

RUN curl -sS

RUN echo "deb

RUN apt-get update && apt-get install yarn # Install yarnRUN apt-get update && apt-get install -y apt-transport-httpsRUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.listRUN apt-get update && apt-get install yarn # Install node_modules with yarn

ADD package.json yarn.lock /tmp/

RUN cd /tmp && yarn

RUN mkdir -p /var/www/api && cd /var/www/api && ln -s /tmp/node_modules # Copy app

COPY . /var/www/api # Expose port

EXPOSE 8000 # Run app

CMD ["npm","start"]

What’s important here is that you install yarn then do other things because it will cache on subsequent builds. In addition, by placing your package.json & yarn.lock files in a /tmp/ folder, you can install your node_modules in a /tmp/ folder, then copy them to the main folder which also caches node_modules. Finally, you can copy your application into the Docker image (assuming you’ve already deployed it).

The .Dockerignore

Here is the structure of my .Dockerignore:

node_modules

That’s right, this file only has one line. The reason you need this line is because when you install your node_modules on your personal machine, modules like bcrypt cannot simply be copied over. Bcrypt must be installed in the environment it will be used because it must be compiled for that environemnt. By ignoring the node_modules folder, don’t copy it over, but rather use the folder you generate in the Dockerfile.

Final Thoughts

I don’t consider myself an expert, but based on my research, this is the best Docker setup for my needs. However, I’m always open to learning more, and if you have suggestions to improve this setup, please let me know!