Skip to main content

Docusaurus 部署到 Ubuntu 系统完整指南

目录


部署方案概述

三种部署方式对比

方案优点缺点适用场景
Nginx 静态部署性能最佳、资源占用少更新需要重新构建生产环境推荐
Node.js + PM2易于调试、可动态路由资源占用较多开发/测试环境
Docker 部署环境一致、易于迁移需要学习 Docker容器化环境

推荐方案

  • 生产环境:Nginx + 静态文件(方案一)
  • 开发环境:PM2(方案二)
  • 容器环境:Docker(方案三)

环境准备

1. 服务器要求

最低配置:

  • CPU: 1 核
  • 内存: 1GB
  • 硬盘: 20GB
  • 系统: Ubuntu 20.04 LTS 或更高

推荐配置:

  • CPU: 2 核
  • 内存: 2GB
  • 硬盘: 40GB
  • 系统: Ubuntu 22.04 LTS

2. 连接到服务器

# 使用 SSH 连接
ssh username@your-server-ip

# 或使用密钥
ssh -i /path/to/private-key.pem ubuntu@your-server-ip

3. 更新系统

# 更新软件包列表
sudo apt update

# 升级已安装的软件包
sudo apt upgrade -y

# 安装基础工具
sudo apt install -y curl wget git build-essential

4. 安装 Node.js

方法一:使用 NodeSource 仓库(推荐)

# 安装 Node.js 20.x LTS
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs

# 验证安装
node -v
npm -v

方法二:使用 NVM(灵活管理版本)

# 安装 NVM
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash

# 重新加载配置
source ~/.bashrc

# 安装 Node.js
nvm install 20
nvm use 20
nvm alias default 20

# 验证
node -v
npm -v

5. 配置防火墙

# 安装 UFW(如果未安装)
sudo apt install -y ufw

# 允许 SSH
sudo ufw allow 22/tcp

# 允许 HTTP 和 HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# 启用防火墙
sudo ufw enable

# 查看状态
sudo ufw status

方案一:使用 Nginx 部署静态文件

这是最推荐的生产环境部署方式。

1.1 在本地构建项目

# 在本地开发机器上
cd my-docusaurus-site

# 安装依赖
npm install

# 构建生产版本
npm run build

# 构建产物在 build/ 目录
ls -la build/

1.2 传输文件到服务器

方法一:使用 SCP

# 压缩构建产物
tar -czf build.tar.gz build/

# 传输到服务器
scp build.tar.gz username@your-server-ip:/home/username/

# 或使用 rsync(更高效)
rsync -avz --progress build/ username@your-server-ip:/var/www/docusaurus/

方法二:使用 Git(推荐)

# 在服务器上克隆仓库
cd /var/www
sudo mkdir -p docusaurus
sudo chown $USER:$USER docusaurus
git clone https://github.com/your-username/your-repo.git docusaurus
cd docusaurus

# 安装依赖并构建
npm install
npm run build

1.3 安装和配置 Nginx

# 安装 Nginx
sudo apt install -y nginx

# 启动 Nginx
sudo systemctl start nginx

# 设置开机自启
sudo systemctl enable nginx

# 检查状态
sudo systemctl status nginx

1.4 配置 Nginx 站点

创建 Nginx 配置文件:

sudo nano /etc/nginx/sites-available/docusaurus

添加以下配置:

server {
listen 80;
listen [::]:80;

# 替换为你的域名或服务器 IP
server_name your-domain.com www.your-domain.com;

# 网站根目录
root /var/www/docusaurus/build;
index index.html;

# 日志文件
access_log /var/log/nginx/docusaurus-access.log;
error_log /var/log/nginx/docusaurus-error.log;

# Gzip 压缩
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/javascript application/json;
gzip_disable "MSIE [1-6]\.";

# 主要位置配置
location / {
try_files $uri $uri/ $uri.html /index.html;
}

# 缓存静态资源
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}

# 安全头部
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;

# 禁止访问隐藏文件
location ~ /\. {
deny all;
}
}

1.5 启用站点并重启 Nginx

