配置好域名和面板之后,我们就要正式开始学习服务器运维了!在服务器上,除了Bot框架本身,还需要运行很多其他的服务去配合Bot,服务器上比较重要的一点是要把服务独立化,便于管理,也不容易服务之间互相影响,于是我们就要学习Docker这种容器化技术!同样的,如果只需要速成Bot如何跑起来,可以直接跳转到构建Koishi应用,有兴趣再回来学习原理!
Docker是什么?
Docker允许开发者们很好地将服务和运行时需要依赖的环境塞到一个容器当中,发布到多种平台上,包括Windows,Linux,MacOS等等,解决了迁移困难,配置困难的问题。Docker以极低的性能额外开销,带来了隔离化和易迁移的好处!
名词解释
镜像:只读,包含了所有需要编译的代码,相当于创建了一个运行环境的模板,当我们需要创建若干个类似的服务时,我们可以使用镜像快速创建若干个容器,便于管理!
Dockerfile:定义了镜像中的所有行为,包括容器有什么,依赖什么,怎么构建,如何运行
容器:容器中包含了需要运行的服务源代码或可执行文件,以及服务所依赖的运行环境,配置文件等等
应用商店
我们安装1Panel的时候已经安装好Docker了,所以我们现在不需要额外安装Docker
我们打开1Panel面板,打开应用商店,这里有许多现成的Docker应用,可以动动手指就能轻松安装到服务器上

那如果应用商店没有我们想要的应用或者不符合需求呢?那就只能够手写Dockerfile,然后构建镜像,然后再生成一个实例!
Docker基础知识
我们从1Panel的 容器/创建容器 界面开始逐步讲解Docker的基础知识!

名称就是容器的名字,起一个你喜欢的名字即可!镜像可以是本地我们自己构建的,也可以是远程仓库中的镜像,比如说Nginx提供的Docker镜像就叫nginx:latest
端口需要根据实际情况来配置。我们先来解释一下容器和宿主机(服务器本体)网络通信的主要原理!
我们看到网络选项下拉栏中有若干个选项,主要分为host网络,和非host网络(自定义网络)两类。当我们选用host网络时,容器会和宿主机的网络共享,在容器中端口等效于宿主机的端口,比如说使用host网络时,容器中有一个开在12345端口上的WebUI,那我们就可以直接添加nginx的配置文件,使一个子域名映射到宿主机上的12345端口;
当我们选用自定义网络时,选择自定义网络的容器会共享一个虚拟网卡,不和宿主机共享,此时需要配置一个穿透,即端口映射,比如说某个服务的会在3000端口提供一个Web控制台,我们可以把容器内的3000端口映射到宿主机的8080端口,好比我们在8080端口后接了一根宿主机向容器的单向访问管道,表现为好像服务是在宿主机的8080端口上运行的。
服务器侧端口需要根据端口占用情况酌情选择,当一个端口占用的时候就不能选了。
我们检查端口占用情况的指令如下:打开Termius,比如说要检查服务器侧8080端口的占用情况,我们就需要:
sudo lsof -i:8080
如果有输出的内容,就证明有占用,不能用,我们需要检查别的端口,直到找到一个没有占用的端口。
比如说服务是跑在3000端口上,检查到8089端口没有占用,就在下图左侧填8089,右侧填3000:

网络我们选择bridge,让所有容器能够共享网络;IPv4地址不用填,会自动分配地址,IPv6地址这里先不考虑;挂载的意思是,当容器运行的时候,将宿主机上某个文件夹和容器中某个文件夹绑定,这个也是需要根据不同服务考虑的。

