gmile

gmile

After docker released native support for multi-stage builds, I decided to make my own small docker container with app.

Below container is based on the one from @bitwalker. It is the smallest one I could come up with in one sitting, given quite limited knowledge of docker & distillery releases:

# Dockerfile
FROM bitwalker/alpine-elixir:1.4.4 as builder

ADD . /app

WORKDIR /app

ENV MIX_ENV=prod

RUN mix do deps.get, deps.compile, release

FROM alpine:3.6

RUN apk add --no-cache \
      ca-certificates \
      openssl-dev \
      ncurses-dev \
      unixodbc-dev \
      zlib-dev

WORKDIR /app

COPY --from=builder /app/_build/prod/rel/ritm/releases/0.0.1/ritm.tar.gz /app

ENV PORT=4000

RUN tar -xzf ritm.tar.gz; rm ritm.tar.gz

CMD ["bin/ritm", "foreground"]

It’s around 64Mb when pushed to docker hub. That’s a lot, although I don’t expect this to grow significantly (more app code & deps shouldn’t contribute that much).

I am aware guys from @Nerves-Core-Team build super-small linux images with the app installed, but I am not sure what could be derived from their work in order to build my own small container with docker.

How can I reduce the size of container even further?

Showing Posts 1 to 10

wmnnd

wmnnd

@gmile You don’t need the -dev libs on the release image.

This should suffice:

 add --no-cache \
      ncurses-libs \
      zlib \
      openssl \
      ca-certificates
gmile

gmile OP

@wmnnd this dropped the size to 56 MB, thanks!

cmkarlsson

cmkarlsson

How big is the actual release tar file you copy onto the image? The
reason I am asking is that I built alpine from scratch with our erlang
release and it was 18MB where 2/3 (if I remember correctly) was our release.

You should be able to shrink this significantly.

wmnnd

wmnnd

How do you suggest shrinking the release size?

cmkarlsson

cmkarlsson

Normally you don’t. You can exclude debug information which will make it
much smaller (half the size?). Without debug information you cannot
do things like tracing and other useful introspection in production. But
if you need the smallest available this is an option.

Generally the release size is the size your image will be + 5MB or so
for alpine.

bitwalker

bitwalker

Leader

If you depend on additional system libs that can add quite a bit of weight, depending on what they are. You can also double check to see which Erlang applications are being included, it should only be the subset your application depends on, not all of them.

A medium-sized application would probably depend on enough Erlang libs to hit that limit before any code from their own application was counted. A simple test project of mine hits 23mb with just libs, and here are the ones included in the release:


asn1-5.0/
certifi-1.1.0/
combine-0.9.6/
compiler-7.1/
crypto-4.0/
elixir-1.4.5/
gettext-0.13.1/
hackney-1.8.0/
idna-4.0.0/
iex-1.4.5/
kernel-5.3/
logger-1.4.5/
metrics-1.0.1/
mimerl-1.0.2/
poison-3.1.0/
public_key-1.4.1/
sasl-3.0.4/
ssl-8.2/
ssl_verify_fun-1.1.1/
stdlib-3.4/
test-0.1.0/
timex-3.1.13/
tzdata-0.5.12/

So either your app was extremely small or didn’t depend on much - in any case, I suspect most real-world applications will be much larger than 18mb. ERTS itself is only like 6mb, and anything in priv of your application or your dependencies will also be included.

I strongly recommend not stripping debug info - those cases you mentioned are some of the most powerful capabilities of the runtime, and are one of the reasons why OTP is such a powerful tool operationally. You are trading a small amount of space for a significant amount of functionality, to me it’s not even close to worth it to sacrifice that.

cmkarlsson

cmkarlsson

So either your app was extremely small or didn’t depend on much - in any case,
I suspect most real-world applications will be much larger than 18mb. ERTS
itself is only like 6mb, and anything in priv of your application or your
dependencies will also be included.

Yes, it didn’t have many dependencies. My point was that the
release is what should take up the most space. You cannot get the docker image
smaller than the release and that the alpine linux image should have
very little overhead in terms of space.

