Hey guys. welcome to SRE101. For the last few weeks, I have been working on an open source project that I call Dockershrink.
It is essentially an AI assistant that helps you reduce the size of your Docker images. By cleverly, optimizing the code in your Docker file. Docker shrink automatically applies techniques like multi-stage builds combined with light-weight base images, checking for unused dependencies.
I'm many other tricks which are often specific to your tech stack and the nature of your application. In a previous video, I explained all these strategies in more detail. So feel free to refer to it.
I've included all necessary links in the description. Behind the curtain docker. Shrink uses OpenAI's GPT-4o with a lot of custom prompting access to knowledge and code analysis.
So in this video, I'm going to show you how to install Docker shrink and how I reduce the size of my two GB Docker image down by 60%. only supports, Nodejs projects, but I do plan on adding support for Python. And go in the coming months.
No installation process is very simple. If you're using Mac or Linux and you have Homebrew, just use the brew install command and you can install. Very easily.
Otherwise, you can head to the releases page of this repository. And you can download a binary, which is suitable for your platform. And if you're feeling adventurous, you can also just clone this repository and build the code yourself into binary.
The instructions are. Yes. Cool.
No once you're done with the installation head over to your terminal and try running the help command. I want to see that the binary is working fine. This is what you should see as a help message.
And. Okay. So as you can see, there are two main functionalities there.
provides. One is generate and one is optimize. I think the names are self-explanatory.
So let's dive straight into optimization. So I created a sample. Application.
The main code is in server. js. And if I had just run server.
js, it starts the server. That's what we need to know about this application. We don't need to know about the nature right now.
More importantly. We have. The package.
json, which defines amongst many other things, the dependencies and the dev dependencies for this application. uh, if you're worked with nodejs applications, you know, that these are the things that add the most bloat. I also have currently a very basic Dockerfile.
Over here. Which is very simple. It uses a base.
nodejs image creates a directory, copies the package. json installs everything. Which means it installs all the dependencies and dev dependencies, then copies the code and just runs the server.
js. Right. This is all.
We start building a Docker image. So first I want to build a Docker image out of the dockerfile. I have at the moment.
Nothing. Okay. Good.
So let's go ahead and build. My app and call it. Original.
Okay. Good. No at the moment, my app is.
2. 05. So let's say 2 gB in size, right?
to optimize my Docker image with Docker shrink. I just have to do two things. number one, I should supply my OpenAI API key.
As an environment, variable. and number 2, call the dockershrink optimize command. something like this.
You enter your key here. I'm obviously not going to record my in this video. I mean, once you're done with that.
let's invoke Docker shrink with the optimize command. Oh, and one more thing. You can also supply the --debug flag.
it gives you detailed. logs about how Docker shrink, interacts with the underlying. LLM, if there are any issues with the optimized command or the generate command, then this debug will actually help you figure out what those issues could be.
For now I'm going to. Not use debug. Just to show the output.
Okay. I have some output. It looks like dockershrink did something.
First of all, uh, there is. Currently no . dockerignore file in my project.
Fine. Secondly, dockershrink is notifying me that, all the new assets have been saved to dockershrink. out directory.
So nothing has been changed in the original project. It just adds a new directory inside the project. And that's where all the changed files are.
Right. A couple of actions were taken. a .
dockerignore file was created. specifically node modules and all this Docker ignore makes sure that certain files and folders don't go inside your Docker image, even when you're copying everything. When you have a simple command "COPY .
. ", which copies everything from your local. build context.
It will not copy the files and folders inside . dockerignore. Then comes the main thing, which is the changes it has made in the dockerfile itself.
So first. It seems to have adopted the multi-stage builds and use the lightweight base image specifically, Alpine. So that the final stage only contains what is necessary for the application to run.
Okay. Secondly, Docker shrink has also made some changes to make sure dev dependencies From the package. json, do not get included in the final image.
And lastly, there is a recommendation. that you should run. depcheck.
To identify unused dependencies. depcheck is a tool which automatically checks your code base to figure it out. If there are any dependencies that are declared in your package.
json, but you are not actually using them in your application. So, this is very helpful because you can get rid of such dependencies. They don't get installed as part of your node modules.
Therefore reducing the size of your Docker image for the. So, uh, I know that this is the recommendation, so I will need to implement this myself because dockershrink couldn't. But what has dockershrink produced so far?
This rectory. So let's go inside this directory and let's see. I have a docker ignore.
And I already know from the logs. Let's check the new docker file. Yeah.
So this is what the new dockerfile looks like. deep, original Dockerfiles stage. node 23 was named as build.
So dockershrink is treating the original stages, just the build stage. Where do we set up some files, install and don't do anything else right now. And I guess this is also the best place for me to run depcheck so that all this checkup happens within the build stage.
I'm none of the extra stuff makes it to the final stage, which does not require. depcheck. photo, final stage.
It has used node 23 Alpine. It has set the NODE_ENV to production. when you said this environment, The production, it has a side effect that All the NPM install or yarn installed commands will only install the production dependencies, and they will exclude any dev dependencies.
Right. And to be double sure? It also included.
--omit=dev. As a flag. So this ensures that we're only installing production dependencies.
Finally dockershrink is only copying the files, which it thinks are absolutely necessary for the application to run. And I think this is absolutely true because for my image to run, all I need is srever. js and article CSV.
And finally I have the server. js run command. So I think this is actually a very well-written Dockerfile because I think this would significantly reduce the size.
Let me also add depcheck. As recommended by Dr Shin. The best place to run.
depcheck is right off that you have. Copied all your files, including package. json.
I don't know the de inside your Docker image. And we can use NPX for that. Good.
Let's try to build this dockerfile. Oh, wait, I need to move those things. So I moved the assets created by Docker string into the main project and I removed the Docker shrink.
out directory. No let's build. as you can see, depcheck is also running now, the new application image has a tag of dshrink, is a total of 660 MB down from the original 2 GB and all of this happened automatically just because I invoked dockershrink optimize so just by using dockershrink, I automatically applied best practices to my dockerfile I'm not saying it will optimize your image 100%, but it can get you to 80% a lot of it can be automated now By the way, if I had run the optimized command again, over this project.
I'm not guaranteed to receive the exact same Docker file again. This is because of the nature of LLMs. Basically, if you ask ChatGPT the same question twice, you may get two different answers formed in a different way, but the underlying meaning will probably be the same.
Same idea here. This is a current limitation of dockershrink and I'm actively working on making the output more deterministic. What you can be sure off is that whatever code is produced by Docker shrink, very, definitely optimize your image and reduce the bloat.
So as you can see, the main goal of Docker shrink is to automatically write optimized Docker files, which are specific. Your application and its tech stack. Other than this Docker shrink also allows you to generate a new Docker file for your project.
this command tries to understand your app. It's purpose structure, startup command, and then generates an image definition again, with a focus on keeping the size as low as possible. I'm going to cover this generate command in more detail in a later video.
if you guys are interested in seeing specific features in Docker, shrink, reach out to me here in the comments or in our slack channel. And let me know if you want to see a video covering the internals of the tool. I can go into the technical details of how I built it.
Thanks a lot for watching guys. Give dockershrink a try. And leave a star on the git hub repository.
It means you support my work. And that means a lot to me. And I really hope this will save you lots of pain in your job.
See you next time.