如何在腾讯云Ubuntu服务器上部署Node.js项目

最近弄了一个Node.js项目,包含前端用户前台,管理后台和服务端API服务三个项目,本地搭建好了,于是在腾讯云上新建了个Ubuntu 24.04服务器,想要将本地的Node.js项目部署上去,包括环境配置和数据库搭建。

本文主要讲解如何部署Node.js项目,通常需要以下步骤:

  1. 服务器初始设置(创建用户,SSH配置,防火墙)

  2. 安装Node.js和npm

  3. 安装和配置数据库(MySQL/MongoDB)

  4. 部署项目代码(通过Git或SCP)

  5. 安装项目依赖,配置环境变量

  6. 使用PM2管理进程

  7. 配置Nginx反向代理(可选)

  8. 配置SSL证书(可选)

  9. 最终测试和故障排除


现在,开始第一步,服务器初始设置。我们需要创建新用户、配置SSH密钥、更新系统包,并设置防火墙。

第1步:服务器初始设置(安全与基础配置)

1.1 登录服务器
  • 使用SSH登录到你的腾讯云服务器(替换your_usernameyour_server_ip):
    ssh root@your_server_ip
    

    📌 如果是首次登录,腾讯云可能要求你通过Web控制台重置root密码或使用SSH密钥。

1.2 创建新用户(避免使用root)
# 创建新用户(例如命名为deploy)
sudo adduser deploy# 赋予sudo权限
sudo usermod -aG sudo deploy# 切换到新用户
su - deploy
1.3 配置SSH密钥登录(提高安全性)
  • 本地机器操作:生成SSH密钥(如果已有可跳过):
    ssh-keygen -t ed25519
    
  • 将公钥上传到服务器(替换your_server_ip):
    ssh-copy-id deploy@your_server_ip
    
  • 禁用密码登录(可选但推荐)
    sudo nano /etc/ssh/sshd_config
    
    找到并修改:
    PasswordAuthentication no
    
    重启SSH服务:
    sudo systemctl restart sshd
    
1.4 更新系统
sudo apt update && sudo apt upgrade -y
1.5 配置防火墙(UFW)
sudo ufw allow OpenSSH  # 允许SSH
sudo ufw allow 80       # HTTP端口(后续Web服务)
sudo ufw allow 443      # HTTPS端口
sudo ufw enable         # 启用防火墙
sudo ufw status         # 检查规则

第2步:安装Node.js环境

2.1 安装Node.js(推荐使用LTS版本)

Ubuntu 24.04 默认仓库中的Node.js可能不是最新版本,建议通过NodeSource安装指定版本(以Node.js 18.x为例):

# 下载并运行NodeSource安装脚本
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -# 安装Node.js和npm
sudo apt install -y nodejs# 验证安装
node -v  # 应输出 v18.x.x
npm -v   # 应输出对应版本

📌 如果需要其他版本(如20.x),替换脚本中的setup_18.xsetup_20.x,详见 NodeSource文档。


2.2 安装PM2(进程管理工具)

PM2 用于守护Node.js进程,确保应用崩溃或重启后自动运行:

sudo npm install -g pm2# 验证安装
pm2 --version

2.3 配置项目依赖(可选,后续步骤会详细操作)

如果已有项目的package.json,可提前安装依赖:

# 假设项目目录为/home/deploy/app
cd /home/deploy/app
npm install --production

好的!接下来是 第3步:部署代码到服务器。这一步需要将本地的Node.js项目代码上传到服务器的 /home/lifire 目录。以下是具体操作:


第3步:部署代码到服务器

3.1 将本地代码传输到服务器

有两种常用方法:SCP(直接复制文件)或 Git(从仓库拉取)。选择其中一种方式操作。


方法1:使用SCP传输文件(推荐简单项目)
  • 本地机器操作(替换/your/local/path为本地项目路径,your_server_ip为服务器IP):
    # 传输整个项目目录到服务器的 /home/lifire
    scp -r /your/local/project/path deploy@your_server_ip:/home/lifire/# 示例:
    # scp -r ./my-node-app deploy@123.45.67.89:/home/lifire/
    

    📌 输入服务器用户 deploy 的密码(如果配置了SSH密钥则无需密码)。