I strongly recommend not stripping debug info - those cases you mentioned are
some of the most powerful capabilities of the runtime, and are one of the
reasons why OTP is such a powerful tool operationally. You are trading a small
amount of space for a significant amount of functionality, to me it’s not even
close to worth it to sacrifice that.

Agreed. I don’t think the trade-off is worth it either but if you want
the smallest image possible you should know about the option.

We generally encrypt the debug info (we ship our software to clients).
In this case you need the key to be able to do any debugging but it
makes it a little bit harder to reconstruct the source code.

gmile

gmile OP

I’ve measured the space taken inside the container, and here’s what I’ve got.

  • here’s the root:

    docker run -it gmile/ritm:0.0.9 du / -h -d 1
    0       /dev
    4.0K    /home
    0       /proc
    4.0K    /root
    8.9M    /usr
    4.0K    /tmp
    812.0K  /bin
    80.0K   /var
    0       /sys
    1.3M    /etc
    4.0K    /run
    4.0K    /srv
    4.0K    /mnt
    220.0K  /sbin
    5.3M    /lib
    16.0K   /media
    55.7M   /app
    72.3M   /
    
  • here’s the /app folder, containing unpacked tar release:

    docker run -it gmile/ritm:0.0.9 du /app -h -d 1
    52.0K   /app/bin
    380.0K  /app/releases
    33.7M   /app/erts-8.3
    21.6M   /app/lib
    55.7M   /app
    

ERTS itself is only like 6mb

@bitwalker from what I am seeing, erts is 33.7 Mb way bigger than 6 Mb. Any ideas why so?

gmile

gmile OP

Upgrading the base image to bitwalker/alpine-elixir:1.4.5 (with erlang 20.0.1 underneath) shaved off another 12 Mb down to 48 Mb. After looking at the size stats, the shrink is due to erts loosing some weight:

docker run -it gmile/ritm:0.0.10 du /app -h -d 1
21.1M   /app/erts-9.0.1
52.0K   /app/bin
380.0K  /app/releases
22.2M   /app/lib
43.7M   /app

The size of erts is still way more than 6 Mb.

bitwalker

bitwalker

Leader

You’d have to show what is taking up that space in the ERTS folder - on my laptop, a release packed with ERTS included only shows 5.4mb in the erts-9.0 folder via du -hs <path>. Either there is more in the ERTS folder on Alpine which can be stripped (and I can tweak that in the Alpine images I produce if so) or it’s just bigger on Linux for some reason, but I can’t imagine why that would be.

Where Next? Top

Trending in Questions Top

itzmidinesh
Hi all, I’m working on a Phoenix project where I need to make external HTTP requests and I’m trying to choose between Req and HTTPoison....
New
yarrichar
I’m very new to Elixir, so sorry if this is a silly question: I am wondering what happens to the mailbox of a process when the machine i...
New
pragdave
How do I tell Hologram not to escape HTML when substituting into templates? {Textile.render(@product.long_description)} escapes the HTM...
New
Fl4m3Ph03n1x
Background When trying to execute mix release on a Windows 11 machine for a Phoenix project I get the following error: * assembling mark...
New
rlipscombe
I’d like to create a file with 600 permissions (rw-------), but there’s a race condition if I create it and then change the permissions. ...
New
saleyn
Is there a way to import record definitions in the iex shell for pretty printing (similar to the rr command in the erl shell)? This woul...
New
rlipscombe
When I use Mix.install with a git dependency, using git@github.com:... how do I change the SSH identity used? I’ve got two Github accoun...
New

Other Trending Topics Top

dominicletz
Hey there, I haven’t seen a list of useful Elixir specific skills for the popular AI tools yet so I’m starting one here with my first. ...
New
raa-ziq
Hi everyone :waving_hand: I wanted to share something I’ve been building — NowBlind, a random chat app designed to help people discover ...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
OndrejValenta
(I just needed to vent somewhere and LinkedIn is full of hope, or hype, I’m not sure which exactly) AI dream has many faces, but general...
New
kip
Localize is the next generation localisation library for Elixir. Think of it as ex_cldr version 3.0. The first version will be released ...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews