When I tried to run the chatops application anago
written in Elixir with GKE, it became a fairly heavy Rails-like capacity, so I verified how far it can be removed.
FROM elixir:latest
WORKDIR /app
ENV MIX_ENV=prod
RUN mix local.hex --force && \
mix local.rebar --force
COPY mix.exs mix.exs
COPY mix.lock mix.lock
COPY config config
RUN mix deps.get --only prod && \
mix deps.compile
COPY . .
CMD ["mix", "run", "--no-halt"]
The Dockerfile at the beginning looks like this. The size of the application built with this Dockerfile is as follows ...
docker images
##
REPOSITORY TAG IMAGE ID CREATED SIZE
anago latest aa7e0779d912 2 seconds ago 1.27GB
If the size of a simple application with no images, JSON, or DB comes out as 1.27GB, you will definitely decide to go on a diet ...
The base image size of Elixir is as follows.
docker pull elixir
## docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
elixir latest 83478b936eba 2 days ago 1.24GB
When I get a Go language container for comparison ...
docker pull golang
### docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
golang latest 5f9d35ce5cfe 3 weeks ago 839MB
After all, the file size is about 30MB including the code of the built library. But the base image is 1.24GB in the first place ... Elixir is nearly 300MB heavier than the image of Go for comparison: upside_down:
I think that the entrance to the image size diet is to make the base image alpine, so I will change the base image.
docker pull elixir:alpine
## docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
elixir alpine dd10458addd0 2 days ago 84.9MB
Overwhelming shape! 96% reduction! Even if you add 30MB of application to this, it will be 114MB!
REPOSITORY TAG IMAGE ID CREATED SIZE
anago alpine c8b8c08b7aef About a minute ago 114MB
Successful dieting to less than 10% compared to the original size! !! Isn't this all right? : thinking:
Erlang has a mechanism called escript that consolidates an application into a single executable file. The executable file may be executable in an environment with the Erlang runtime. Does that mean it works with the image of Erlang: alpine? : thinking: Get the base image of Erlang: alpine right away.
docker pull erlang:alpine
## docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
erlang alpine daa6bbdd7458 2 weeks ago 69.4MB
Since Elixir runs on Erlang, the base image of Erlang may be lighter. It's about 15MB, but it's lightweight. Let's go with this! !!
So I added mix escript build
to Dockerfile.
By the way, you don't need the source code, so let's do a multi-stage build.
FROM elixir:alpine as build
WORKDIR /app
ENV MIX_ENV=prod
RUN mix local.hex --force && \
mix local.rebar --force
COPY mix.exs mix.exs
COPY mix.lock mix.lock
COPY config config
RUN mix deps.get --only prod && \
mix deps.compile
COPY . .
RUN mix escript.build
FROM erlang:alpine
WORKDIR /app
COPY --from=build /app/anago /app/anago
This is Yoshi! : thumbsup:
When I try docker build
again and look at the size: eyes:
REPOSITORY TAG IMAGE ID CREATED SIZE
anago erlang_alpine a01f810d11dc 2 seconds ago 71.4MB
Succeeded in reducing the weight to 71.4MB! !! !! We have finally broken through the 100MB wall! !!
I originally intended to run this application with mix run --no-halt
, but when I use escript, it ends immediately.
In such a case, if you write timer.sleep (: infinity)
, it will work all the time.
defmodule Anago.CLI do
def main(_args) do
:timer.sleep(:infinity)
end
end
erlang: I think that alpine will be included at least, so I'm wondering how much it will be reduced by apk add erlang
to alpine.
The vanilla alpine is only 5MB in size.
Let's create a Dockerfile that installs only erlang in alpine.
FROM alpine:latest
RUN apk add --no-cache erlang
Building this Dockerfile will reduce the result to 63.6MB! (Erlang has a capacity of about 58MB, so no more diet is possible) If you reduce it to this point, you will be worried that it will work properly, but when you come to this point, the goal has shifted to how much you can reduce the size, so I will build it including the application.
REPOSITORY TAG IMAGE ID CREATED SIZE
anago custom_alpine fb1de28697a1 9 minutes ago 65.6MB
I came up to 65.6MB: tada:
By the way, I was able to execute this image properly: tada: (Wow ...) It seems that the limit of weight reduction is 63.6MB + escript because I think that the size limit of Erlang probably cannot reduce the weight any more.
Recommended Posts