O contêiner Docker morre e dá: -bash: fork: retry: Recurso temporariamente indisponível

O contêiner Docker morre e dá: -bash: fork: retry: Recurso temporariamente indisponível

Não tenho certeza se você pergunta isso aqui ou em outras comunidades(ou seja, Superusuário ou Unix e Linux)mas vou ficar aqui por enquanto.

Eu tenho um aplicativo NodeJS encaixado usando Selenium e gerenciado pelo tempo de execução PM2. O aplicativo é executado na caixa DO com1 GBMemória e25 GBDisco. O aplicativo serve apenas para extrair dados periodicamente de um site em um intervalo de 2 minutos usando o Selenium WebDriver. Me deparei com esse problema há um tempo atrás, onde se eu usasse SSH na caixa, qualquer comando retornaria:

-bash: fork: retry: Recurso temporariamente indisponível

Configure uma nova caixa DO com monitoramento para medir o uso de memória. Meu uso estava aumentando, então pensei que havia um vazamento de memória em algum lugar. Tentei encontrá-lo, mas não consegui(Ainda procurando). Eu vi que PM2 tem umopçãopara reiniciar o aplicativo se o uso da memória chegar a um determinado ponto. Por precaução, configurei isso para800M (80%). Meu 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'
            }
        }
    ]
}

Depois de olhar um pouco mais em volta, vi quePM2 pode causar vazamento de memóriapor não executar a coleta de lixo completamente, então incluí os argumentos do nó --expose-gcpara executar a coleta de lixo à força em um intervalo de um minuto(baseado emeste exemplo):

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)
    }
}

Achei que isso seria descoberto, pois mesmo que a coleta de lixo falhasse, o PM2 reiniciaria com 80% de uso. Eu comecei o container @ aproximadamente22h45 (GMT +1)e a julgar pelo meu gráfico de uso, o contêiner foi cortado @2h00. Estes são meus gráficos de uso nas últimas 24 horas:

insira a descrição da imagem aqui

Você pode ver que o uso de memória não está chegando perto de 80%, então devo diminuir meu limite de reinicialização como medida temporária?

Tentei ver o uso de memória na própria caixa, mas qualquer comando digitado exibe o erro acima.

Vale a pena tentar definir --max_old_space_size? Vi que um processo NodeJS tenta alocar 1,5 GB de memória que não tenho nesta caixa.

Estou muito confuso sobre por que isso está acontecendo. Infelizmente, os logs do contêiner são gravados apenas em um arquivo local na caixa, portanto não posso acessá-los agora.

Tentei verificar os contêineres em execução e ele retornou algo útil uma vez:

insira a descrição da imagem aqui

Meu npm startcomando é:

sudo -E pm2-runtime --raw ecossistema.config.js --env produção --only raspador

E completo 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"]

Fornecerei o código mediante solicitação, se necessário, mas não achei que fosse inicialmente necessário e não queria tornar a pergunta muito grande :)

OBSERVAÇÃO: Inicialmente postei esta pergunta no SO, mas fui solicitado a movê-la para cá

EDITAR

De acordo com o comentário de @dirkt, parece que estou atingindo o limite de recursos. ulimit -ame retorna:

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

Portanto, o usuário tem limites de processo, que é o que acho que estou atingindo. No entanto, não tenho certeza de onde alterar esse valor e devo defini-lo unlimitedou apenas aumentá-lo para um valor arbitrário? Não há limites definidos em /etc/security/limits.conf. Eu vi algumas maneiras de alterar o soft/hard( ulimitCLI,, limits.conf- user.confimagino que o último seja irrelevante para mim, pois estou executando como root)limites para um usuário. Também é importante notar que estou executando este contêiner docker comoroot (vai mudar isso no futuro)

informação relacionada