# 创建符号链接
sudo ln -s /etc/nginx/sites-available/docusaurus /etc/nginx/sites-enabled/

# 删除默认站点(可选)
sudo rm /etc/nginx/sites-enabled/default

# 测试 Nginx 配置
sudo nginx -t

# 重新加载 Nginx
sudo systemctl reload nginx

1.6 验证部署

# 访问网站
curl http://your-server-ip

# 或在浏览器访问
# http://your-server-ip

方案二:使用 Node.js + PM2 部署

适合需要服务端渲染或动态功能的场景。

2.1 安装 PM2

# 全局安装 PM2
sudo npm install -g pm2

# 验证安装
pm2 -v

2.2 安装 serve 或使用 Docusaurus serve

方法一:使用 serve(简单)

# 全局安装 serve
sudo npm install -g serve

# 创建 PM2 配置文件
cd /var/www/docusaurus
nano ecosystem.config.js

添加以下内容:

module.exports = {
apps: [{
name: 'docusaurus',
script: 'serve',
args: 'build -s -l 3000',
cwd: '/var/www/docusaurus',
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: '500M',
env: {
NODE_ENV: 'production'
}
}]
};

方法二:使用 Docusaurus 内置 serve

// ecosystem.config.js
module.exports = {
apps: [{
name: 'docusaurus',
script: 'npm',
args: 'run serve -- --port 3000 --host 0.0.0.0',
cwd: '/var/www/docusaurus',
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: '500M',
env: {
NODE_ENV: 'production'
}
}]
};

2.3 启动应用

# 使用 PM2 启动
pm2 start ecosystem.config.js

# 查看状态
pm2 status

# 查看日志
pm2 logs docusaurus

# 设置开机自启
pm2 startup
pm2 save

2.4 配置 Nginx 反向代理

sudo nano /etc/nginx/sites-available/docusaurus
server {
listen 80;
server_name your-domain.com;

location / {
proxy_pass http://localhost:3000;
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;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# 启用配置
sudo ln -s /etc/nginx/sites-available/docusaurus /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

2.5 PM2 常用命令

# 重启应用
pm2 restart docusaurus

# 停止应用
pm2 stop docusaurus

# 删除应用
pm2 delete docusaurus

# 查看详细信息
pm2 show docusaurus

# 监控
pm2 monit

# 查看日志
pm2 logs docusaurus --lines 100

方案三:使用 Docker 部署

3.1 安装 Docker

# 安装 Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# 将当前用户添加到 docker 组
sudo usermod -aG docker $USER

# 重新登录或执行
newgrp docker

# 验证安装
docker --version

# 安装 Docker Compose
sudo apt install -y docker-compose

# 验证
docker-compose --version

3.2 创建 Dockerfile

在项目根目录创建 Dockerfile

# 多阶段构建
FROM node:20-alpine AS builder

# 设置工作目录
WORKDIR /app

# 复制 package 文件
COPY package*.json ./

# 安装依赖
RUN npm ci

# 复制源代码
COPY . .

# 构建应用
RUN npm run build

# 生产阶段
FROM nginx:alpine

# 复制构建产物到 Nginx
COPY --from=builder /app/build /usr/share/nginx/html

# 复制 Nginx 配置(可选)
COPY nginx.conf /etc/nginx/conf.d/default.conf

# 暴露端口
EXPOSE 80

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget --quiet --tries=1 --spider http://localhost/ || exit 1

# 启动 Nginx
CMD ["nginx", "-g", "daemon off;"]

3.3 创建 Nginx 配置

创建 nginx.conf

server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;

location / {
try_files $uri $uri/ $uri.html /index.html;
}

location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}

gzip on;
gzip_vary on;
gzip_types text/plain text/css text/xml text/javascript application/javascript application/json;
}

3.4 创建 docker-compose.yml

version: '3.8'

services:
docusaurus:
build:
context: .
dockerfile: Dockerfile
container_name: docusaurus-site
restart: unless-stopped
ports:
- "80:80"
networks:
- docusaurus-network
labels:
- "com.centurylinklabs.watchtower.enable=true"