方法2:使用Git克隆仓库(推荐已有Git管理的项目)
  • 服务器操作(确保已安装Git):
    # 安装Git
    sudo apt install git -y# 进入项目目录
    cd /home/lifire# 克隆你的Git仓库(替换为你的仓库URL)
    git clone https://github.com/yourusername/your-repo.git .# 如果是私有仓库,配置SSH密钥:
    # 1. 在服务器生成SSH密钥(一路回车):
    #    ssh-keygen -t ed25519
    # 2. 将公钥 `cat ~/.ssh/id_ed25519.pub` 添加到GitHub/GitLab的SSH Keys设置中
    

3.2 安装项目依赖
  • 服务器操作
    # 进入项目目录
    cd /home/lifire# 安装依赖(根据项目实际情况选择)
    npm install         # 安装所有依赖(开发+生产)
    # 或
    npm install --production  # 仅安装生产依赖
    

3.3 配置环境变量(如有需要)

如果项目使用了环境变量(如数据库密码、API密钥),需在服务器配置:

# 创建.env文件(示例)
nano .env# 填写你的环境变量,例如:
# DB_HOST=localhost
# DB_USER=root
# DB_PASSWORD=your_password

Ctrl+O 保存,Ctrl+X 退出。


3.4 启动项目(使用PM2守护进程)
# 进入项目目录
cd /home/lifire# 启动项目(假设入口文件为app.js)
pm2 start app.js --name "my-node-app"# 设置PM2开机自启动
pm2 save
pm2 startup
# 执行最后一行输出的命令(例如 `sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u deploy --hp /home/deploy`)

3.5 验证服务是否运行
# 查看PM2进程列表
pm2 list# 检查应用日志
pm2 logs my-node-app

如果看到应用正常启动且无报错,说明部署成功。


3.6 开放应用端口(如3000、8080等)

如果项目监听的是非80/443端口(例如3000),需开放防火墙:

sudo ufw allow 3000
sudo ufw reload

第4步:配置MySQL数据库

4.1 安装MySQL Server
# 更新软件包列表
sudo apt update# 安装MySQL Server
sudo apt install mysql-server -y# 验证安装
sudo systemctl status mysql
  • 如果状态显示 active (running),说明安装成功。

4.2 运行安全配置脚本
sudo mysql_secure_installation

按提示操作:

  1. 设置密码强度验证插件(建议选择 Y)。
  2. 设置root用户密码(输入一个强密码并记住)。
  3. 移除匿名用户(选择 Y)。
  4. 禁止远程root登录(选择 Y)。
  5. 移除测试数据库(选择 Y)。
  6. 重新加载权限表(选择 Y)。

4.3 登录MySQL并创建专用数据库和用户
# 以root身份登录MySQL(使用刚设置的密码)
sudo mysql -u root -p

在MySQL命令行中执行以下操作(替换 your_db_nameyour_db_useryour_db_password):

-- 创建数据库
CREATE DATABASE your_db_name;-- 创建专用用户并设置密码(推荐强密码)
CREATE USER 'your_db_user'@'localhost' IDENTIFIED BY 'your_db_password';-- 授予用户对数据库的完全权限
GRANT ALL PRIVILEGES ON your_db_name.* TO 'your_db_user'@'localhost';-- 刷新权限
FLUSH PRIVILEGES;-- 退出MySQL
EXIT;

4.4 配置MySQL允许远程访问(可选)

如果Node.js应用与MySQL不在同一服务器,需开放远程访问(注意:仅限内网环境或配置IP白名单):

# 修改MySQL配置文件
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf

找到 bind-address 并修改为:

bind-address = 0.0.0.0

重启MySQL服务:

sudo systemctl restart mysql

然后开放防火墙端口:

sudo ufw allow 3306

4.5 在Node.js项目中配置数据库连接

在项目的 .env 文件中添加数据库信息:

DB_HOST=localhost
DB_PORT=3306
DB_USER=your_db_user
DB_PASSWORD=your_db_password
DB_NAME=your_db_name

4.6 测试数据库连接

在Node.js代码中,使用 mysql2sequelize 等库测试连接:

const mysql = require('mysql2/promise');async function testConnection() {const connection = await mysql.createConnection({host: process.env.DB_HOST,user: process.env.DB_USER,password: process.env.DB_PASSWORD,database: process.env.DB_NAME});console.log('数据库连接成功!');await connection.end();
}testConnection().catch(console.error);

运行测试:

node test-db.js

