Q. インストールしたのに、なぜimportできないの? A. インストールした環境が、Lambdaと違うから
インストールしたはずなのに…と思いながらもエラーメッセージが出たので検索します。「Unable to import module
」で検索すると、Python Lambda 関数の「モジュールをインポートできません」エラーを解決するが見つかります。「ベストプラクティスは、Lambda ランタイムのベースと同じ オペレーティングシステムで Lambda レイヤーを作成することです。」と書いてあります。オペレーティングシステムの部分にはリンクがあり、Lambda ランタイム - AWS Lambdaへと続きます。今回はAWS lambdaでPython 3.9を動かしていて、amazon linux 2というオペレーティングシステム(OS)を使っているようです。
ざっくり言うと、手元のmacで動かす前提でinstallしたMeCabは、amazon linux 2 ではファイル構成などの違いによって動かない…という感じでしょうか。amazon linux 2上でpip installしたPythonファイルをzipにしてレイヤーに入れると良さそうです。
Q. Lambdaと同じ環境でインストールするにはどうすればいいの? A. Cloud9かDockerを使おう
Cloud9を使うのがベストプラクティスだと書かれているのでそうしようと思ったのですが、偶然にもこの日、Cloud9を使って良いのかを聞こうとしたらVPoEが休みだったので他の方法を探します。
「Lambda レイヤー 作成 amazon linux 2」で検索し、【AWS】Lambdaレイヤーでライブラリを共通化 | Points & Linesを見つけます。「Amazon Linux版EC2を利用するか、もしくはローカル開発環境でもAmazon LinuxのDockerイメージを利用することができます。」と書いてあるので、Dockerイメージを試します。
「Amazon Linux 2 docker」で検索し、Amazon Linux 2 の Dockerイメージから開発環境を作り Visual Studio Codeで接続してみる | DevelopersIOを見つけます。今回のはPythonなので少し違いますし、接続までする必要はありません。よく読むと、「「Dockerfile」の1行目では、タイトルの書いたようにAmazon Linux 2 の Dockerイメージを使うため、「FROM amazonlinux:2」を記載しています。」と書いてあり、これだけで終わりそうな気がしてきます(「docker 使い方 amazon linux 2」などと検索しても、Amazon Linux 2 「に」 dockerをインストールする話ばかりで、検索力不足を少し感じました)。
Q. Dockerってなに? A. (Macでも)(Amazon Linux 2などの)他の環境を動かすサービス
今さらですが、Dockerとはなんでしょう。ここまでの記事だけでは、「Lambdaのレイヤーを作ることができる道具」くらいの理解しかできませんが、もっと賢いです。手元のMacで、Amazon Linux 2を動かすみたいなものだと理解しています。つまりここでpip installしたものをlayerとしてアップロードすれば、環境が同じだから読み込まれるんだろう。そう信じて作り始めます。
この記事では、レイヤーに乗せるパッケージがLambdaと違う環境でインストールされていると動かないことがありそうだと分かりました。次の記事では、同じ環境でインストールする手法を説明します。
Q. Dockerってどう使えば良いの? A. Dockerfileでimageとcontainerを作ってrunしよう
「FROM amazonlinux:2」とだけ記載されたDockerfileは作れました。しかしこれをどうすれば良いのでしょう。「docker コマンド」で検索し、Dockerコマンド よく使うやつ - Qiitaを見つけます。dockerには、imageとcontainerがあり、dockerfileはimageを作り、imageからcontainerを作るらしいです。
docker build -t イメージ名 Dockerfileのあるディレクトリ
でimageが作られる(buildされる)ので、
docker build -t docker_575_awslinux2_image .
を実行します。imageであることを分かりやすくするために、imageと最後に付けました。
「docker image 場所」Dockerのイメージファイルの格納場所 - Qiita
コンテナを起動するので、次はdocker runです。
docker run --name {コンテナ名} -it {image名} /bin/bash
と書いてありますが、-itや末尾の/bin/bashが必要なのか迷います。docker runコマンドのオプションを「docker run」で調べ、docker run — Docker-docs-ja 20.10 ドキュメントやdocker run — Docker-docs-ja 20.10 ドキュメントを見つけます。
他にも様々なオプションを見ながら、自分好みのものにしていきます。
docker run -i -t --rm --name docker_575_awxlinux2_container -v `pwd`/tmp:/var/app/tmp:z docker_575_awslinux2_image
それぞれ、
- -i
- インタラクティブに
- -t
- 疑似ターミナルを割り当て(-itで、「コンテナ内でインタラクティブな bash シェルを作成します。」docker run — Docker-docs-ja 20.10 ドキュメント )
- --rm
- 作業が終わったらコンテナを削除。
- --name
- コンテナの名前。imageと区別するために、containerと最後に付けました。
docker_575_awxlinux2_container
- コンテナの名前。imageと区別するために、containerと最後に付けました。
- -v(docs.docker.jp/run.rst at main · zembutsu/docs.docker.jp · GitHub)
- 現在の作業ディレクトリ:コンテナ内のディレクトリで、現在の作業場所をコンテナ内にマウント。
- 末尾に:zを入れると同期。コンテナでデータを管理する — Docker-docs-ja 1.9.0b ドキュメント
docker_575_awslinux2_image
- コンテナの元となるimageの名前。
この長いコマンドを実行します。
すると、ターミナルのコマンドを打つ部分(プロンプトと呼ばれる)が「bash-4.2# 」という表示になります。
ここがAmazon Linux 2の中であるという確証はありませんが、lsやpwdなどのコマンドを打って、少なくとも自分の端末のいつものディレクトリ構成では無いことがわかります。
exit
とすると出られました。退路の確認は大事です。
再度
docker run -i -t --rm --name docker_575_awxlinux2_container -v `pwd`/tmp:/var/app/tmp:z docker_575_awslinux2_image
として中に入ります。
この記事では、AWS Lambdaと同じ環境でインストールされたレイヤーが必要なこと、そしてそれはDockerを使えば手に入ることがわかりました。
次の記事では、Dockerを使ってAWS Lambdaと同じ環境でレイヤーを作成します。