PM2 与 Docker 结合使用:Node.js 应用的高效管理与部署

news/2025/2/9 8:15:55 标签: docker, node.js, eureka

在现代 Web 开发中,Node.js 应用的部署和管理至关重要。为了确保应用的高可用性和性能,开发者常常采用 PM2(进程管理工具)和 Docker(容器化平台)的结合方案。本文将详细介绍 PM2 的功能、Docker 的优势,并展示如何在 Docker 容器中使用 PM2 管理 Node.js 应用,实现高效、稳定的部署。


1. 什么是 PM2?

PM2(Process Manager 2)是 Node.js 的流行进程管理工具,能够帮助开发者更好地管理和监控应用进程。以下是 PM2 的核心功能:

PM2 的主要功能

  1. 进程守护:应用崩溃后,PM2 会自动重启,确保服务高可用。
  2. 集群模式:通过多进程管理(cluster 模式),充分利用多核 CPU,提升应用性能。
  3. 日志管理:支持日志分割、集中管理和实时查看,方便排查问题。
  4. 性能监控:提供实时资源使用情况(CPU、内存),支持告警功能。
  5. 零停机重启:通过 reload 命令实现无缝更新,避免服务中断。

PM2 的配置文件(如 ecosystem.config.js)允许开发者定义应用的启动参数、环境变量和资源限制,简化了应用的部署和管理。


2. 什么是 Docker?

Docker 是一个容器化平台,允许开发者将应用及其依赖打包成镜像,并在任何支持 Docker 的环境中运行。Docker 的核心优势包括:

Docker 的主要优势

  1. 环境一致性:确保开发、测试和生产环境的依赖一致,避免“在我机器上能跑”问题。
  2. 资源隔离:限制容器的 CPU、内存等资源,防止单个应用影响宿主机或其他容器。
  3. 快速部署:通过镜像文件,实现“一次打包,到处运行”。
  4. 扩展性:结合 Kubernetes 或 Docker Swarm,轻松实现水平扩展和负载均衡。

3. 为什么在 Docker 中使用 PM2?

Docker 推荐“单进程容器”模式,即每个容器运行一个主进程。但 Node.js 是单线程的,直接运行多个 node 进程会违反这一原则。PM2 的引入解决了这一问题:

PM2 在 Docker 中的作用

  1. 单入口点:PM2 作为容器的主进程(PID 1),管理多个 Node.js 子进程。
  2. 优雅关闭:Docker 发送 SIGTERM 信号时,PM2 会优雅关闭所有子进程。
  3. 资源利用:通过 PM2 的集群模式,充分利用多核 CPU,提升应用性能。
  4. 日志管理:PM2 将日志输出到标准输出(stdout),由 Docker 收集,避免日志冗余。

4. Docker + PM2 的典型使用场景

4.1 高并发 API 网关

  • 场景:需要处理每秒数千次请求的 API 网关。
  • 优势:PM2 的集群模式利用多核 CPU,Docker 提供资源隔离和快速扩展。

4.2 微服务架构

  • 场景:多个 Node.js 微服务需要独立管理。
  • 优势:每个微服务打包为 Docker 镜像,PM2 管理容器内的多个子进程。

4.3 持续集成/持续部署(CI/CD)

  • 场景:自动化测试、构建和部署。
  • 优势:Docker 镜像标准化,PM2 支持零停机重启。

4.4 多环境一致性

  • 场景:开发、测试和生产环境需要一致的配置。
  • 优势:Docker 镜像确保依赖一致,PM2 配置文件统一管理。

5. Docker + PM2 的完整示例

以下是一个完整的 Node.js 应用示例,展示如何在 Docker 中使用 PM2 管理应用。

5.1 项目结构

node-pm2-docker/
├── app.js          # Node.js 应用入口文件
├── ecosystem.config.js # PM2 配置文件
└── Dockerfile      # Docker 配置文件

5.2 应用代码 (app.js)

const express = require('express');
const app = express();
const port = process.env.PORT || 3000;

app.use(express.json());

// 健康检查接口
app.get('/health', (req, res) => {
    res.status(200).json({
        status: 'ok',
        pid: process.pid,
        timestamp: new Date().toISOString()
    });
});

// 示例接口
app.get('/api', (req, res) => {
    res.send('Hello from Node.js PM2 Docker!');
});

const server = app.listen(port, () => {
    console.log(`Server running on port ${port} (PID: ${process.pid})`);
});

// 优雅关闭处理
process.on('SIGTERM', () => {
    console.log('SIGTERM signal received: closing HTTP server');
    server.close(async (err) => {
        if (err) {
            console.error('Error closing server:', err);
        } else {
            console.log('Server closed');
        }
    });
});

5.3 PM2 配置文件 (ecosystem.config.js)

module.exports = {
    apps: [{
        name: 'node-app',
        script: './app.js',
        instances: 'max',
        exec_mode: 'cluster',
        env: {
            NODE_ENV: 'production'
        },
        max_memory: '512M',
        log_date_format: 'YYYY-MM-DD HH:mm:ss',
        out_file: '/dev/stdout',
        err_file: '/dev/stderr'
    }]
};