networks:
docusaurus-network:
driver: bridge

3.5 构建和运行

# 构建镜像
docker build -t docusaurus-site .

# 运行容器
docker run -d -p 80:80 --name docusaurus docusaurus-site

# 或使用 docker-compose
docker-compose up -d

# 查看日志
docker logs docusaurus

# 停止容器
docker stop docusaurus

# 重启容器
docker restart docusaurus

3.6 Docker 常用命令

# 查看运行的容器
docker ps

# 进入容器
docker exec -it docusaurus sh

# 查看日志
docker logs -f docusaurus

# 删除容器
docker rm -f docusaurus

# 删除镜像
docker rmi docusaurus-site

# 清理未使用的资源
docker system prune -a

配置域名和 HTTPS

4.1 配置域名 DNS

在域名提供商处添加 A 记录:

类型: A
名称: @ 或 www
值: your-server-ip
TTL: 3600

4.2 安装 Certbot(Let's Encrypt)

# 安装 Certbot
sudo apt install -y certbot python3-certbot-nginx

# 获取 SSL 证书
sudo certbot --nginx -d your-domain.com -d www.your-domain.com

# 跟随提示完成配置

4.3 自动续期

# 测试自动续期
sudo certbot renew --dry-run

# Certbot 会自动配置 cron job
# 检查定时任务
sudo systemctl status certbot.timer

4.4 手动配置 HTTPS(可选)

如果需要手动配置,编辑 Nginx 配置:

server {
listen 80;
server_name your-domain.com www.your-domain.com;
return 301 https://$server_name$request_uri;
}

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name your-domain.com www.your-domain.com;

# SSL 证书
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;

# SSL 配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

# HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

root /var/www/docusaurus/build;
index index.html;

location / {
try_files $uri $uri/ $uri.html /index.html;
}

location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}

自动化部署

5.1 使用 Git Hooks

在服务器上配置 post-receive hook:

# 创建 bare 仓库
mkdir -p ~/git/docusaurus.git
cd ~/git/docusaurus.git
git init --bare

# 创建 post-receive hook
nano hooks/post-receive

添加以下内容:

#!/bin/bash

TARGET="/var/www/docusaurus"
GIT_DIR="/home/username/git/docusaurus.git"
BRANCH="main"

while read oldrev newrev ref
do
# 只在推送到 main 分支时部署
if [[ $ref = refs/heads/"$BRANCH" ]]; then
echo "Ref $ref received. Deploying ${BRANCH} branch to production..."
git --work-tree=$TARGET --git-dir=$GIT_DIR checkout -f $BRANCH
cd $TARGET
npm install
npm run build

# 如果使用 PM2
pm2 restart docusaurus

# 或重启 Nginx
sudo systemctl reload nginx

echo "Deployment complete!"
fi
done
# 设置执行权限
chmod +x hooks/post-receive

在本地添加远程仓库:

# 在本地项目中
git remote add production ssh://username@your-server-ip/home/username/git/docusaurus.git

# 推送部署
git push production main

5.2 使用 GitHub Actions

创建 .github/workflows/deploy.yml

name: Deploy to Ubuntu Server

on:
push:
branches: [ main ]

jobs:
deploy:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Build
run: npm run build

- name: Deploy to Server
uses: appleboy/scp-action@master
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USERNAME }}
key: ${{ secrets.SERVER_SSH_KEY }}
source: "build/*"
target: "/var/www/docusaurus"
strip_components: 1

- name: Restart Nginx
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USERNAME }}
key: ${{ secrets.SERVER_SSH_KEY }}
script: |
cd /var/www/docusaurus
sudo systemctl reload nginx

在 GitHub 仓库设置中添加 Secrets:

  • SERVER_HOST: 服务器 IP
  • SERVER_USERNAME: SSH 用户名
  • SERVER_SSH_KEY: SSH 私钥

5.3 使用 rsync 脚本

创建 deploy.sh

#!/bin/bash

# 配置
SERVER="username@your-server-ip"
REMOTE_DIR="/var/www/docusaurus"
LOCAL_BUILD="build/"

echo "🚀 开始部署..."