Command指的是启动的指令,比如说对于Node.js应用,可能是npm start,需要根据不同服务考虑
这里仅做入门,具体的教程可以参考runoob的Docker教程!以后笔者也许会详细讲解相关内容!
下文会提供在应用商店安装博客网站Wordpress的流程,以及如何从头构建Koishi镜像的方法(下面会解释要从头构建的原因)
Docker常用指令
对于有1Panel的用户来说,如果不熟悉操作,我们只需要知道在应用商店没法满足我们需求的时候如何构建镜像即可,其他操作基本来说都可以在1Panel面板中完成,如果还有其他问题可以在Bot群或者评论区提问!
指令只需要在Termius中输入即可!以下内容引用自runoob官网:
以下是常用的 Docker 客户端命令:
命令 功能 示例 docker run启动一个新的容器并运行命令 docker run -d ubuntudocker ps列出当前正在运行的容器 docker psdocker ps -a列出所有容器(包括已停止的容器) docker ps -adocker build使用 Dockerfile 构建镜像 docker build -t my-image .docker images列出本地存储的所有镜像 docker imagesdocker pull从 Docker 仓库拉取镜像 docker pull ubuntudocker push将镜像推送到 Docker 仓库 docker push my-imagedocker exec在运行的容器中执行命令 docker exec -it container_name bashdocker stop停止一个或多个容器 docker stop container_namedocker start启动已停止的容器 docker start container_namedocker restart重启一个容器 docker restart container_namedocker rm删除一个或多个容器 docker rm container_namedocker rmi删除一个或多个镜像 docker rmi my-imagedocker logs查看容器的日志 docker logs container_namedocker inspect获取容器或镜像的详细信息 docker inspect container_namedocker exec -it进入容器的交互式终端 docker exec -it container_name /bin/bashdocker network ls列出所有 Docker 网络 docker network lsdocker volume ls列出所有 Docker 卷 docker volume lsdocker-compose up启动多容器应用(从 docker-compose.yml文件)docker-compose updocker-compose down停止并删除由 docker-compose启动的容器、网络等docker-compose downdocker info显示 Docker 系统的详细信息 docker infodocker version显示 Docker 客户端和守护进程的版本信息 docker versiondocker stats显示容器的实时资源使用情况 docker statsdocker login登录 Docker 仓库 docker logindocker logout登出 Docker 仓库 docker logout常用选项说明:
-d:后台运行容器,例如docker run -d ubuntu。-it:以交互式终端运行容器,例如docker exec -it container_name bash。-t:为镜像指定标签,例如docker build -t my-image .。
认识Koishi Bot
Koishi 是一个跨平台、可扩展、高性能的聊天机器人框架。
它的名字和图标设计来源于东方 Project 中的角色 古明地恋 (Komeiji Koishi)。古明地恋是一个会做出无意识举动的角色,取这个名字既象征着聊天机器人的主题,也蕴含了开发者为之倾注的热爱。Koishi提供丰富的插件系统,可以热重载(就是即保存即运行)的插件开发环境,提供非常多平台的Adapter(官方QQ机器人、QQ Onebot、Telegram、Discord等等),基于Typescript开发,具有十分先进且强大的开发环境(如类型系统、代码提示等等)
总之笔者认为,Koishi是和Nonebot一样强大的划时代框架(自认为),十分推荐用来构建更先进的机器人!更多可以查阅Koishi官网以及插件市场和官方插件一览
构建Koishi应用
接下来我们面临两种选择!如果只需要使用内置插件与插件市场内的插件或完全不需要进行服务器远程插件开发(即本地开发完后再上传),可以查看直接通过1Panel市场安装;如果需要在服务器上进行开发(笔者的选择),则需要查看手动构建Koishi模板项目镜像(并不复杂!)但是,无论选择哪个方案,都需要查看将Koishi安全地暴露至公网!
直接通过1Panel市场安装
我们进入1Panel面板,点击应用商店,搜索MariaDB,点击安装:


注意,需要记录下Root用户密码,也可以更改为自己的常用密码!以及绝对不能勾选端口外部访问,这将会导致数据库暴露在公网上引发安全问题!
搜索Koishi,点击安装:


这里数据库服务选择为刚才安装的MariaDB服务即可,然后需要查看5140端口是否被占用,我们打开Termius,输入:
sudo lsof -i:5140
如果没有内容输出,则表明可以将Koishi服务开在5140端口上,否则要换一个端口,直到查询到它未被占用。以及同样的,不需要端口外部访问!
手动构建Koishi模板项目镜像
首先说一下这么做的原因,因为当使用应用商店提供的镜像时,不能以开发模式运行,不能创建新插件,不能进行插件开。如果需要将本地的插件上传至服务器需要配置非常多东西,为了简化入门流程,直接选择在服务器上开发,需要使用模板项目手动构建镜像!
首先我们打开Termius,然后输入:
cd /home # 设置路径为home文件夹
npm init koishi@latest # 创建模板项目
然后根据下面这张图片完成安装步骤,为了方便和与教程统一,可以把项目名称设置为koishi-template,下文都会用这个名称代替:

最后安装后会显示下图,我们使用组合键Ctrl+C(Mac系统下的command+C)退出程序:

在1Panel的系统/文件页面,在目录/home/koishi-template/koishi.yml中添加一行并保存(如果这一行有就不用加了!):
group:server:
server:k4saya:
host: 0.0.0.0 #添加这一行 注释不要写进去!!
port: 5140
maxPort: 5149
在1Panel的系统/文件页面,在目录/home/koishi-template中创建文件Dockerfile,打开填写:
FROM node:lts-alpine
WORKDIR /koishi
COPY . .
EXPOSE 5140
CMD ["npm","run","dev"]
此时我们再输入下列指令:
cd /home/koishi-template
rm -rf node_modules # 删除依赖
npm i # 重新安装依赖 避免bug出现
docker build -t koishi-template . --no-cache
接下来只需要静等指令结束即可!然后我们进入1Panel面板去使用这个镜像:

名称按自己喜好填写,镜像下拉栏中选择koishi-template:latest,然后选择暴露端口,以及保持网络选择bridge
我们打开Termius,输入:
sudo lsof -i:5140
如果没有内容输出,则表明可以将Koishi服务开在5140端口上,否则要换一个端口,直到查询到它未被占用。以及同样的,不需要端口外部访问!假设5143可用,我们在端口这里左侧填5143,右侧填5140。

在挂载中填写我们需要持久化的内容。什么是持久化?在 Docker 里,“持久化”指的是让容器里的数据在 容器停止、删除或重新创建之后依然存在,而不是随着容器的生命周期一起消失。容器本质上是运行在 镜像的只读层 之上的一个 可写层(Container Layer)。这个可写层随容器存在,容器一旦删除,这层就会被清理,数据也就丢了。所以进行挂载的原因有两点:一个是如果不进行挂载,我们容器中所有东西会被塞到一个匿名卷中,完全无法直接修改其中的内容;另一个是如果删除或者重建容器后,不持久化的内容会全部丢失。
因为我们通过直接读取服务器上已有的项目来建立镜像,所以说可以直接在建立镜像的目录来创建容器,我们在本机目录中填写/home/koishi-template,容器目录中填写/koishi,其他没有提及的选项都可以不动
将Koishi安全地暴露至公网
首先按照上一节教程添加koishi的子域名,比如说叫koishi.abc.xyz,最后的Nginx配置不能照抄,需要添加不同的conf文件!
打开1Panel的系统/文件,导航至 /etc/nginx/conf.d 中,创建新文件koishi.conf,内容如下:
server {
listen 80;
server_name koishi.abc.xyz;
# 这里改成你的子域名
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name koishi.abc.xyz;
# 这里改成你的子域名
ssl_certificate /etc/ssl/certs/morami.pem;
ssl_certificate_key /etc/ssl/certs/morami.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
location / {
proxy_pass http://localhost:5140/;
# 这里改成你的Koishi服务在**服务器一侧的**端口号
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $http_host;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
此时我们输入Koishi服务子域名(比如koishi.abc.xyz),应该已经可以正常访问了,但现在这个服务处于没有安全保障的环境,我们需要启用一个官方插件,我们点击左侧边栏的第二个选项插件配置,选择console中的auth插件,填写常用的用户名和密码,并且在右上角左数第一个按钮启用插件即可:

启用后页面会重新加载,稍等片刻后会出现登录界面,选择用户密码登录即可!

最后
到这里为止,我们已经完全将开发环境搭建完毕了!下一节中会讲解Koishi各个界面的用处,创建第一个插件,以及编程的基础知识,再会!

Comments NOTHING