解释:

  • “name”:应用名称,便于管理。
  • “script”:应用入口文件。
  • “instances”:启动的实例数量,设置为"max"表示根据CPU核心数自动确定。
  • “exec_mode”:执行模式,"cluster"表示开启集群模式,负载均衡。
  • “env”:环境变量配置,这里设置为生产环境。
  • “max_memory”:内存使用限制,超过则自动重启。
  • “log_file”、“out_file”、“err_file”:日志文件路径和格式,便于日志管理。

5.4 Docker 配置文件 (Dockerfile)

dockerfile"># 使用 node:16 的官方镜像作为基础
FROM node:16

# 安装 PM2
RUN npm install pm2 -g

# 创建应用目录
WORKDIR /app

# 将整个项目文件复制到容器中
COPY . /app/

# 设置环境变量
ENV NODE_ENV production

# 设置容器停止时的信号处理
STOPSIGNAL SIGINT

# 启动命令:使用 PM2 启动应用
CMD ["pm2-runtime", "start", "ecosystem.config.js"]

5.5 构建和运行

  1. 构建 Docker 镜像
docker build -t node-pm2-docker .
  1. 运行容器
docker run -p 3000:3000 node-pm2-docker
  1. 验证应用状态
docker exec -it node-pm2-docker pm2 ls

6. 总结

通过本文的介绍,可以看出 PM2 和 Docker 的结合使用为 Node.js 应用带来了以下优势:

  1. 高可用性:PM2 自动重启崩溃的进程,Docker 提供容器级别的资源隔离。
  2. 性能优化:PM2 的集群模式充分利用多核 CPU,Docker 提供快速扩展能力。
  3. 环境一致性:Docker 镜像确保依赖一致,PM2 配置文件统一管理。
  4. 日志管理:PM2 和 Docker 协同管理日志,方便排查问题。

http://www.niftyadmin.cn/n/5845815.html

相关文章

IDEA编写SpringBoot项目时使用Lombok报错“找不到符号”的原因和解决

目录 概述|背景 报错解析 解决方法 IDEA配置解决 Pom配置插件解决 概述|背景 报错发生背景:在SpringBoot项目中引入Lombok依赖并使用后出现"找不到符号"的问题。 本文讨论在上述背景下发生的报错原因和解决办法,如果仅为了解决BUG不论原…

LIMO:少即是多的推理

25年2月来自上海交大、SII 和 GAIR 的论文“LIMO: Less is More for Reasoning”。 一个挑战是在大语言模型(LLM)中的复杂推理。虽然传统观点认为复杂的推理任务需要大量的训练数据(通常超过 100,000 个示例),但本文展…

工业相机在工业生产制造过程中的视觉检测技术应用

随着技术不断发展以及工业4.0时代的到来,利用工业相机进行视觉检测技术已经成为制造业不可或缺的一部分。通过结合先进的计算机视觉、AI算法和自动化设备,工业视觉检测为生产线质量控制和效率提升提供了革命性的解决方案。 一、什么是工业视觉检测技术 …

Linux 安装 Ollama

1、下载地址 Download Ollama on Linux 2、有网络直接执行 curl -fsSL https://ollama.com/install.sh | sh 命令 3、下载慢的解决方法 1、curl -fsSL https://ollama.com/install.sh -o ollama_install.sh 2、sed -i s|https://ollama.com/download/ollama-linux|https://…

C++小等于的所有奇数和=最大奇数除2加1的平方。

缘由 三种思路解题&#xff1a;依据算术推导得到一个规律&#xff1a;小等于的所有奇数和等于最大奇数除以2加1的平方。将在后续发布&#xff0c;总计有十种推导出来的实现代码。 int a 0,aa 1,aaa 0;cin >> a; while (aa<a) aaa aa, aa 2;cout << aaa;i…

DeepSeek vs. ChatGPT:不同的诞生时间,对人工智能发展的不同影响

DeepSeek vs. ChatGPT&#xff1a;不同的诞生时间&#xff0c;对人工智能发展的不同影响 ChatGPT 和 DeepSeek 诞生于不同的时间节点&#xff0c;代表了人工智能不同阶段的发展方向。它们在技术、应用以及对AI发展趋势的影响方面各有侧重。 1. 诞生时间与背景 ChatGPT&#x…

日志2025.2.8

日志2025.2.8 1.增加了近战敌人攻击类型 public struct AttackData { public string attackName; public float attackRange; public float attackIndex; public float animationSpeed; public float moveDistance; public AttackType_Melee attackType; …

已经安装了Visual C++ 2015-2022 Redistributable,但运行程序时,提示找不到VCRUNIME140_1D.dll

VCRUNTIME140_1.dll 功能&#xff1a;这是 Visual C 2015 及更高版本运行时库的更新版本&#xff0c;提供了与 VCRUNTIME140.dll 类似的功能&#xff0c;但可能包含一些改进和新特性。 用途&#xff1a;用于支持使用 Visual C 2015 及更高版本编译的应用程序。 VCRUNTIME140…