Especially when working with public cloud and running your Docker images on their serverless environments it becomes more and more important that your Docker image size is as small as possible to reduce bootup time, cold start time, costs, and improve overall performance.
But oftentimes I see people still use the “full” image of their corresponding environment. So I want to show in this article how a one-liner in your Dockerfile can reduce the Docker image size of your application by around 90% without breaking your application.
Create the Docker image
In my example, I dockerized a small Node.js “Hello-World”-web server but since the actual application isn’t important in this article I won’t show its code here, but you can expect just a few KB of code here.
A typical Dockerfile for a Node.js environment might look like the following:
# Use Node.js v12
# Copy over the whole folder content
COPY . ./
# Make a clean npm install and only install modules
# needed for production
RUN npm ci --only=production
# Run the web service on container startup.
CMD [ "npm", "run", "start" ]
npm ci --only=production command we already have a small optimization in place. Because we only install the modules defined in the
dependencies section of our
package.json so if you have a lot of modules in your
eslint, jest, typescript, babeletc these won’t be installed so you already saved some space here. So make sure that you always have this line in your Dockerfile when you using NPM.
Running the above Dockerfile via
docker build --tag docker-size-full:1.0 -f Dockerfile . results in a Docker image with a ridiculous size of 930MB!
Having already 930MB in size without any application code at all is of course a big performance killer, especially when you want to scale up with cloud container services like GCP Cloud Run.
Optimize Docker image size
So how can we now reduce these 930MB by around 90%? Here are two possibilities:
# Instead of using the full 930MB via 'FROM node:12'# Use the alpine image
FROM node:12-alpine # OR
# Use the slim image
Pretty easy, right? You just have to change the very first statement in your Dockerfile.
The results of using the three different
FROM statements can be seen in the below image:
As you can see the slim-variant is 83%! smaller than the full-variant and the alpine-variant is even 89%! smaller than the full one.
And I tell you something: Your Node.js script will run on all three of them! So there is absolutely no valid reason to use a super big Docker image if you can also use a smaller one.
Different base images
So now you are for sure asking: “Why are there different images anyway? Can’t I simply always use the smallest one?”
And yeah, in my opinion, you should always use the smallest one, even if you don’t use the alpine one you should at least take the slim one, but never the full one for production applications. BUT you should know what is the difference, at least very roughly since you MIGHT run into some issues even though it's super unlikely and the alpine and slim variant will work for 99.9% of all software applications.
The alpine variant is based on Alpine Linux which is a very small image containing only the most important stuff. It also contains some “unusual” libs which might cause an issue when e.g. using Python, even so very unlikely, but with Node.js you shouldn’t run into any issues.
This image does not contain the common packages contained in the full image and only contains the minimal packages needed to run
You should have seen now how easy it is to reduce your Docker image size by around 90% when you were still using the full version of Node.js.
If you don’t run into any unusual runtime issues it makes always sense to use the smallest image possible for your application to speed up your application and reduce costs when being billed my time consumed e.g. in the cloud environments. So you should always try to go with the alpine image first. If you really stumble into unusual errors you can always go “up” to using the slim variant, but if you don’t run into issues there is no reason to make your image bigger than needed.
Thanks for taking the time to read my article.
👋 Join FAUN today and receive similar stories each week in your inbox! ️ Get your weekly dose of the must-read tech stories, news, and tutorials.