DigitalOcean Droplet

在本指南中了解如何在 DigitalOcean Droplets 上部署您的 Strapi 应用程序。

这是将 Strapi 项目部署到 DigitalOcean Droplet 的分步指南。或者,如果数据库相关要求和预算更适合您的使用案例,您也可以选择部署到 DigitalOcean 的平台即服务 (PaaS),即 App Platform

本指南介绍如何在 DigitalOcean Droplet 上托管数据库。另一种选择是使用 DigitalOcean 托管数据库 将数据库作为服务在外部托管。

创建 Strapi 项目时,请勿使用 --quickstart 标志,因为快速启动安装使用 SQLite,而这对于远程托管来说并非理想选择。

创建“Droplet”

DigitalOcean 称虚拟专用服务器为 Droplet。创建一个新的 Droplet 来托管您的 Strapi 项目:

  1. 登录您的 DigitalOcean 帐户
  2. 选择右上角附近的 Create 下拉菜单,然后选择 Droplets
  3. 选择离用户位置最近的“区域”和“数据中心”。
  4. 从“OS”选项卡中选择 Ubuntu 22.04 (LTS) x64 作为镜像。
  5. 根据您的需求选择合适的 droplet 大小和定价计划。Strapi 需要 至少 2GB 的 RAM 来构建和部署管理界面。
  6. 选择 SSH 密钥
  7. 在您计算机上的终端实例中,运行以下命令:pbcopy < ~/.ssh/id_rsa.pub。该命令将开发计算机上现有的 SSH 公钥复制到剪贴板。
  8. 返回 DigitalOcean 网站,将您的公钥 SSH 密钥粘贴到“新 SSH 密钥”字段中。命名此 SSH 密钥并单击“保存”**。
  9. (可选)根据需要选择其他选项,例如 IPv6
  10. (可选)选择 主机名 或保留原样。
  11. 单击右下角的 创建 Droplet 按钮。

DigitalOcean 将创建您的 Droplet 并通过加载栏指示进度。完成后,继续设置生产服务器并安装 Node.js。

有关创建和使用 SSH 密钥的其他说明,请参阅 DigitalOcean 官方文档

设置生产服务器并安装 Node.js

以下步骤将帮助您设置生产服务器和非 root 用户来管理服务器。

设置生产服务器

按照 DigitalOcean 官方文档使用 Ubuntu 22.04 进行初始 服务器设置

安装和配置 Node.js 和 npm

现在服务器已设置完毕,使用个人软件包存档 (PPA) 安装 Node,如 官方 DigitalOcean 文档 中所述。

安装 Node(默认情况下也会安装 npm)后,您将手动更改 npm 的默认目录。以下步骤基于官方 Node 文档中的 如何解决访问权限

  1. 创建一个 .npm-global 目录,并通过运行以下命令为 node_modules 设置此目录的路径:
bash
mkdir ~/.npm-global
npm config set prefix '~/.npm-global'
  1. 运行以下命令创建(或修改)一个 ~/.profile 文件:
bash
sudo nano ~/.profile
  1. 将以下行粘贴到打开的 ~/.profile 文件的前两行中:
bash
# 设置 PATH,以便全局节点模块安装时不会出现权限问题
export PATH=~/.npm-global/bin:$PATH

然后按Ctrl+X 退出,y 保存,Enter 接受。 4. 通过运行以下命令更新系统变量:

bash
source ~/.profile

您现在可以在服务器上安装和配置 Git 版本控制了。

在您的服务器上安装和配置 Git 版本控制

在初始开发期间和之后维护和更新 Strapi 应用程序的一种方便方法是使用 Git。为了使用 Git,您需要在您的 Droplet 上安装它。

Droplet 应该默认安装 Git。通过运行以下命令检查 Git 是否已安装:

bash
git --version

如果终端返回 git version 后跟某个版本号(例如,git version 2.x.x),则表示 Git 已安装,您可以继续 为您的项目安装数据库

如果未安装 Git:

  1. 按照 DigitalOcean 文档 如何在 Ubuntu 22.04 上安装 Git 安装 Git。
  2. 按照 DigitalOcean 文档 中所述设置用户名和电子邮件,配置 Git。

为您的项目安装数据库

按照 DigitalOcean 文档 中的“第 4 步 - 创建新数据库”步骤,在 Ubuntu 22.04 上安装 PostgreSQL。完成后,将安装 PostgreSQL 并创建用户和数据库。

