* Update deployment.md 重新提交 PM2 部署文档 * ♻️ 📝 Refactor PM2 deplotyment document * ✏️ Fix typo in PM2 deployment document * Update deployment.md fix 表述歧义 * 🚚 copy docs to next version Co-authored-by: Mix <32300164+mnixry@users.noreply.github.com> Co-authored-by: yanyongyu <42488585+yanyongyu@users.noreply.github.com>
9.7 KiB
sidebar_position | description |
---|---|
11 | 部署你的机器人 |
部署
在编写完成后,你需要部署你的机器人来使得用户能够使用它。通常,会将机器人部署在服务器上,来保证服务持久运行。
在开发时机器人运行的环境称为开发环境,而在部署后机器人运行的环境称为生产环境。与开发环境不同的是,在生产环境中,开发者通常不能随意地修改/添加/删除代码,开启或停止服务。
部署前准备
在生产环境中,为确保机器人能够正常运行,你需要固定你的依赖库版本。下面提供了几种常见的文件格式与生成方式:
-
poetry.lock
poetry 依赖管理工具使用的 lock 文件,通常会在安装依赖时自动生成,或者使用
poetry lock
来生成。 -
pdm.lock
pdm 依赖管理工具使用的 lock 文件,通常会在安装依赖时自动生成,或者使用
pdm lock
来生成。 -
Pipfile.lock
Pipenv 依赖管理工具使用的 lock 文件,通常会在安装依赖时自动生成,或者使用
pipenv lock
来生成。 -
requirements.txt
如果你未使用任何依赖管理工具,你可以使用
pip freeze
来生成这个文件。
使用 Docker 部署(推荐)
请自行参考 Docker 官方文档 安装 Docker。
在生产环境安装 docker-compose 工具以便部署机器人。
编译镜像与部署配置
在项目目录下添加以下两个文件(以 poetry 和 FastAPI 驱动器为例):
FROM python:3.9 as requirements-stage
WORKDIR /tmp
COPY ./pyproject.toml ./poetry.lock* /tmp/
RUN curl -sSL https://install.python-poetry.org -o install-poetry.py
RUN python install-poetry.py --yes
ENV PATH="${PATH}:/root/.local/bin"
RUN poetry export -f requirements.txt --output requirements.txt --without-hashes
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9
WORKDIR /app
COPY --from=requirements-stage /tmp/requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir --upgrade -r requirements.txt
RUN rm requirements.txt
COPY ./ /app/
version: "3"
services:
nonebot:
build: .
ports:
- "8080:8080" # 映射端口到宿主机 宿主机端口:容器端口
env_file:
- ".env.prod" # fastapi 使用的环境变量文件
environment:
- ENVIRONMENT=prod
- APP_MODULE=bot:app
- MAX_WORKERS=1
network_mode: bridge
配置完成后即可使用 docker-compose up -d
命令来启动机器人并在后台运行。
CI/CD
配合 GitHub Actions 可以完成 CI/CD,在 GitHub 上发布 Release 时自动部署至生产环境。
在 Docker Hub 上创建仓库,并将下方 workflow 文件中高亮行中的仓库名称替换为你的仓库名称。
前往项目仓库的 Settings
> Secrets
> actions
栏目 New Repository Secret
添加部署所需的密钥:
DOCKERHUB_USERNAME
: 你的 Docker Hub 用户名DOCKERHUB_PASSWORD
: 你的 Docker Hub PAT(创建方法)DEPLOY_HOST
: 部署服务器 IP 地址DEPLOY_USER
: 部署服务器用户名DEPLOY_KEY
: 部署服务器私钥DEPLOY_PATH
: 部署服务器上的项目路径
将以下文件添加至项目下的 .github/workflows/
目录下:
name: Docker Hub Release
on:
push:
tags:
- "v*"
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Docker
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Generate Tags
uses: docker/metadata-action@v3
id: metadata
with:
images: |
{organization}/{repository}
tags: |
type=semver,pattern={{version}}
type=sha
- name: Build and Publish
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }}
name: Deploy
on:
workflow_run:
workflows:
- Docker Hub Release
types:
- completed
jobs:
deploy:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- name: start deployment
uses: bobheadxi/deployments@v0.6
id: deployment
with:
step: start
token: ${{ secrets.GITHUB_TOKEN }}
env: official-bot
- name: remote ssh command
uses: appleboy/ssh-action@master
env:
DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }}
with:
host: ${{ secrets.DEPLOY_HOST }}
username: ${{ secrets.DEPLOY_USER }}
key: ${{ secrets.DEPLOY_KEY }}
envs: DEPLOY_PATH
script: |
cd $DEPLOY_PATH
docker-compose down
docker-compose pull
docker-compose up -d
- name: update deployment status
uses: bobheadxi/deployments@v0.6
if: always()
with:
step: finish
token: ${{ secrets.GITHUB_TOKEN }}
status: ${{ job.status }}
deployment_id: ${{ steps.deployment.outputs.deployment_id }}
将上一部分的 docker-compose.yml
文件以及 .env.prod
配置文件添加至 DEPLOY_PATH
目录下,并修改 docker-compose.yml
文件中的镜像配置,替换为 Docker Hub 的仓库名称。
- build: .
+ image: {organization}/{repository}:latest
使用 Supervisor 部署
[supervisord]
[fcgi-program:nonebot]
socket=tcp://localhost:8080
command=python3 -m uvicorn --fd 0 bot:app
directory=/path/to/bot
autorestart=true
startsecs=10
startretries=3
numprocs=1
process_name=%(program_name)s-%(process_num)d
stdout_logfile=/path/to/log/nonebot.out.log
stdout_logfile_maxbytes=2MB
:::warning 警告 请配合虚拟环境使用,如 venv 等,请勿直接在 Linux 服务器系统环境中安装。 :::
使用 PM2 部署
:::tip 提示 在阅读这一节的过程中, 你总是可以参照 PM2 官方文档 来得到更多的信息 :::
安装 PM2
需要有 NodeJS 10+环境来运行 PM2, (什么 NTR)
然后通过以下命令安装即可:
npm install -g pm2
在安装完成后, 执行以下指令, 如果得到类似的输出则说明你安装成功了 PM2:
$ pm2 -V
5.2.0
在后台运行进程
:::tip 提示 以下步骤要求您在您 Bot 的工作目录下执行
如果您使用了虚拟环境, 请确保 Bot 启动命令能在虚拟环境中正常执行
换言之, Bot 程序需要在当前终端环境下正常运行 :::
启动 Bot 进程
$ pm2 start "python -m nb_cli run" # 或者直接 nb run 也行
[PM2] Starting /usr/bin/bash in fork_mode (1 instance)
[PM2] Done.
┌─────┬────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├─────┼────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 0 │ nb run │ default │ N/A │ fork │ 93061 │ 0s │ 0 │ online │ 0% │ 8.3mb │ mix │ disabled │
└─────┴────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
此时 Bot 进程就在后台运行了, 注意到表格第一列的 ID, 它可以用来查看和控制进程的状态
常用命令
更具体的用法请移步 PM2 官方文档, 如果想要详细示例建议直接上手试试
其中命令中的所有<id>
应该替换为上文启动进程后返回的 ID
-
查看最近 150 行日志
pm2 log <id> --lines 150
-
实时监控所有进程日志
pm2 monit
-
展示当前 PM2 管理的所有进程
pm2 ls
-
停止某个进程
pm2 stop <id>
-
删除某个进程
pm2 del <id>
-
重启某个进程
pm2 restart <id>
-
保存当前进程列表
pm2 save
-
恢复保存的进程列表
pm2 resurrect
-
设置开机自动启动进程列表
pm2 startup
- 需要执行过
pm2 save
如果不是 root 用户执行, 则需要手动添加指令返回的环境变量