AWS LambdaのCustom RuntimeでElixirを動かす【Docker環境+VSCodeリモート編】



Dockerコンテナ上に構築された開発環境にVSCodeからリモートアクセスして[こちら](https://qiita.com/ansoposKAZ/items/508fd51640a8201c683b)で実施した内容を再実施します。微妙にハマったので次回こそはDynamoDBにアクセスするところまで実施する予定です。

## 環境
- Windows 10 Pro 64bit
- VSCode 1.38.1
- Docker Desktop for Windows 2.1.0.3
- Docker Engine 19.03.2

## 事前準備
[こちら](https://qiita.com/ansoposKAZ/items/0eac1e6c5a97d81a72fd)で作った環境をベースに作業を進めます。

## Dockerfileの変更

- ~~[前回のDockerfile](https://qiita.com/ansoposKAZ/items/0eac1e6c5a97d81a72fd#dockerfile%E3%81%AE%E4%BD%9C%E6%88%90)の内容から以下の箇所を変更しました。~~
	- ~~aptの更新を追加~~
	- ~~zipのインストールを追加~~

- (訂正)AWS Lambdaできちんと動いたと思ってましたが、検証に使っていモジュールを見誤っており結果的に全く動いてませんでした。alertlogic社製のDockerfileをベースにするように変更しました。
	- [erllambda_docker/20のDockerfile](https://github.com/alertlogic/erllambda_docker/blob/master/20/Dockerfile)と[erllambda_docker/elixirのDockerfile](https://github.com/alertlogic/erllambda_docker/blob/master/elixir/Dockerfile)の内容をベースにして自動生成された`Dockerfile`に上書きします。
	- ベースの`Dockerfile`から以下の箇所を変更しました。
		- 各モジュールのバージョンを以下の通り変更
			- Erlang: 22.1
			- Rebar3: 3.12.0
			- Elixir: 1.9.1
		- githubから取得するモジュールのハッシュ値をパラメータ化し、適切な値に変更

```diff
FROM erlang:22

# elixir expects utf8.
FROM lambci/lambda-base:build

# install build dependencies, not provided by lambda-base:build image
RUN set -e \
   && yum -y install \
      ncurses-devel

ARG OTP_VERSION="22.1"
ARG OTP_HASH="7b26f64eb6c712968d8477759fc716d64701d41f6325e8a4d0dd9c31de77284a"

RUN set -e \
        && OTP_DOWNLOAD_URL="https://github.com/erlang/otp/archive/OTP-${OTP_VERSION}.tar.gz" \
        && OTP_DOWNLOAD_SHA256="${OTP_HASH}" \
        && curl -fSL -o otp-src.tar.gz "$OTP_DOWNLOAD_URL" \
        && echo "$OTP_DOWNLOAD_SHA256  otp-src.tar.gz" | sha256sum -c - \
        && export ERL_TOP="/usr/src/otp_src_${OTP_VERSION%%@*}" \
        && mkdir -vp $ERL_TOP \
        && tar -xzf otp-src.tar.gz -C $ERL_TOP --strip-components=1 \
        && rm otp-src.tar.gz \
        && ( cd $ERL_TOP \
             && ./otp_build autoconf \
             && ./configure \
             && make -j$(nproc) \
             && make install ) \
        && find /usr/local -name examples | xargs rm -rf

CMD ["erl"]

ENV REBAR_VERSION="2.6.4"
ENV REBAR_HASH="577246bafa2eb2b2c3f1d0c157408650446884555bf87901508ce71d5cc0bd07"

RUN set -xe \
        && REBAR_DOWNLOAD_URL="https://github.com/rebar/rebar/archive/${REBAR_VERSION}.tar.gz" \
        && REBAR_DOWNLOAD_SHA256="${REBAR_HASH}" \
        && mkdir -p /usr/src/rebar-src \
        && curl -fSL -o rebar-src.tar.gz "$REBAR_DOWNLOAD_URL" \
        && echo "$REBAR_DOWNLOAD_SHA256 rebar-src.tar.gz" | sha256sum -c - \
        && tar -xzf rebar-src.tar.gz -C /usr/src/rebar-src --strip-components=1 \
        && rm rebar-src.tar.gz \
        && cd /usr/src/rebar-src \
        && ./bootstrap \
        && install -v ./rebar /usr/local/bin/ \
        && rm -rf /usr/src/rebar-src

ARG REBAR3_VERSION="3.12.0"
ARG REBAR3_HASH="8ac45498f03e293bc6342ec431888f9a81a4fb9e1177a69965238d127c00a79e"

RUN set -xe \
        && REBAR3_DOWNLOAD_URL="https://github.com/erlang/rebar3/archive/${REBAR3_VERSION}.tar.gz" \
        && REBAR3_DOWNLOAD_SHA256="${REBAR3_HASH}" \
        && mkdir -p /usr/src/rebar3-src \
        && curl -fSL -o rebar3-src.tar.gz "$REBAR3_DOWNLOAD_URL" \
        && echo "$REBAR3_DOWNLOAD_SHA256 rebar3-src.tar.gz" | sha256sum -c - \
        && tar -xzf rebar3-src.tar.gz -C /usr/src/rebar3-src --strip-components=1 \
        && rm rebar3-src.tar.gz \
        && cd /usr/src/rebar3-src \
        && HOME=$PWD ./bootstrap \
        && install -v ./rebar3 /usr/local/bin/ \
        && rm -rf /usr/src/rebar3-src

ARG ELIXIR_VERSION="1.9.1"
ARG ELIXIR_HASH="94daa716abbd4493405fb2032514195077ac7bc73dc2999922f13c7d8ea58777"
ENV LANG=en_US.UTF-8 \
        LANGUAGE=en_US.UTF-8 \
        LC_ALL=en_US.UTF-8

ENV MIX_REBAR3=/usr/local/bin/rebar3
ENV MIX_REBAR=/usr/local/bin/rebar

RUN set -xe \
        && ELIXIR_DOWNLOAD_URL="https://github.com/elixir-lang/elixir/archive/v${ELIXIR_VERSION}.tar.gz" \
        && ELIXIR_DOWNLOAD_SHA256="${ELIXIR_HASH}" \
        && curl -fsSL $ELIXIR_DOWNLOAD_URL -o elixir-src.tar.gz \
        && echo "$ELIXIR_DOWNLOAD_SHA256 elixir-src.tar.gz" | sha256sum -c - \
        && mkdir -p /usr/src/elixir-src \
        && tar -xzf elixir-src.tar.gz -C /usr/src/elixir-src --strip-components=1 \
        && rm elixir-src.tar.gz \
        && cd /usr/src/elixir-src \
        && make -j$(nproc) \
        && make install \
        && rm -rf /usr/src/elixir-src \
        && cd $HOME \
        && mix local.hex --force \
        && mix hex.info

```

## カスタムランタイムで動かす検証用モジュールを作成～動作確認する
- [Elixirプロジェクトの作成](https://qiita.com/ansoposKAZ/items/508fd51640a8201c683b#%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E4%BD%9C%E6%88%90)～[Lambda関数の実行](https://qiita.com/ansoposKAZ/items/508fd51640a8201c683b#lambda%E9%96%A2%E6%95%B0%E3%81%AE%E5%AE%9F%E8%A1%8C)まで実施する。  
- zipファイルはローカル環境に出来ているので、AWS コンソールを開き、Lambdaの設定画面でzipファイル選択時に直接選択することが可能（この点が前回より楽）
- ハマったポイント
	- distillery ver.2.1以降、リリース構成の初期化コマンドが`mix release.init`から`mix distillery.init`に変更になっていたため、`mix release.init`を実行しても`rel/config.exs`が作られなかった。（`==> You are missing a release config file. Run the release.init task first`というエラーが表示されますが、`mix release.init`しても解消されないです。）
	- Elixir ver.1.9.0からconfig/config.exsが`mix new`で自動生成されなくなっていたので、とりあえず動かすために自分で生成する必要があった。（[ここ](https://elixir-lang.org/blog/2019/06/24/elixir-v1-9-0-released/#configuration)を見る限り非推奨になっている？）
	- jiffyを明示的に`mix.exs`に追記する必要があった。（前回記事の漏れ？）

## 所感
思っていた通り、生成したzipを一々ローカル環境に移す必要がなく、成果物がコンテナ終了後も残るので良いです。あと、erllambdaとmix_erllambdaがErlang v22、Elixir v1.9.1環境でも動作することが確認できました。