【问题标题】:Running multiple apps with PM2 from same repo从同一个仓库使用 PM2 运行多个应用程序
【发布时间】:2023-10-01 00:28:01
【问题描述】:

一些上下文:

  • 我有一个用于部署到多个应用程序/域的存储库(nuxt 应用程序)
  • 所有应用都在同一台服务器上
  • 每个应用程序都位于一个单独的文件夹中,其中包含一个 repo 的克隆,每个文件夹都在其自己的域 (nginx) 上提供服务
  • 每个应用都有不同的 env 文件,最重要的区别是域 id(例如:DOMAIN_ID=1 等)
  • 在构建之前,我有一个节点脚本,它基于此DOMAIN_ID 进行一些设置工作

我想用 PM2 来:

  • 为我的所有域使用带有 repo 的单个目录
  • 在运行 pm2 deploy production 时,我希望能够部署所有域,每个域都应该在构建之前运行它的设置脚本
  • 每个域都应构建在一个子文件夹中,以便我可以配置 nginx 以从其文件夹中为特定域提供应用程序

我尝试像这样创建一个生态系统文件:

module.exports = {
  apps: [
    {
      name: 'Demo1',
      exec_mode: 'cluster',
      instances: 'max',
      script: './node_modules/nuxt/bin/nuxt.js',
      args: 'start',
      env: {
        DOMAIN_ID: 1,
      },
    },
    {
      name: 'Demo2',
      exec_mode: 'cluster',
      instances: 'max',
      script: './node_modules/nuxt/bin/nuxt.js',
      args: 'start',
      env: {
        DOMAIN_ID: 2,
      },
    },
  ],
  deploy: {
    production: {
      host: 'localhost',
      user: 'root',
      ref: 'origin/master',
      repo: 'my_repo',
      path: 'path_to_repo',
      'post-setup': 'npm install && node setup.js',
      'post-deploy': 'npm run build:setup && pm2 startOrRestart ecosystem.config.js --env production',
    },
  },
}

但它似乎不起作用。

使用上述生态系统文件创建了进程,但是当我访问 Demo1 的域时,pm2 从 Demo1 或 Demo2 进程中随机提供服务。

某处应该有 2 个 dist 文件夹,每个应用一个。

我想知道上面的配置是否很好,我只是遇到了一个 nginx 问题,或者 pm2 无法真正处理我的用例。

【问题讨论】:

  • 这些应用是静态应用还是 SSR?
  • 嗨尼克。这些应用是 SSR。
  • 嘿 Catalin,我已经准备了一个答案,但我不确定它是否能解决您的问题,因为您还没有真正说明它是什么不起作用。您能否更详细地更新您的问题?你的目标很明确,但你只是说“但它似乎不起作用”。
  • 谢谢尼克。我试图在问题中加入更多相关信息。对不起,但我不知道 nginx(其他人正在研究这部分)。不确定我想要实现的目标是否可以用 pm2 完成。
  • 我发布了一个答案,它应该可以帮助您指出正确的方向。如果您需要帮助将事情弯曲到您的确切用例,只需发表评论,我会看看是否可以提供帮助。其他人可能会在我无法提供帮助的地方提供帮助。

标签: nginx nuxt.js pm2


【解决方案1】:

要实现您的目标,您需要为每个应用提供以下条件:

  • 用于提供生产构建文件的目录。
  • 节点服务器实例,在唯一端口(例如 3000、3001)上运行。
  • 适合每个应用的 nginx 虚拟主机配置。

首先,构建目录。 nuxt build 脚本将在srcDir(默认为项目根目录)中查找.nuxt.config.js.env 文件,根据这些文件为您的应用程序生成生产构建文件,并将输出存储在/.nuxt (同样,默认情况下)。将 --config-file--dotenv 参数传递给 nuxt build 命令允许您指向不同的配置和 env 文件,从而使您能够从单个 repo 生成单独的构建。

例如:

-- appRoot (the default srcDir, we'll change this in nuxt.config.js)
   |__ node_modules
   |__ package.json
   |__ ...etc
   |__ src
      |__ commons
      |  |__ (shared configs, plugins, components, etc)
      |__ app1
      |  |__ nuxt.config.js
      |  |__ ecosystem.config.js
      |  |__ .env
      |__ app2
         |__ nuxt.config.js
         |__ ecosystem.config.js
         |__ .env

为方便起见,您可以在package.json 中创建以下脚本。要为 app1 生成构建,请运行 npm run app1:build

"scripts": {
  ...
  "app1:build": "nuxt build --config-file src/app1/nuxt.config.js --dotenv src/app1/.env",
  "app2:build": "nuxt build --config-file src/app2/nuxt.config.js --dotenv src/app2/.env",
  ...
}

现在我们将构建脚本指向单个应用的nuxt.config.js 文件,我们需要更新这些文件并指定srcDirbuildDirbuildDir 将存储每个构建命令的输出。

nuxt.config.js
...
  srcDir: __dirname,
  buildDir: '.nuxt/app1' (this path is relative to the project root)
...

这就是构建。为服务...

每个应用都需要一个唯一的生产服务器实例,在其自己的唯一端口上运行。默认情况下,nuxt start 将基于项目根目录下的nuxt.config.js 文件启动一个侦听端口 3000 的服务器。与 build 命令一样,我们可以传递参数来更改默认行为。

您可以将命令添加到 package.json:

"scripts": {
  ...
    "app1:build": "nuxt build --config-file src/app1/nuxt.config.js --dotenv src/app1/.env",
    "app1:start": "nuxt start --config-file src/app1/nuxt.config.js --dotenv src/app1/.env -p=3000",
    "app2:build": "nuxt build --config-file src/app2/nuxt.config.js --dotenv src/app2/.env",
    "app2:start": "nuxt start --config-file src/app2/nuxt.config.js --dotenv src/app2/.env -p=3001",
  ...
}

通过告诉nuxt start 使用特定于应用程序的nuxt.config.jss,并让它们指向唯一的buildDirs,我们告诉我们的服务器为每个应用程序提供哪些目录。

重要

确保在启动生产服务器时指定唯一的端口号。将其添加到启动命令(如上)或每个应用程序的 nuxt.config.js 文件中。

现在您拥有独特的构建和独特的服务器实例,您需要配置 nginx 为每个域提供正确的应用程序(我假设您知道如何配置 nginx 以支持虚拟主机,或者您团队中的某个人是为您处理)。这是一个精简的配置示例:

server {
    ...
    server_name app1.com;
    root /path/to/appRoot;
    ...
    location / {
        ...
        proxy_pass   http://localhost:3000;
        ...
    }
    ...
}

每个应用程序的 nginx 配置都可以指向同一个根目录——它是 proxy_pass 将请求路由到正确的节点服务器,当我们使用 nuxt start 命令传递适当的参数时,它反过来知道要为哪个应用程序提供服务。

PM2

我使用 PM2 管理节点服务器实例,因此给定示例的部署脚本可能如下所示:

处理您的版本控制/env 文件,然后...

cd /appRoot
npm install
npm run app1:build
pm2 reload src/app1/ecosystem.config.js

app1 的ecosystem.config.js 文件设置如下:

module.exports = {
  apps: [
    {
      name: "app1",
      exec_mode: "cluster",
      instances: "max",
      script: "./node_modules/nuxt/bin/nuxt.js",
      args: "start --config-file src/app1/nuxt.config.js --dotenv src/app1/.env -p=3000"
    }
  ]
}

可能需要进行一些调整以满足您的需求,但我希望这会有所帮助!

【讨论】:

    最近更新 更多