Docker コンテナが終了し、次のメッセージが表示される: -bash: fork: retry: リソースが一時的に利用不可

Docker コンテナが終了し、次のメッセージが表示される: -bash: fork: retry: リソースが一時的に利用不可

ここで質問するか、他のコミュニティで質問するかは不明です(例: SuperUser または Unix&Linux)しかし、今のところはここに残しておきます。

私はSeleniumを使用し、PM2ランタイムで管理されているDocker化されたNodeJSアプリを持っています。アプリはDOボックスで実行されます。1GBメモリ &25GBディスク。このアプリは、Selenium WebDriver を使用して、2 分間隔で Web サイトから定期的にデータを取得するだけです。しばらく前にこの問題に遭遇しました。ボックスに SSH で接続すると、任意のコマンドが返されます。

-bash: fork: retry: リソースが一時的に利用できません

メモリ使用量を測定するために監視機能を備えた新しいDOボックスをセットアップしました。使用量が徐々に増加していたので、どこかにメモリリークがあると思いました。見つけようとしましたが、できませんでした。(まだ探している)PM2にはオプションメモリ使用量が一定量に達したらアプリを再起動する。予防策として、これを800M (80%)。 私のecosystem.config.js

module.exports = {
    apps: [
        {
            name: 'scraper',
            script: './index.js',
            watch: process.env.NODE !== 'production',
            ignore_watch: ['node_modules', 'logs', 'test', 'scripts', '.vscode', '.git'],
            out_file: './logs/app.log',
            max_memory_restart: '800M',
            node_args: '--expose-gc',
            env_development: {
                NODE_ENV: 'development'
            },
            env_production: {
                NODE_ENV: 'production'
            }
        }
    ]
}

もう少し周りを見回すと、PM2はメモリリークを引き起こす可能性がある--expose-gcガベージコレクションを徹底的に実行しないため、 1分間隔でガベージコレクションを強制的に実行するためのノード引数を含めました。(に基づくこの例:

exports.generateHeapDumpAndStats = function() {
    try {
        if (global.gc) {
            global.gc()
        } else {
            logger.info('Garbage collection unavailable. Use "--expose-gc" when launching to enable forced garbage collection')
        }
        const heapUsed = process.memoryUsage().heapUsed
        const heapUsedMb = (heapUsed / 1024 * 1024).toFixed(2)
        logger.info(`Program is using ${heapUsedMb} MB of heap`)
    } catch (err) {
        logger.error(`Error: ${err.message}`)
        process.exit(1)
    }
}

ガベージコレクションが失敗しても、PM2は80%の使用率で再起動するので、これは問題ないと思いました。コンテナをおよそ午後10時45分 (GMT +1)私の使用状況グラフから判断すると、コンテナは@を切り取った午前2:00以下は過去 24 時間の使用状況グラフです。

ここに画像の説明を入力してください

メモリ使用量が 80% に近づいていないことがわかります。一時的な対策として再起動しきい値を下げる必要がありますか?

ボックス自体のメモリ使用量を確認しようとしましたが、どのコマンドを入力しても上記のエラーが表示されます。

設定してみる価値はあるでしょうか--max_old_space_size? NodeJS プロセスが 1.5 GB のメモリを割り当てようとしているのを確認しましたが、このボックスにはそのメモリがありません。

なぜこのようなことが起こるのか、非常に困惑しています。残念ながら、コンテナのログはボックス上のローカル ファイルにのみ書き込まれるため、現在はアクセスできません。

実行中のコンテナをチェックしようとしたところ、役に立つ結果が返されました:

ここに画像の説明を入力してください

私のnpm start命令は:

sudo -E pm2-runtime --raw ecosystem.config.js --env production --only スクレーパー

そして完了しますDockerfile:

FROM selenium/standalone-chrome

WORKDIR /usr/src/app

RUN curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
RUN sudo apt-get install -y nodejs build-essential firefox

# copy package.json & package-lock.json and install packages
# we do this separate from the application code to better use docker's caching
# `npm install` will be cached on future builds if only the app code changed
COPY package*.json ./

RUN sudo npm install pm2 -g
RUN sudo npm install

# ENV vars dynamically set here by CI

# copy the app
COPY . .

# expose port for express & start
EXPOSE 3000
CMD [ "npm", "start"]

必要であればリクエストに応じてコードを提供しますが、最初は必要だとは思わなかったし、質問が大きくなりすぎないようにしたかっただけです :)

注記: 最初はSOにこの質問を投稿しましたが、ここに移動するように求められました

編集

@dirkt のコメントによると、リソース制限に達しているようです。ulimit -a次の結果が返されます:

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 3842
max locked memory       (kbytes, -l) 16384
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 3842
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

つまり、ユーザーにはプロセス制限があり、それが私が直面している問題だと思います。しかし、この値をどこで変更すればよいのか、また、それを設定すればよいのか、unlimitedそれとも任意の値に上げればよいのか、よくわかりません。制限は設定されていません/etc/security/limits.conf。ソフト/ハードを変更する方法はいくつか見てきました。( ulimitCLI、limits.confuser.conf- 私は として実行しているので、後者は関係ないと思いますroot)ユーザーの制限。また、このDockerコンテナを次のように実行していることにも注目してください。root (将来的には変更する予定です)

関連情報