-1

我有一个 Node 应用程序,它由三个独立的 Node 服务器组成,每个服务器由pm2 start. 我同时使用来运行三个服务器,作为 package.json 中的启动脚本:

"scripts": {
    ...
    "start-all": "concurrently \" pm2 start ./dist/foo.js \" \"pm2 start ./dist/bar.js \" \"pm2 start ./dist/baz.js\"",
    "stop-all": "pm2 stop all",
    "reload-all": "pm2 reload all",
...
}

从 localhost 上的命令行运行时,这一切都运行良好,但是当我将其作为RUNdocker-compose 命令或作为 Dockerfile 中的命令运行时,只有一个服务器脚本(每次尝试时随机一个!)将启动,但随后立即退出。在我的--verbosedocker-compose 输出中,我可以看到 pm2 面板(列表名称、版本、模式、pid 等),但随后出现以下错误消息:

pm2 start ./dist/foo.js exited with code 0.

注意:这都是 Docker 在本地运行的(在具有 16GB RAM 的 Mac Mini 上),而不是在远程服务器上。

如果我docker exec -it <container_name> /bin/bash进入容器并npm run start-all从 src 目录的顶层手动运行(我COPY在我的 Dockerfile 中)一切正常。这是我的 Dockerfile:

FROM node:latest

# Create the workdir
RUN mkdir /myapp
WORKDIR /myapp

# Install packages
COPY package*.json ./
RUN npm install

# Install pm2 and concurrently globally.
RUN npm install -g pm2
RUN npm install -g concurrently

# Copy source code to the container
COPY . ./

在我的 docker-compose 文件中,我只是将 npm run start-all 列为 Node 服务的命令。但是如果我像这样将它添加到 Dockerfile 中并没有什么区别:

RUN npm run start-all

可能会发生什么?pm2 日志只显示应用程序已启动的报告。

4

2 回答 2

1

第一个原因是pm2 start app.js在后台启动应用程序,这就是为什么容器一运行就停止的原因pm2 start

您需要使用 启动一个应用程序pm2_runtime,它会在前台启动一个应用程序。你也不需要concurrently,pm2 process.yml 会做这项工作。

码头工人集成

使用容器?我们得到了你的支持。从今天开始使用pm2-runtime,它是在生产环境中充分利用 Node.js 的完美伴侣。

pm2-runtime 的目标是将您的应用程序包装到适当的 Node.js 生产环境中。它解决了在容器中运行 Node.js 应用程序时的主要问题,例如:

用于高应用程序可靠性的第二个流程回退流程控制自动应用程序监控以使其始终保持正常和高性能自动源映射发现和解析支持

docker-pm2-nodejs

第二个重要的事情,你应该把你所有的应用程序放在 pm2 配置文件中,因为 docker 只能从CMD.

生态系统文件

PM2 增强了您的流程管理工作流程。它允许您通过进程文件微调每个应用程序的行为、选项、环境变量、日志文件。它对于基于微服务的应用程序特别有用。

pm2 config application-declaration 创建文件process.yml

apps:
  - script   : ./dist/bar.js
    name     : 'bar'
  - script : ./dist/foo.js
    name   : 'worker'
    env    :
      NODE_ENV: development

然后添加CMDDockerfile

CMD ["pm2-runtime", "process.yml"]

command从 docker-compose中删除。

于 2019-11-15T06:52:05.553 回答
0

Docker 和 pm2 提供了重叠的功能:例如,两者都具有重新启动进程和管理日志的能力。在 Docker 中,通常认为最好的做法是只在容器中运行一个进程,如果这样做,则不一定需要 pm2。 一起使用 pm2 和 docker 有什么意义? 更详细地讨论了这一点。

运行映像时,您可以指定要运行的命令,并且可以从同一个映像启动多个容器。鉴于您最初显示的 Dockerfile,您可以将它们启动为

docker run --name foo myimage node ./dist/foo.js
docker run --name bar myimage node ./dist/bar.js
docker run --name baz myimage node ./dist/baz.js

这将使您可以在代码更改时仅重新启动其中一个容器,而其余的保持不变。

您暗示 Docker Compose;它的command:指令设置相同的属性。

version: '3'
services:
  foo:
    build: .
    command: node ./dist/foo.js
  bar:
    build: .
    command: node ./dist/bar.js
  baz:
    build: .
    command: node ./dist/baz.js
于 2019-11-15T11:09:18.680 回答