如果输出 数据库连接成功!,说明配置正确。


关键注意事项

  1. 安全建议
    • 不要使用root用户直接连接应用。
    • 生产环境避免开放MySQL到公网,建议通过内网或SSH隧道访问。
  2. 备份数据库
    mysqldump -u your_db_user -p your_db_name > backup.sql
    

第5步:配置Nginx反向代理

5.1 安装Nginx
sudo apt install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx  # 设置开机自启

5.2 配置反向代理
  1. 创建Nginx配置文件(替换 your_domain.com 为你的域名或服务器IP):

    sudo nano /etc/nginx/sites-available/your_domain.conf
    
  2. 粘贴以下配置(假设Node.js运行在 127.0.0.1:3000):

    server {listen 80;server_name your_domain.com www.your_domain.com;  # 无域名可改为 server_name _;location / {proxy_pass http://127.0.0.1:3000;  # 转发到Node.js端口proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection 'upgrade';proxy_set_header Host $host;proxy_cache_bypass $http_upgrade;}# 静态文件处理(可选)location /static/ {alias /home/lifire/blog-server/static/;expires 30d;}# 错误页面配置error_page 500 502 503 504 /50x.html;location = /50x.html {root /usr/share/nginx/html;}
    }
    
  3. 保存并退出Ctrl+OEnterCtrl+X)。


5.3 启用配置并测试
# 创建符号链接到sites-enabled目录
sudo ln -s /etc/nginx/sites-available/your_domain.conf /etc/nginx/sites-enabled/# 测试Nginx配置语法
sudo nginx -t  # 应显示 "test is successful"# 重启Nginx
sudo systemctl restart nginx

5.4 配置防火墙(如果未开放80/443端口)
sudo ufw allow 'Nginx Full'  # 允许HTTP(80)和HTTPS(443)
sudo ufw reload

5.5 验证反向代理

访问 http://your_domain.comhttp://服务器IP,应显示Node.js应用页面。


可选:配置HTTPS(Let’s Encrypt免费证书)

5.6 安装Certbot
sudo apt install certbot python3-certbot-nginx -y
5.7 获取SSL证书
sudo certbot --nginx -d your_domain.com -d www.your_domain.com

按提示操作(输入邮箱、同意条款等),Certbot会自动修改Nginx配置并启用HTTPS。

5.8 验证证书自动续签
sudo certbot renew --dry-run  # 模拟续签测试

关键检查点

  1. Nginx状态

    systemctl status nginx  # 确保状态为 "active (running)"
    
  2. 防火墙规则

    sudo ufw status  # 确保80和443端口允许
    
  3. Node.js应用监听地址
    确保Node.js应用绑定到 0.0.0.0127.0.0.1,而非仅本地回环地址。例如:

    app.listen(3000, '0.0.0.0', () => {console.log('Server running on port 3000');
    });
    

第6步:部署后的优化与监控

6.1 启用PM2集群模式(提升性能)

如果你的应用支持多进程,使用PM2集群模式充分利用多核CPU:

# 停止现有应用
pm2 delete blog-server-v2# 启动集群模式(假设使用4个进程)
pm2 start app.js -i 4 --name "blog-server-v2"# 保存配置
pm2 save

6.2 配置日志轮转(防止日志占满磁盘)
  1. 安装PM2日志轮转模块

    pm2 install pm2-logrotate
    pm2 set pm2-logrotate:max_size 100M  # 单个日志最大100MB
    pm2 set pm2-logrotate:retain 30     # 保留30个历史日志
    
  2. 手动触发日志切割

    pm2 flush  # 清理旧日志
    

