低スペックなマシンで npm ビルド時に OOM Killer が発生したらスワップファイルを設定する

Always Free な Linux IaaS 上で npm プロジェクトをビルドしようとしたら、エラーコード 137 が発生してしまった。コレは Out of Memory エラーのコードで、ビルドに必要なメモリが足りないということだ。

# エラーコード 137 でビルドが失敗している例
$ npm run build

> my-app@ build /home/neo/my-app
> ng build --prod

50% building 123/124 modules 1 active ...evkit/build-optimizer/src/build-optimizer/webpack-loader.js??ref--7-0!/home/neo/my-app/node_modules/rxjs/_esm2015/internal/operators/withLatestFrom.jsKilled
npm ERR! code ELIFECYCLE
npm ERR! errno 137
npm ERR! blog-editor@ buildc: `ng build --prod`
npm ERR! Exit status 137
npm ERR! 
npm ERR! Failed at the blog-editor@ buildc script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/neo/.npm/_logs/2020-11-14T15_22_03_776Z-debug.log

Always Free な VM はメモリが 1GB 程度しかなく、ビルドに十分なメモリが確保できないようだ。

# メモリは 1GB 程度。Swap なるモノは 0B らしい
$ free -h
              total        used        free      shared  buff/cache   available
Mem:           975M        264M        590M        3.2M        121M        578M
Swap:            0B          0B          0B

そんな時どうするかというと、スワップ領域を作ってやれば良い。メモリに乗り切らないデータをファイルに退避できるように設定するワケだ。

# 2GB 分のスワップファイルを作る
$ fallocate -l 2G /swapfile
$ chmod 600 /swapfile
$ mkswap /swapfile
Setting up swapspace version 1, size = 2 GiB (2147479552 bytes)
no label, UUID=77b227d5-b50e-49fb-8b0e-5ccfcef95a57

$ swapon /swapfile
$ echo '/swapfile none swap sw 0 0' >> /etc/fstab
$ echo 'vm.swappiness = 10' > /etc/sysctl.d/10-swappiness.conf
$ sysctl --load /etc/sysctl.d/10-swappiness.conf
vm.swappiness = 10

Ubuntu の VM では上のように実施できた。

# スワップ領域が 2GB 分増えている
$ free -h
              total        used        free      shared  buff/cache   available
Mem:           975M        263M        557M        3.2M        153M        566M
Swap:          2.0G          0B        2.0G

しかし、CentOS では fallocate コマンドだと失敗するようで、元のスワップファイルの作り方を変えた。

# fallocate コマンドの代わりに以下で作る
$ dd if=/dev/zero of=/swapfile bs=1M count=2048
2048+0 レコード入力
2048+0 レコード出力
2147483648 バイト (2.1 GB) コピーされました、 2.46604 秒、 871 MB/秒

# 後のコマンドは先程と同じ
$ chmod 600 /swapfile
$ mkswap /swapfile
$ swapon /swapfile
$ echo '/swapfile none swap sw 0 0' >> /etc/fstab
$ echo 'vm.swappiness = 10' > /etc/sysctl.d/10-swappiness.conf
$ sysctl --load /etc/sysctl.d/10-swappiness.conf

このようにしたらスワップファイルが作れた。このあとビルドをやり直すと、多少時間はかかったが最後までエラーなくビルドが成功するようになった。

どうしてもメモリが増やせない VM で作業せざるを得ない時はこんなやり方で。