I made a simple image through Dockerfile from Fedora (initially 320 MB).
Added Nano (this tiny editor of 1MB size), and the size of the image has risen to 530 MB. I've added Git on top of that (30-ish MB), and then my image size sky-rockets to 830 MB.
Isn't that insane?
I've tried to export and import container to remove history/intermediate images. This effort saved up to 25 MB, now my image size is 804 MB. I've also tried to run many commands on one RUN
, but still I'm getting the same initial 830MB.
I'm having my doubts if it is worth to use Docker at all. I mean, I barely installed anything and I'm hitting 1GB over. If I will have to add some serious stuff like a database and so on I might run out of disk space.
Anyone suffers from ridiculous size of images? How do you deal with it?
Unless my Dockerfile is horribly incorrect?
FROM fedora:latest
MAINTAINER Me NotYou <email@dot.com>
RUN yum -y install nano
RUN yum -y install git
but it's hard to imagine what could go wrong in here.
Docker Squash is a really nice solution to this. you can
$packagemanager clean
in the last step instead of in every line and then just run a docker squash to get rid of all of the layers.https://github.com/jwilder/docker-squash
Here are some more things you can do:
RUN
commands where you can. Put as much as possbile into oneRUN
command (using&&
)With these both AND the recommendations from @Andy and @michau I was able to resize my nodejs image from 1.062 GB to 542 MB.
Edit: One more important thing: "It took me a while to really understand that each Dockerfile command creates a new container with the deltas. [...] It doesn't matter if you rm -rf the files in a later command; they continue exist in some intermediate layer container." So now I managed to put
apt-get install
,wget
,npm install
(with git dependencies) andapt-get remove
into a singleRUN
command, so now my image has only 438 MB.Edit 29/06/17
With Docker v17.06 there comes a new features for Dockerfiles: You can have multiple
FROM
statements inside one Dockerfile and only the stuff from lastFROM
will be in your final Docker image. This is useful to reduce image size, for example:Will result in an image having only the nodejs base image plus the content from /var/my-project from the first steps - but without the ruby, python, git, openssh and gcc!
Yes, those sizes are ridiculous, and I really have no idea why so few people notice that.
I made an Ubuntu image that is actually minimal (unlike other so-called "minimal" images). It's called
textlab/ubuntu-essential
and has 60 MB.The above image is 82 MB after installing nano.
Git has many more prerequisites, so the image gets larger, about 192 MB. That's still less that the initial size of most images.
You can also take a look at the script I wrote to make the minimal Ubuntu image for Docker. You can perhaps adapt it to Fedora, but I'm not sure how much you will be able to uninstall.
Yes the layer system is quite surprising. If you have a base image and you increment it by doing the following:
The image has exactly the same size. That essentially means, you have to manage to put into your RUN steps a lot of extract, install and cleanup magic to make the images as small as the software installed.
This makes life much harder...
The dockerBuild is missing RUN steps without commit.
For best practise, you should execute a single RUN command, because every RUN instruction in the Dockerfile writes a new layer in the image and every layer requires extra space on disk. In order to keep the number layers to a minimum, any file manipulation like install, moving, extracting, removing, etc, should ideally be made under a single RUN instruction
The following helped me a lot:
After removing unused packages (e.g. redis 1200 mb freed) inside my container, I have done the following:
The layers get flatten. The size of the new image will be smaller because I've removed packages from the container as stated above.
This took a lot of time to understand this and that's why I've added my comment.