# 构建
echo "📦 构建项目..."
npm run build

# 同步文件
echo "📤 同步文件到服务器..."
rsync -avz --delete --progress \
--exclude 'node_modules' \
--exclude '.git' \
$LOCAL_BUILD $SERVER:$REMOTE_DIR/

# 重启服务
echo "🔄 重启服务..."
ssh $SERVER "sudo systemctl reload nginx"

echo "✅ 部署完成!"
# 设置执行权限
chmod +x deploy.sh

# 运行部署
./deploy.sh

性能优化

6.1 启用 HTTP/2

编辑 Nginx 配置:

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
# ... 其他配置
}

6.2 配置缓存

# 在 http 块中添加
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=docusaurus_cache:10m max_size=1g inactive=60m use_temp_path=off;

server {
# ... 其他配置

location / {
proxy_cache docusaurus_cache;
proxy_cache_valid 200 60m;
proxy_cache_valid 404 10m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_background_update on;
proxy_cache_lock on;

add_header X-Cache-Status $upstream_cache_status;

try_files $uri $uri/ $uri.html /index.html;
}
}

6.3 配置 Brotli 压缩

# 安装 Brotli 模块
sudo apt install -y nginx-module-brotli

# 或编译安装
# git clone https://github.com/google/ngx_brotli.git

在 Nginx 配置中添加:

# 在 http 块中
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;

# 在 server 块中
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/javascript application/json;

6.4 优化静态资源

# 预压缩静态文件
cd /var/www/docusaurus/build
find . -type f \( -name '*.html' -o -name '*.css' -o -name '*.js' \) -exec gzip -k9 {} \;

配置 Nginx 使用预压缩文件:

location ~* \.(css|js|html)$ {
gzip_static on;
expires 1y;
add_header Cache-Control "public, immutable";
}

监控和维护

7.1 安装监控工具

# 安装 htop(系统监控)
sudo apt install -y htop

# 安装 netdata(实时监控)
bash <(curl -Ss https://my-netdata.io/kickstart.sh)

# 访问 netdata
# http://your-server-ip:19999

7.2 日志管理

# 查看 Nginx 访问日志
sudo tail -f /var/log/nginx/docusaurus-access.log

# 查看 Nginx 错误日志
sudo tail -f /var/log/nginx/docusaurus-error.log

# 日志轮转配置
sudo nano /etc/logrotate.d/nginx
/var/log/nginx/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
prerotate
if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
run-parts /etc/logrotate.d/httpd-prerotate; \
fi \
endscript
postrotate
invoke-rc.d nginx rotate >/dev/null 2>&1
endscript
}

7.3 自动备份脚本

创建 backup.sh

#!/bin/bash

BACKUP_DIR="/home/username/backups"
SITE_DIR="/var/www/docusaurus"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="docusaurus_backup_$DATE.tar.gz"

# 创建备份目录
mkdir -p $BACKUP_DIR

# 备份网站文件
tar -czf $BACKUP_DIR/$BACKUP_FILE -C $SITE_DIR .

# 删除 7 天前的备份
find $BACKUP_DIR -name "docusaurus_backup_*.tar.gz" -mtime +7 -delete

echo "✅ 备份完成: $BACKUP_FILE"
# 设置执行权限
chmod +x backup.sh

# 添加到 crontab(每天凌晨 2 点备份)
crontab -e

# 添加以下行
0 2 * * * /home/username/backup.sh >> /home/username/backup.log 2>&1

7.4 健康检查脚本

创建 health-check.sh

#!/bin/bash

URL="http://localhost"
TELEGRAM_BOT_TOKEN="your_bot_token"
TELEGRAM_CHAT_ID="your_chat_id"

response=$(curl -s -o /dev/null -w "%{http_code}" $URL)

if [ $response -ne 200 ]; then
echo "❌ 站点异常!HTTP状态码: $response"

# 发送告警(Telegram)
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
-d chat_id=${TELEGRAM_CHAT_ID} \
-d text="⚠️ Docusaurus 站点异常!HTTP状态码: $response"