6.3 设置基础监控
  1. PM2内置监控

    pm2 monit  # 实时查看进程资源占用
    
  2. 系统级监控(推荐安装htop

    sudo apt install htop
    htop  # 查看CPU、内存、进程详情
    

6.4 配置自动化备份
  1. 备份数据库(每日凌晨3点备份):

    # 创建备份脚本
    nano ~/backup-db.sh
    

    内容:

    #!/bin/bash
    mysqldump -u your_db_user -p'your_db_password' your_db_name > /home/deploy/backups/db_$(date +\%Y\%m\%d).sql
    
    # 赋予执行权限
    chmod +x ~/backup-db.sh# 添加定时任务
    crontab -e
    

    添加一行:

    0 3 * * * /home/deploy/backup-db.sh
    
  2. 备份项目代码(每周日备份):

    crontab -e
    

    添加:

    0 4 * * 0 tar -czf /home/deploy/backups/app_$(date +\%Y\%m\%d).tar.gz /home/lifire/blog-server
    

6.5 安全加固
  1. 定期更新系统

    # 配置自动安全更新
    sudo apt install unattended-upgrades
    sudo dpkg-reconfigure unattended-upgrades  # 选择"Yes"
    
  2. 防火墙加固

    sudo ufw deny 3306       # 禁止MySQL默认端口暴露(如果之前开放过)
    sudo ufw limit OpenSSH   # 防止SSH暴力破解
    

6.6 配置健康检查端点(可选)

在Node.js应用中添加一个健康检查路由:

app.get('/health', (req, res) => {res.status(200).json({ status: 'ok', timestamp: Date.now() });
});

然后通过Nginx或外部监控服务定期访问 http://your_domain.com/health 确认应用存活。


后续建议

  1. 持续集成/部署(CI/CD)
    可配置GitHub Actions或Jenkins,实现代码推送后自动部署。

  2. 高级监控
    使用 Prometheus + Grafana 或 New Relic 监控应用性能。

  3. 负载均衡
    流量大时,可在腾讯云添加多个服务器并使用负载均衡器。


至此,你的Node.js应用已完成完整部署!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/77804.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

国产AI新突破!全球首款无限时长电影生成模型SkyReels-V2开源:AI视频进入长镜头时代!

在 AI 技术日新月异的今天,我们再次见证了历史性的突破。 昆仑万维 SkyReels 团队于近日正式发布了全球首款支持无限时长的电影生成模型——SkyReels-V2,并免费开源。这无疑为 AI 视频领域掀开了崭新的一页,标志着 AI 视频正式迈入长镜头时代…

SpringAI系列 - MCP篇(一) - 什么是MCP

目录 一、引言二、MCP核心架构三、MCP传输层(stdio / sse)四、MCP能力协商机制(Capability Negotiation)五、MCP Client相关能力(Roots / Sampling)六、MCP Server相关能力(Prompts / Resources / Tools)一、引言 之前我们在接入大模型时,不同的大模型通常都有自己的…

一个很简单的机器学习任务

一个很简单的机器学习任务 前言 基于线上colab做的一个简单的案例,应用了线性回归算法,预测了大概加州3000多地区的房价中位数 过程 先导入了Pandas,这是一个常见的Python数据处理函数库 用Pandas的read_csv函数把网上一个共享数据集&…

【第十六届 蓝桥杯 省 C/Python A/Java C 登山】题解

题目链接:P12169 [蓝桥杯 2025 省 C/Python A/Java C] 登山 思路来源 一开始想的其实是记搜,但是发现还有先找更小的再找更大的这种路径,所以这样可能错过某些最优决策,这样不行。 于是我又想能不能从最大值出发往回搜&#xf…

软件工程师中级考试-上午知识点总结(上)

我总结的这些都是每年的考点,必须要记下来的。 1. 计算机系统基础 1.1 码 符号位0表示正数,符号位1表示负数。补码:简化运算部件的设计,最适合进行数字加减运算。移码:与前几种不同,1表示,0表…

Python Cookbook-6.7 有命名子项的元组

任务 Python 元组可以很方便地被用来将信息分组,但是访问每个子项都需要使用数字索引,所以这种用法有点不便。你希望能够创建一种可以通过名字属性访问的元组。 解决方案 工厂函数是生成符合要求的元组的子类的最简单方法: #若在2.4中可使用operator…

win10设置软件开机自启

参考教程:windows10应用程序设置了开机启动,但没有自启_win10软件设置了自启动但是不能自启动-CSDN博客 主要设置是安全策略:

自注意力机制、多头自注意力机制、填充掩码 Python实现

原理讲解 【Transformer系列(2)】注意力机制、自注意力机制、多头注意力机制、通道注意力机制、空间注意力机制超详细讲解 自注意力机制 import torch import torch.nn as nn# 自注意力机制 class SelfAttention(nn.Module):def __init__(self, input…

【大模型】Browser-Use AI驱动的浏览器自动化工具

Browser-Use AI驱动的浏览器自动化工具 1. 项目概述2. 核心架构3. 实战指南3.1 环境安装3.2 快速启动3.3 进阶功能 4. 常见问题与解决5. 项目优势与局限6. 扩展资源7. 总结 1. 项目概述 项目地址:browser-use Browser-Use 是一个开源工具,旨在通过 AI 代…

ubuntu20.04安装安装x11vnc服务基于gdm3或lightdm这两种主流的显示管理器。

前言:在服务端安装vnc服务,可以方便的远程操作服务器,而不用非要插上显示器才行。所以在服务器上安装vnc是很重要的。在ubuntu20中,默认的显示管理器已经变为gdm3,它可以带来与 GNOME 无缝衔接的体验,强调功…

用银河麒麟 LiveCD 快速查看原系统 IP 和打印机配置

原文链接:用银河麒麟 LiveCD 快速查看原系统 IP 和打印机配置 Hello,大家好啊!今天给大家带来一篇在银河麒麟操作系统的 LiveCD 或系统试用镜像环境下,如何查看原系统中电脑的 IP 地址与网络打印机 IP 地址的实用教程。在系统损坏…

C++——STL——容器deque(简单介绍),适配器——stack,queue,priority_queue

目录 1.deque(简单介绍) 1.1 deque介绍: 1.2 deque迭代器底层 1.2.1 那么比如说用迭代器实现元素的遍历,是如何实现的呢? 1.2.2 头插 1.2.3 尾插 1.2.4 实现 ​编辑 1.2.5 总结 2.stack 2.1 函数介绍 2.2 模…

Java并发编程-线程池

Java并发编程-线程池 线程池运行原理线程池生命周期线程池的核心参数线程池的阻塞队列线程池的拒绝策略线程池的种类newFixedThreadPoolnewSingleThreadExecutornewCachedThreadPoolnewScheduledThreadPool 创建线程池jdk的Executors(不建议,会导致OOM)jdk的ThreadP…

【前沿】成像“跨界”测量——扫焦光场成像

01 背景 眼睛是人类认识世界的重要“窗口”,而相机作为眼睛的“延伸”,已经成为生产生活中最常见的工具之一,广泛应用于工业检测、医疗诊断与影音娱乐等领域。传统相机通常以“所见即所得”的方式记录场景,传感器捕捉到的二维图像…

TM1640学习手册及示例代码

数据手册 TM1640数据手册 数据手册解读 这里我们看管脚定义DIN和SCLK,一个数据线一个时钟线 SEG1~SEG8为段码,GRID1~GRID16为位码(共阴极情况下) 这里VDD给5V 数据指令 数据命令设置 地址命令设置 显示控制命令 共阴极硬件连接图…

uni-app 开发企业级小程序课程

课程大小:7.7G 课程下载:https://download.csdn.net/download/m0_66047725/90616393 更多资源下载:关注我 备注:缺少两个视频5-14 tabs组件进行基本的数据展示和搜索历史 处理searchData的删除操作 1-1导学.mp4 2-10小程序内…

判断点是否在多边形内

代码段解析: const intersect = ((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); 第一部分:(yi > y) !== (yj > y) 作用:检查点 (x,y) 的垂直位置是否跨越多边形的当前边。 yi > y 和 yj > y 分别检查边的两个端…

【redis】集群 如何搭建集群详解

文章目录 集群搭建1. 创建目录和配置2. 编写 docker-compose.yml完整配置文件 3. 启动容器4. 构建集群超时 集群搭建 基于 docker 在我们云服务器上搭建出一个 redis 集群出来 当前节点&#xff0c;主要是因为我们只有一个云服务器&#xff0c;搞分布式系统&#xff0c;就比较…

[langchain教程]langchain03——用langchain构建RAG应用

RAG RAG过程 离线过程&#xff1a; 加载文档将文档按一定条件切割成片段将切割的文本片段转为向量&#xff0c;存入检索引擎&#xff08;向量库&#xff09; 在线过程&#xff1a; 用户输入Query&#xff0c;将Query转为向量从向量库检索&#xff0c;获得相似度TopN信息将…

C语言复习笔记--字符函数和字符串函数(下)

在上篇我们了解了部分字符函数及字符串函数,下面我们来看剩下的字符串函数. strstr 的使用和模拟实现 老规矩,我们先了解一下strstr这个函数,下面看下这个函数的函数原型. char * strstr ( const char * str1, const char * str2); 如果没找到就返回NULL指针. 下面我们看下它的…