Next.js是目前非常流行的React服务端渲染框架,很多团队会用它来搭建文档站点、内部知识库或者产品手册。开发阶段在本地跑得很好,但真正要把项目放到Ubuntu服务器上长期运行,就会涉及环境安装、构建产物、进程守护、反向代理等一系列问题。本文以一台全新的Ubuntu服务器为例,完整演示从零开始部署一个Next.js文档应用的全过程,并覆盖上线后常见的运维细节。

一、准备Ubuntu服务器环境
部署的第一步是安装Node.js运行时。Ubuntu默认软件源里的Node版本往往比较老,而Next.js 14以上版本要求Node.js不低于18,因此推荐使用官方提供的安装脚本来获取较新的LTS版本。可以先更新系统包索引,再执行NodeSource的安装脚本:
sudo apt update && sudo apt upgrade -y curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - sudo apt install -y nodejs node -v npm -v
如果服务器上以后可能同时运行多个项目,且各项目依赖不同的Node版本,建议改用nvm来管理版本。nvm安装在用户目录下,不需要root权限,切换版本也很方便。需要注意的是,通过nvm安装的Node在以systemd服务方式运行时,环境变量的加载顺序可能出问题,这一点后面配置开机自启时会再提到。
除了Node本身,还建议安装git用于拉取代码,安装build-essential保证一些带原生依赖的npm包能正常编译。服务器内存如果只有1GB,构建时可能因为内存不足而失败,可以临时添加swap分区来缓解:
sudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile
二、构建Next.js文档应用
环境就绪后,把代码传到服务器上。可以用git clone拉取仓库,也可以在本地打包后通过scp上传。进入项目目录后先安装依赖再执行构建。生产环境安装依赖时务必加上--production或者设置环境变量NODE_ENV=production,这样能跳过devDependencies,减少磁盘占用:
cd /var/www/my-docs npm install --production=false npm run build
构建完成后会生成.next目录,这就是生产版本的全部产物。这里有一个非常容易踩的坑:Next.js默认使用构建时内嵌的环境变量,NEXT_PUBLIC_开头的变量会在构建时被替换进静态文件。如果你的文档站点依赖不同环境的API地址,一定要在执行npm run build之前就把.env.production文件放到项目根目录,构建完再改文件是无效的,必须重新构建。
构建成功后先用生产模式手动启动一次,确认应用本身没有问题:
npm run start # 默认监听3000端口,也可以指定端口 PORT=4000 npm run start
在浏览器中访问服务器的IP加端口,如果文档页面能正常渲染,说明构建产物是好的。此时按Ctrl+C停掉进程,进入下一步用PM2来托管。
三、使用PM2守护进程并配置Nginx反向代理
直接用npm start跑在前台,一旦SSH断开或者进程崩溃,站点就挂了。PM2是Node生态中最常用的进程管理器,自带守护、日志、集群模式等功能。全局安装后用下面的命令启动应用:
sudo npm install -g pm2 cd /var/www/my-docs pm2 start npm --name "my-docs" -- start pm2 save pm2 startup
其中pm2 save会把当前进程列表持久化,pm2 startup会生成一条systemd配置,让服务器重启后自动拉起这些进程。日常运维中几个高频命令要记牢:pm2 list查看进程状态,pm2 logs my-docs实时查看日志,pm2 restart my-docs重启应用,pm2 monit打开资源监控面板。
最后一步是配置Nginx反向代理,把80端口的请求转发到Next.js监听的3000端口,这样用户直接用域名访问即可,也为后续配置HTTPS打好基础:
sudo apt install -y nginx sudo vim /etc/nginx/sites-available/my-docs
配置文件内容如下,注意对/_next/static静态资源开启缓存:
server {
listen 80;
server_name docs.example ipipp.com;
location /_next/static/ {
proxy_pass http://127.0.0.1:3000;
expires 365d;
add_header Cache-Control "public, immutable";
}
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
保存后建立软链接启用站点,检查语法并重载Nginx:
sudo ln -s /etc/nginx/sites-available/my-docs /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx
四、常见问题排查与优化建议
部署完成后如果访问报502,大概率是Next.js进程没有起来,用pm2 list确认状态,再看pm2 logs里的报错信息。如果报EADDRINUSE,说明端口被占用,可以用sudo lsof -i :3000查到占用进程并处理。如果报权限错误,检查项目目录的属主是否是当前运行PM2的用户。
关于性能,有几个值得做的优化:第一,在next.config.js中开启output: 'standalone',构建产物会只保留运行必需的文件,部署体积能缩小很多;第二,Nginx层面对静态资源设置长缓存,前面配置中已经体现;第三,如果文档站访问量较大,可以用pm2 start npm -i 2 -- start开启集群模式,利用多核提升吞吐。配置HTTPS时推荐使用certbot一键申请Let's Encrypt证书,命令为sudo certbot --nginx -d 你的域名,证书会自动续期,无需人工干预。
按照以上四个步骤操作下来,一个Next.js文档应用就能在Ubuntu服务器上稳定运行了。后续每次更新文档内容,只需在服务器上重新拉取代码、执行构建,然后pm2 restart my-docs即可完成发布,整个过程可以进一步写成自动化脚本,接入CI流水线实现一键部署。
Next.js部署Ubuntu服务器配置PM2进程管理修改时间:2026-08-31 22:06:56