package.json を投げたらそれを npm i するのにどのくらいの時間がかかるかを返却する Lambda を作りたい件
本当にやりたいことは別だけどわかりやすい例として題記のような仮の目的を設定。
要点は、
- AWS Lambda を使いたい(EC2 や CodePipeline などではなく)
- Lambda 内で npm コマンドを実行したい
- Lambda 関数自体のランタイムも node にしたい
である。
雑に、
index.js
const { execSync } = require("child_process");
exports.handler = async (event) => {
execSync('npm i', { cwd: '/tmp' });
const response = {
statusCode: 200,
body: JSON.stringify('Hello, World!'),
};
return response;
};
なんて関数を Lambda で実行したら、次のようなエラーが出た。
npm ERR! enoent ENOENT: no such file or directory, mkdir '/home/sbx_userXXXX'
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoentnpm ERR! Log files were not written due to an error writing to the directory: /home/sbx_userXXXX/.npm/_logs
Lambda の実行環境は /tmp
以外は Readonly であるが、npm i のログファイルを /home
に書き出そうとするのでエラーになっていると理解した。
npm の世界で、ログファイルの出力先を変えたり抑制したりできそうではあるが、別な問題として関数(のライブラリ)サイズがデカすぎて S3 経由でもアップロードできず、コンテナを使う事にした。
上記の例を参考に、npm i
を実行する Docker コンテナを作成してローカルでの動作を確認後、Lambda 側にデプロイして実行したところ、上記と同じエラーが発生。
npm ERR! enoent ENOENT: no such file or directory, mkdir '/home/sbx_userXXXX'
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoentnpm ERR! Log files were not written due to an error writing to the directory: /home/sbx_userXXXX/.npm/_logs
ローカルでは動作していたが、Lambda でコンテナ実行するとコンテナ内なのに /tmp
以外は Readonly になるっぽい。
まあ分かる。
ついでにもう一つ Lambda 固有の挙動を発見。
docker build 時にコンテナの /tmp
に必要なファイルをコピーしておこうと、次のような Dockerfile を使用していた。
Dockerfile
FROM public.ecr.aws/lambda/nodejs:18
COPY ./main /var/task/
COPY ./temp/package.json /tmp/package.json
CMD ["index.handler"]
ローカルのコンテナでは /tmp/package.json
は確かに存在するのだけど、 Lambda にデプロイすると /tmp/package.json
が NOT FOUND になっている。
どうやら関数実行時に /tmp
が消去されているように見える。
これがコールドスタートのみか、ホットスタートでも行われるかは不明。
現状だとやはり npm の世界でログファイル出力を抑制しないとダメっぽい。
ログファイルへの書き込みだけを抑制したい(標準出力への表示はしたい)のだけどね。
Dockerfile に
RUN npm config set cache /tmp/.npm
を追記してみたけどダメ。
https://zenn.dev/amay077/scraps/7326d5e7e1c4e0#comment-7492efba0f2710 にあった、
.npmrc
loglevel=silent
を試してみたけどダメ。
execSync の第2引数に
{
env: {
...process.env, // 現在の環境変数を維持
npm_config_cache: '/tmp/.npm'
}
}
を指定したらいけたっぽい。
関数実行時に /tmp が消去されているように見える。
これがコールドスタートのみか、ホットスタートでも行われるかは不明。
これはコールドのみのようだ。
デプロイ後2度目の実行時に /tmp
を見たらファイルが残っていた。
npm_config_cache: '/tmp/.npm'
yarn の場合は、
export YARN_CACHE_FOLDER=/tmp/.yarn
とするらしい。試しに設定してみて yarn コマンド使ってるけど問題なさそう。