escriptを動かすDockerfileのサンプル


  • mix escript.build で生成されるバイナリを動かしたい
  • 面倒なことは避けたい
  • コード変更した後短い時間でimage作成したい
  • imageのサイズは小さくしたい

を満たすDockerfileを作りました。
手元で動かすだけであれ必要はないのだけれども、github actionsで利用したかったので image 化しました。

できあがったものは niku/nwiki にあります。
docker image ls によると 257MB のようです。
あんまり小さくはないけれど、これ以上がんばる気力がなかった。

Elixir Advent Calendar 2019で埋まっていないところがあったので参加させてもらいました

方針

  • 面倒なことは避けたい
  • コード変更した後短い時間でimage作成したい
    • 上から変更の頻度が低い順に並べる。アプリケーションのコードが変更されたら、アプリケーションのレイヤーだけビルドされるように構築した。
    • apt-get
    • mix が共通で利用する hex と rebar パッケージのインストール、コンパイル
    • mix がアプリケーションで利用するパッケージをインストール、コンパイル
    • アプリケーションを読みこみ、コンパイル
  • imageのサイズは小さくしたい
    • MultiStageビルドを利用
    • escriptをビルドする環境と、escriptを動かす環境を分けることでビルド時に必要で動かすときには不要な依存を保持しなくともよい
    • escript化したらerlangの実行環境のみでよい(elixirは必要ない)
    • ビルドする環境と動かす環境は同じOS、CPUでないと動かない点には注意すること

Dockerfile

#
# Building stage
#
FROM elixir:slim
ENV LANG=C.UTF-8 \
    MIX_ENV=prod

# os dependency
# mix global dependency
RUN set -xe \
    && apt-get update \
    && apt-get install -y --no-install-recommends \
    git \
    ca-certificates \
    && rm -rf /var/lib/apt/lists/* \
    && mix local.hex --force \
    && mix local.rebar --force

# mix dependency
COPY mix.exs mix.lock ./
RUN set -xe \
    && mix deps.get --only prod \
    && mix deps.compile

# application code
COPY lib ./lib/
RUN set -xe \
    mix escript.build

#
# Runtime stage
#
# elixir:slim based on erlang:22-slim
FROM erlang:22-slim
ENV LANG=C.UTF-8
COPY --from=0 nwiki .
ENTRYPOINT ["./nwiki"]