Lambda上でnpm installするためにnpmとnode, npmrc入りのLambda Layerを作った。 GitHubにある。
Lambda Layerでバイナリやライブラリを切り出す - sambaiz-net
まずは/usr/bin/npm
をそのまま入れて実行してみた。
FROM lambci/lambda-base:build
WORKDIR /opt
RUN curl -sL https://rpm.nodesource.com/setup_12.x | bash - && \
yum install -y nodejs && \
mkdir bin && \
cp /usr/bin/node bin/node && \
cp /usr/bin/npm bin/ && \
zip -yr /tmp/npm-layer.zip ./*
$ docker build -t npmbin .
$ docker run npmbin cat /tmp/npm-layer.zip > npm-layer.zip && unzip npm-layer.zip -d layer
相対パスでの参照に失敗したようだが対象のパスが見当たらない。
internal/modules/cjs/loader.js:628
throw err;
^
Error: Cannot find module '../lib/utils/unsupported.js'
Require stack:
- /opt/bin/npm
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:625:15)
at Function.Module._load (internal/modules/cjs/loader.js:527:27)
at Module.require (internal/modules/cjs/loader.js:683:19)
at require (internal/modules/cjs/helpers.js:16:16)
at /opt/bin/npm:19:21
at Object.<anonymous> (/opt/bin/npm:152:3)
at Module._compile (internal/modules/cjs/loader.js:776:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:787:10)
at Module.load (internal/modules/cjs/loader.js:643:32)
at Function.Module._load (internal/modules/cjs/loader.js:556:12) {
code: 'MODULE_NOT_FOUND',
requireStack: [ '/opt/bin/npm' ]
}
exit status 1
というのもnpmはシンボリックリンクで、その参照先に対象のパスがあった。
$ ls -l /usr/bin/npm
lrwxrwxrwx 1 root root 38 Jul 23 09:34 /usr/bin/npm -> ../lib/node_modules/npm/bin/npm-cli.js
これごとLayerに含めることにした。
FROM lambci/lambda-base:build
WORKDIR /opt
RUN curl -sL https://rpm.nodesource.com/setup_12.x | bash - && \
yum install -y nodejs && \
mkdir bin nodejs && \
cp /usr/bin/node bin/node && \
cp -r /usr/lib/node_modules ./nodejs/node_modules && \
ln -s ../nodejs/node_modules/npm/bin/npm-cli.js ./bin/npm && \
zip -yr /tmp/npm-layer.zip ./*
すると次のエラーに変わった。Lambdaは/tmp
にしかwriteできないのに$HOMEに書こうとしているようだ。
Unhandled rejection Error: EACCES: permission denied, mkdir '/home/sbx_user1051'
npm ERR! cb() never called!
npm ERR! This is an error with npm itself. Please report this error at:
npm ERR! <https://npm.community>
exit status 1
npm configのデフォルト値をみてみたところ、いくつか$HOMEを参照している。
$ npm config ls -l | grep $HOME
cache = "/root/.npm"
init-module = "/root/.npm-init.js"
userconfig = "/root/.npmrc"
そこでこれらの値を書き換えたnpmrcを含めた。
ENV NPM_CONFIG_USERCONFIG /opt/nodejs/.npmrc
RUN ...
npm config set cache /tmp/.npm && \
npm config set init-module /tmp/.npm-init.js && \
npm config set update-notifier false && \
chmod a+r $NPM_CONFIG_USERCONFIG && \
ln -s ../nodejs/node_modules/npm/bin/npm-cli.js ./bin/npm && \
zip -yr /tmp/npm-layer.zip ./*
func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
if err := os.Setenv("NPM_CONFIG_USERCONFIG", "/opt/nodejs/.npmrc"); err != nil {
return events.APIGatewayProxyResponse{
Body: err.Error(),
StatusCode: 500,
}, nil
}
...
}
これでlocalでうまくいくことが確認できたのでデプロイしてみたところ、
Error: Cannot find module '../lib/utils/unsupported.js'
が再発してしまった。
原因はシンボリックリンクがコピーになっているためで、PRが上がっている。
out, err = exec.Command("ls", "-l", "/opt/bin/npm").CombinedOutput()
// => ls: -rwxr-xr-x 1 root root 4566 Jul 24 2019 /opt/bin/npm
代わりにshell scriptを置くことにした。
FROM lambci/lambda-base:build
WORKDIR /opt
ENV NPM_CONFIG_USERCONFIG /opt/nodejs/.npmrc
RUN curl -sL https://rpm.nodesource.com/setup_12.x | bash - && \
yum install -y nodejs && \
mkdir bin nodejs && \
cp /usr/bin/node bin/node && \
cp -r /usr/lib/node_modules ./nodejs/node_modules && \
npm config set cache /tmp/.npm && \
npm config set init-module /tmp/.npm-init.js && \
npm config set update-notifier false && \
chmod a+r $NPM_CONFIG_USERCONFIG && \
echo -e "#!/bin/sh\n/opt/nodejs/node_modules/npm/bin/npm-cli.js \$@" > ./bin/npm && \
chmod a+x ./bin/npm && \
zip -yr /tmp/npm-layer.zip ./*
あとはタイムアウト対策のためMemorySizeを1024に増やしてようやく返ってくるようになった。
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN [email protected] No description
npm WARN [email protected] No repository field.
+ [email protected]
added 50 packages from 37 contributors and audited 126 packages in 3.455s
found 0 vulnerabilities