要使用 Strapi 连接到 PostgreSQL 数据库,数据库:

  • 需要有密码,
  • 或通过将空字符串(“'''”)声明为密码来明确说明没有密码。

要使用 Strapi 连接到 PostgreSQL 数据库:

  1. (可选) 如果您已从 postgres@ 用户切换,请运行以下命令:
bash
sudo -u postgres psql
[sudo] password for your-name: # 出现此身份验证提示
psql (14.8 (Ubuntu 14.8-0ubuntu0.22.04.1)) # 输入密码后的 shell 响应
输入“help”获取帮助。
  1. 运行以下命令更改您创建的用户并添加密码,将 your-name'your-password' 替换为您自己的值:
bash
psql
# 在下面输入 SQL 命令(包括引号和分号)。
postgres=# ALTER USER your-name PASSWORD 'your-password';
ALTER ROLE # SQL 命令后的 shell 响应
# 然后使用 \q 命令退出,因为我们不想更改角色。
postgres=# \q
exit
  1. (可选) 如果您在首次设置 Strapi 时选择 PostgreSQL 作为初始数据库选择,则 pg 包会自动安装在本地。如果您的 Strapi 项目使用 SQLite,请安装 pg 依赖包。在您的开发机器上,在 Strapi 项目文件夹中运行以下命令:
bash
npm install pg --save

记下数据库名称、用户名和密码以供日后使用。

为本地开发配置

  • 您必须在本地安装并设置 git
  • 应该为您之前创建的 Strapi 项目初始化 Git。
  1. config/database.js 的内容替换为以下内容:
js
path: ./config/database.js
js
module.exports = ({ env }) => ({
  connection: {
    client: 'postgres',
    connection: {
      host: env('DATABASE_HOST', '127.0.0.1'),
      port: env.int('DATABASE_PORT', 5432),
      database: env('DATABASE_NAME', 'strapidb'),
      user: env('DATABASE_USERNAME', ''),
      password: env('DATABASE_PASSWORD', ''),
      ssl: env.bool('DATABASE_SSL', false) && {
        rejectUnauthorized: env.bool('DATABASE_SSL_SELF', false),
      },
    },
    debug: false,
  },
})
  1. Push these changes to Github by running the following commands:
bash
git add .
git commit -m "Configured production/database.json"
git push

从 GitHub 部署

现在,您将通过从 GitHub 克隆 Strapi 项目来将其部署到您的 Droplet。

  1. 从您的终端,以非 root 用户身份登录到您的 Droplet,运行以下命令,将“your-handle”和“your-project”替换为您的 GitHub 用户名和项目名称:
bash
cd ~
git clone https://github.com/your-handle/your-project.git
  1. 可选)如果使用基于密码的身份验证而不是 SSH 密钥:
  • 尝试克隆时,系统将提示您输入“your-handle”和密码。这实际上是一个 个人访问令牌 (PAT),因为密码已被 弃用
  • 为了解决稍后使用 webhook 时出现的 问题,请运行以下命令,将 your-handleyour-patyour-project 替换为适当的值:
bash
cd ~/your-project
git remote add origin https://your-handle:your-pat@github.com/your-handle/your-project.git

# 如果响应为“fatal: remote origin already exist.”,则运行:
git remote set-url origin https://your-handle:your-pat@github.com/your-handle/your-project.git
  1. 导航到项目的文件夹,即 Strapi 的根文件夹,并通过运行以下命令安装项目的 npm 包,将 your-project 替换为通过 GitHub 上的项目名称:
bash
cd your-project
npm install
  1. 通过运行以下命令构建 Strapi 的管理面板:
bash
NODE_ENV=production npm run build
  1. 由于 Strapi 默认使用端口 1337,您必须通过运行以下命令配置您的 ufw 防火墙以允许访问此端口以进行测试和安装:
bash
cd ~
sudo ufw allow 1337/tcp
sudo ufw enable

y 回答 命令可能会破坏现有的 ssh 连接。继续操作 (y|n)? 消息。

您的 Strapi 项目现已安装在您的 DigitalOcean Droplet 上。在创建第一个用户之前,您必须安装并配置 Nginxpm2、配置 ecosystem.config.js` 文件和环境变量 以及 设置 webhook

安装和配置 Nginx 网络服务器

  1. 按照 DigitalOcean 官方文档 上的指南安装和配置 Nginx,并牢记以下特殊性:
  • 您可以为 Strapi 项目添加域名或使用子域名。
  • “步骤 5 - 设置服务器块”中对 your_domain 的引用应包含 TLD,(例如 example.com)。
  • “步骤 5 - 设置服务器块”中的位置字段(指定为 try_files $uri $uri/ =404;)必须替换为以下内容:
proxy_pass http://localhost:1337;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header 连接 'upgrade';
proxy_set_header 主机 $host;
proxy_cache_bypass $http_upgrade;
  • Nginx 有一个名为 client_max_body_size配置设置,它将阻止大于指定大小的文件上传。由于其默认值只有 1MB,因此需要进行调整。请注意,strapi 中间件已经负责解析最大 200MB 的文件大小的请求。
...
http {
...
client_max_body_size 200m; # 或 0 禁用
...
}
...
  1. 通过运行以下命令关闭对外部流量的端口:
bash
cd ~
sudo ufw denied 1337

安装和配置 pm2

pm2 允许您保持 Strapi 项目处于活动状态并在不停机的情况下重新加载它。

确保您以非 root 用户身份登录并通过运行以下命令全局安装 pm2:

bash
npm install pm2@latest -g

配置 ecosystem.config.js.env 文件

ecosystem.config.js 管理 Strapi 连接到数据库所需的数据库连接变量。ecosystem.config.js 也被 pm2 用于在 Strapi 文件系统本身的文件发生任何更改时重新启动项目,例如当 GitHub 收到更新时。您可以在 官方 pm2 文档 中阅读有关 ecosystem.config.js 文件的更多信息。

  1. 使用以下命令创建 ecosystem.config.js 文件并打开它。我们将使用 nano 编辑器:
bash
cd ~
pm2 init
sudo nano ecosystem.config.js
  1. 将文件中的样板内容替换为以下内容:
js
module.exports = {
  apps: [
    {
      name: 'strapi-app',
      cwd: '/home/your-name/your-project', // 必须有绝对路径
      script: 'npm',
      args: 'start',
      env: {
        NODE_ENV: 'production',
      },
    },
  ],
}
  1. 转到 your-project 文件夹以创建并打开 .env 文件:
bash
cd ~/your-project
sudo nano .env
  1. 将 Strapi 应用程序的本地 .env 文件的内容复制到当前打开的文件中nano。将数据库名称和凭据替换为在数据库设置期间指定的名称和凭据。
bash
HOST=0.0.0.0
PORT=1337
APP_KEYS=your-app-keys # 自动生成
API_TOKEN_SALT=your-api-token-salt # 自动生成
ADMIN_JWT_SECRET=your-admin-jwt-secret # 自动生成
TRANSFER_TOKEN_SALT=your-transfer-token-salt # 自动生成
# 数据库
DATABASE_CLIENT=postgres
DATABASE_HOST=127.0.0.1
DATABASE_PORT=5432
DATABASE_NAME=your-database-name # 在数据库设置期间指定
DATABASE_USERNAME=your-database-username # 在数据库设置期间指定
DATABASE_PASSWORD=your-database-password # 在数据库设置期间指定
DATABASE_SSL=false
JWT_SECRET=your-jwt-secret #自动生成
  1. 运行以下命令启动 pm2
bash
cd ~
pm2 start Ecosystem.config.js

pm2 现已设置为使用 ecosystem.config.js 来管理更改后重新启动应用程序。这是推荐的最佳做法。

配置 .env 以在系统启动时启动 Strapi

以下步骤根据 DigitalOcean PM2 设置文档 修改而来:

  1. 生成启动脚本,通过运行以下命令启动 PM2:
bash
$ cd ~
$ pm2 startup systemd

# Shell 输出
[PM2] 找到初始化系统:systemd
[PM2] 要设置启动脚本,请复制/粘贴以下命令:
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u your-name --hp /home/your-name
  1. 复制上面生成的命令并粘贴到终端:
bash
$ sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u your-name --hp /home/your-name

# Shell 输出
[PM2] 找到初始化系统:systemd
平台 systemd

# ...

[PM2] [v] 命令已成功执行。
+---------------------------------------+
[PM2] 重启时冻结进程列表:
$ pm2 save

[PM2] 删除初始化脚本:
$ pm2 unstartup systemd
  1. 保存新的 PM2 进程列表和环境:
bash
pm2 save

# Shell 输出
[PM2] 保存当前进程列表...
[PM2] 已成功保存在 /home/your-name/.pm2/dump.pm2 中

您可以使用 sudo reboot 命令测试上述脚本是否在系统重启时有效。再次以非 root 用户身份登录并运行“pm2 list”和“systemctl status pm2-your-name”以验证一切正常。您还可以使用“pm2 logs strapi-app --lines 20”检查日志。

Strapi 生产服务器现在应该可以在 Nginx 设置期间 指定 的域中使用。登录屏幕可在同一域的“/admin”端点上使用。

在 DigitalOcean/GitHub 上设置 webhook

如果您的项目是在 GitHub 上设置的,则必须使用 webhook 在那里配置您的 Strapi 项目存储库。

有关 webhook 的更多信息,请参阅 GitHub 文档DigitalOcean 文档

  1. 转到 GitHub 上的“your-project”并按照 DigitalOcean 文章中的 步骤 1 设置 webhook。记下“your-webhook-secret”中输入的内容,以备后用。
  2. 在您的服务器上创建一个 webhook 脚本。以下命令创建一个名为“webhook.js”的新文件,该文件将包含 2 个变量:
bash
cd ~
mkdir NodeWebhooks
cd NodeWebhooks
sudo nano webhook.js
  1. 在打开的“nano”编辑器中,粘贴以下脚本,确保更新文件顶部的“secret”和“repo”变量的值。然后保存并退出。
    js
    var secret = 'your-webhook-secret' // created in GitHub earlier
    var repo = '~/your-project'
    
    const http = require('node:http')
    const crypto = require('node:crypto')
    const exec = require('node:child_process').exec
    
    const PM2_CMD = 'cd ~ && pm2 startOrRestart ecosystem.config.js'
    
    http
      .createServer((req, res) => {
        req.on('data', (chunk) => {
          const sig
            = `sha1=${
             crypto
              .createHmac('sha1', secret)
              .update(chunk.toString())
              .digest('hex')}`
    
          if (req.headers['x-hub-signature'] === sig) {
            exec(`cd ${repo} && git pull && NODE_ENV=production npm run build && ${PM2_CMD}`, (error, stdout, stderr) => {
              if (error) {
                console.error(`exec error: ${error}`)
                return
              }
              console.log(`stdout: ${stdout}`)
              console.log(`stderr: ${stderr}`)
            })
          }
        })
    
        res.end()
      })
      .listen(8080)
    

上面的脚本声明了一个名为PM2_CMD的变量,该变量在从 GitHub 拉取后用于更新您的项目。脚本首先更改为主目录,然后将变量PM2_CMD作为pm2 restart strapi运行。

  1. 通过运行以下脚本允许端口与端口 8080 的外部 Web 流量进行通信:
bash
sudo ufw allow 8080/tcp
sudo ufw enable

y 接受 Command may break already ssh connections. Proceed with operation (y|n)? 消息。

之前,您设置了 pm2,以便在 Droplet 重新启动或启动时启动 your-project 的服务。现在,您将对 webhook.js 脚本执行相同操作。

  1. 将 webhook 安装为 systemd 服务。首先运行 echo $PATH,然后复制输出以供下一步使用。
bash
echo $PATH

# Shell 输出
/home/your-name/.npm-global/bin:/home/your-name/bin:/home/your-name/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
  1. 创建 webhook.service 文件:
bash
sudo nano /etc/systemd/system/webhook.service
  1. 将以下配置详细信息粘贴到打开的 nano 编辑器中。确保将两个位置的 your-name 替换为您的用户名。然后,将上面输出到 shell 的路径粘贴到 your-path 的位置,然后保存并退出:
bash
[Unit]
Description=Github webhook
After=network.target

[Service]
Environment=PATH=your-path
Type=simple
User=your-name
ExecStart=/usr/bin/node /home/your-name/NodeWebhooks/webhook.js
Restart=on-failure

[Install]
WantedBy=multi-user.target
  1. 启用并启动新服务,使其在系统启动时启动:
bash
sudo systemctl enable webhook.service
sudo systemctl start webhook
  1. 检查 webhook 的状态:
bash
sudo systemctl status webhook
  1. 可选)按照 DigitalOcean 文档 中所示测试您的 webhook,但使用 node webhook.js 命令,因为 nodejs 已弃用。有时即使身份验证失败,GitHub 也会显示最近成功交付。最可靠的方法是将代码更改推送到 GitHub 存储库,然后再次运行 sudo systemctl status webhook 以查看最新提交的 SHA 是否已注册。

后续步骤

🥳 您的 Strapi 项目已使用 Ubuntu 22.04 安装在 DigitalOcean Droplet 上。