部署
在编写完成后,你需要部署你的机器人来使得用户能够使用它。通常,会将机器人部署在服务器上,来保证服务持久运行。
在开发时机器人运行的环境称为开发环境,而在部署后机器人运行的环境称为生产环境。与开发环境不同的是,在生产环境中,开发者通常不能随意地修改/添加/删除代码,开启或停止服务。
部署前准备
在生产环境中,为确保机器人能够正常运行,你需要固定你的依赖库版本。下面提供了几种常见的文件格式与生成方式:
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.2
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.2
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
警告
请配合虚拟环境使用,如 venv 等,请勿直接在 Linux 服务器系统环境中安装。