I'm currently in process of rewriting app from Python/Flask to Ruby/Rails, and one of changes is in deployment process.
I decided to use containers and Kamal, as it's upcoming default for Rails.
Mind you, I have no prior experience with neither Docker nor deployment tools like Capistrano.
There are many things that I got stuck on (and I plan to write about them maybe later), but today I was trying to solve one problem - images Kamal generated were about 3GB.
Whoa, that's a lot! It takes a long time to build, to upload to registry, to download to server. It's huge waste of resources!
I had to dig into it, and here's what I learned:
To find out how big my images really are (and compare before/after some changes), there's docker images
. It lists all my images and their sizes.
But whats inside?
I found out about this handy command to show me what's contained inside the image:
docker history registry.example/example-all:latest
which shows me something like this:
IMAGE CREATED CREATED BY SIZE COMMENT
211b6b39d381 About a minute ago CMD ["./bin/rails" "server"] 0B buildkit.dockerfile.v0
<missing> About a minute ago EXPOSE map[3000/tcp:{}] 0B buildkit.dockerfile.v0
<missing> About a minute ago ENTRYPOINT ["/rails/bin/docker-entrypoint"] 0B buildkit.dockerfile.v0
<missing> About a minute ago USER rails:rails 0B buildkit.dockerfile.v0
<missing> About a minute ago RUN /bin/sh -c useradd rails --create-home -… 74.9MB buildkit.dockerfile.v0
<missing> About a minute ago COPY /rails /rails # buildkit 2.7GB buildkit.dockerfile.v0
<missing> 17 minutes ago COPY /usr/local/bundle /usr/local/bundle # b… 148MB buildkit.dockerfile.v0
<missing> 18 minutes ago RUN /bin/sh -c apt-get update -qq && apt… 148MB buildkit.dockerfile.v0
<missing> 18 minutes ago ENV RAILS_ENV=production BUNDLE_DEPLOYMENT=1… 0B buildkit.dockerfile.v0
<missing> 19 minutes ago WORKDIR /rails 0B buildkit.dockerfile.v0
<missing> 8 weeks ago CMD ["irb"] 0B buildkit.dockerfile.v0
<missing> 8 weeks ago RUN /bin/sh -c mkdir -p "$GEM_HOME" && chmod… 0B buildkit.dockerfile.v0
<missing> 8 weeks ago ENV PATH=/usr/local/bundle/bin:/usr/local/sb… 0B buildkit.dockerfile.v0
<missing> 8 weeks ago ENV BUNDLE_SILENCE_ROOT_WARNING=1 BUNDLE_APP… 0B buildkit.dockerfile.v0
<missing> 8 weeks ago ENV GEM_HOME=/usr/local/bundle 0B buildkit.dockerfile.v0
<missing> 8 weeks ago RUN /bin/sh -c set -eux; savedAptMark="$(a… 58.1MB buildkit.dockerfile.v0
<missing> 8 weeks ago ENV RUBY_DOWNLOAD_SHA256=cfb231954b8c241043a… 0B buildkit.dockerfile.v0
<missing> 8 weeks ago ENV RUBY_DOWNLOAD_URL=https://cache.ruby-lan… 0B buildkit.dockerfile.v0
<missing> 8 weeks ago ENV RUBY_VERSION=3.2.3 0B buildkit.dockerfile.v0
<missing> 8 weeks ago ENV LANG=C.UTF-8 0B buildkit.dockerfile.v0
<missing> 8 weeks ago RUN /bin/sh -c set -eux; mkdir -p /usr/loca… 45B buildkit.dockerfile.v0
<missing> 8 weeks ago RUN /bin/sh -c set -eux; apt-get update; a… 46.5MB buildkit.dockerfile.v0
<missing> 8 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 8 weeks ago /bin/sh -c #(nop) ADD file:b86ae1c7ca3586d8f… 74.8MB
Here I saw that my problem lies in COPY rails/ rails/
, meaning my app directory is huge.
Why's that? Here's another handy command to see that:
du --max-depth 1
This shows me size of directories inside my project:
8 ./.bundle
108 ./test
824388 ./.ruby-lsp
176 ./config
554380 ./vendor
56 ./lib
108 ./db
125260 ./tmp
28 ./bin
3034272 ./old
24 ./.kamal
39508 ./.git
8 ./.vscode
2300452 ./storage
232 ./spec
8216 ./app
20 ./public
427176 ./log
4614096 .
The thing is, I started deploying from my laptop, so I have all this files that are not present when deploying from CI/CD (as would be optimal way).
So, we have /storage
(with all files), /.ruby-lsp
(from editor), /old
(thats just some migration data), and /vendor
.
I don't want these in my image!
Let's not include them:
# .dockerignore
old/
*.log
vendor/
tmp/
.ruby-lsp/
After another build, I check my image again, and I got to much nicer ~600MB image.
There migth be still some room for improvement, but I'm quite happy with this - my build time is down significantly, my self-hosted registry is not full of useless data, and I learned something new.
Top comments (1)
Great job! Are you using different base and build images in your Dockerfile? It should get you further down in the size.