Writing a Dockerfile its fundamentals and optimizing it.

AbhijeetAbhijeet
3 min read

There are certain concepts of writing a dockerfile to make it secure , in this blog i will be showcasing how to write a docker file what things you should consider and how you could write a dockerfile more secured

Lets get started -

I am currently writing a dockerfile for my nodejs application

FROM ubuntu:22.04
RUN apt update
RUN apt install nodejs npm -y
COPY . .
RUN npm install
EXPOSE 3000
CMD ["npm","run","dev"]

Lets go through the Dockerfile above -
FROM <image-name>:<image:tag> - using base image as ubuntu
RUN - This used to install the required packages and dependencies
COPY <source> <destination> - to copy the source code from host to image
EXPOSE - Description of where the application is listening on
CMD - This defines the commands to run when to run a container using this image
if i run this Dockerfile lets see the output and how we can optimize the dockerfile -

Lets run the image on container with port 3000 and see the output

docker build . -d -p 3000:3000 my-nodejs-app

Lets see the image size -

The image size is significantly large and we can reduce it if we optimize the dockerfile and create a new image with required dependency

Optimization of Docker image -

  • From our previous dockerfile we run multiple RUN commands to update packages and install packages,Each RUN command creates a new layer which increases the image size we can eliminate this by combine it-
RUN apt update && apt install nodejs npm -y
  • There could be a significant improvement to the size of the docker image if i used the only the required dependencies to run the application.So, instead of using ubuntu as image we can use node docker image which is bundled with npm package manager which is needed to run the application.(we are using node:22.6.0-alpine as it is one of the lightweight image)

  • we copy package.json and package-lock.json file first instead of whole source code.

  • RUN npm install to run the dependencies and then we copy the source code -

FROM node:22.6.0-alpine
COPY package*.json .
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm","run","dev"]

Lets create the new updated dockerimage -

As you can see the significant difference in the size of the image

Lets make the Dockerfile for production environment-

  • We specify work directory by using WORKDIR this makes it more organised where the application source code is used instead of root directory

  • You need to put Environmental variable in some application and for that ENV is used here in the following Dockerfile i have used ENV to set NODE_ENV to production

  • Instead of running as root user we can specify a user and for this image there is node user we have specified it in the dockerfile

  • we created node user so we also need to give user ownership to the directory so it could read the application source code we can achieve this with
    --chown=node:node

FROM node:22.6.0-alpine
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json .
RUN npm install
USER node
COPY --chown=node:node . .
EXPOSE 3000
CMD ["node","index.js"]

The difference between the images -

you can also write .dockerignore file where you can specify which dir/files you don't want to copy while creating the image further reducing the size of the image

That's it for this Blog.
Thanks for reading

GIthub repo - https://github.com/iamabhijeet20/my-docker-knowledge

10
Subscribe to my newsletter

Read articles from Abhijeet directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Abhijeet
Abhijeet

I am Abhijeet, a Computer Science Master's Degree holder. with an A+ grade, specializing in AWS, Azure, Docker, Kubernetes, Terraform, and DevOps tools.