# 尝试重启服务
sudo systemctl restart nginx
else
echo "✅ 站点正常"
fi
# 每 5 分钟检查一次
*/5 * * * * /home/username/health-check.sh

常见问题

Q1: 页面刷新后 404 错误

原因: Nginx 无法处理客户端路由。

解决方案:

location / {
try_files $uri $uri/ $uri.html /index.html;
}

Q2: 静态资源加载失败

检查:

# 检查文件权限
ls -la /var/www/docusaurus/build

# 修改权限
sudo chown -R www-data:www-data /var/www/docusaurus/build
sudo chmod -R 755 /var/www/docusaurus/build

Q3: 构建时内存不足

解决方案:

# 增加交换空间
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# 永久启用
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

# 或限制 Node.js 内存
NODE_OPTIONS="--max-old-space-size=2048" npm run build

Q4: Nginx 配置测试失败

诊断:

# 测试配置
sudo nginx -t

# 查看详细错误
sudo nginx -T

# 检查语法
sudo nginx -c /etc/nginx/nginx.conf -t

Q5: PM2 应用频繁重启

检查:

# 查看日志
pm2 logs docusaurus --lines 100

# 检查内存使用
pm2 monit

# 增加内存限制
pm2 start ecosystem.config.js --max-memory-restart 1G

Q6: HTTPS 证书自动续期失败

检查和手动续期:

# 检查证书状态
sudo certbot certificates

# 手动续期
sudo certbot renew

# 测试续期
sudo certbot renew --dry-run

# 查看日志
sudo tail -f /var/log/letsencrypt/letsencrypt.log

Q7: Docker 容器无法访问

排查:

# 检查容器状态
docker ps -a

# 查看容器日志
docker logs docusaurus

# 检查端口映射
docker port docusaurus

# 检查网络
docker network inspect bridge

安全加固

8.1 配置防火墙规则

# 只允许必要端口
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

8.2 禁用 root 登录

# 编辑 SSH 配置
sudo nano /etc/ssh/sshd_config

# 修改以下选项
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes

# 重启 SSH
sudo systemctl restart sshd

8.3 安装 Fail2ban

# 安装
sudo apt install -y fail2ban

# 配置
sudo nano /etc/fail2ban/jail.local
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5

[sshd]
enabled = true

[nginx-http-auth]
enabled = true

[nginx-limit-req]
enabled = true
# 启动
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

# 查看状态
sudo fail2ban-client status

8.4 配置 Nginx 安全头部

# 安全头部
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

# 隐藏 Nginx 版本
server_tokens off;

性能测试

测试网站性能

# 使用 Apache Bench
sudo apt install -y apache2-utils
ab -n 1000 -c 100 http://your-domain.com/

# 使用 wrk
sudo apt install -y wrk
wrk -t12 -c400 -d30s http://your-domain.com/

使用在线工具


总结

✅ 推荐方案对比

场景推荐方案命令
生产环境Nginx 静态部署npm run build + Nginx
快速部署PM2 + Node.jspm2 start ecosystem.config.js
容器化Dockerdocker-compose up -d
自动部署GitHub Actions推送代码自动部署

📋 部署检查清单

  • 服务器环境配置完成(Node.js, Nginx)
  • 项目代码已上传/克隆
  • 依赖安装成功
  • 构建成功
  • Nginx 配置正确
  • 防火墙规则配置
  • 域名解析完成
  • HTTPS 证书安装
  • 自动部署脚本配置
  • 监控和日志配置
  • 备份策略实施
  • 安全加固完成

🚀 快速部署命令汇总

# 完整部署流程(Nginx 方式)
sudo apt update && sudo apt upgrade -y
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs nginx git
git clone https://github.com/your-username/your-repo.git /var/www/docusaurus
cd /var/www/docusaurus
npm install && npm run build
sudo cp nginx.conf /etc/nginx/sites-available/docusaurus
sudo ln -s /etc/nginx/sites-available/docusaurus /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d your-domain.com

现在你的 Docusaurus 网站已经成功部署到 Ubuntu 服务器了! 🎉


参考资源


最后更新:2025年11月16日