docker安装并跑通QQ机器人实践(2)-签名服务器bs-qsign搭建

news2024/11/20 6:27:12

在前文中,我们详尽阐述了QQ机器人的搭建过程及其最终实现的各项功能展示。接下来,我们将转向探讨该项目基于Docker构建服务的具体实践。本篇将以QQ机器人签名服务——qsign为起点,逐步展开论述。

1 获取和运行 xzhouqd/qsign:8.9.63 镜像

1.1 获取镜像

获取镜像有两种方式

1.1.1 从 Docker Hub 拉取镜像
docker pull xzhouqd/qsign:8.9.63
1.1.2 从本地存储文件加载镜像
docker load -i xzhouqd_qsign_8.9.63.tar

上面提及的示例文件 “xzhouqd_qsign_8.9.63.tar” ,实际上是由 Docker 镜像导出并存储到本地的压缩文件。那么,这样的文件是如何生成的呢?接下来,我们将逐步揭示这一过程。
首先,我们需要使用 Docker 的镜像列举命令来确认目标镜像是否已经存在于本地的 Docker 环境中:

docker images

执行的结果如下图:
在这里插入图片描述
通过执行上述命令,您将看到一个列表,其中包含了本地已有的所有镜像或指定镜像的信息。如果目标镜像确实存在,它将在列表中显示;否则,需要从远程仓库(如Docker Hub)拉取或通过其他方式获取(如:1.1.1所述 )。

假设“xzhouqd/qsign:8.9.63”镜像已存在于本地Docker环境中,接下来我们将演示如何将其导出为.tar文件:

docker save -o xzhouqd_qsign_8.9.63.tar xzhouqd/qsign:8.9.63

这条命令中:

  • docker save 是用于导出镜像的Docker命令。
  • -o xzhouqd_qsign_8.9.63.tar 指定了导出后压缩文件的名称和路径。
  • xzhouqd/qsign:8.9.63 是要导出的镜像的完整名称(包括仓库名、镜像名和标签)。

执行此命令后,Docker将把指定镜像及其依赖的所有层打包成一个名为“xzhouqd_qsign_8.9.63.tar”的.tar文件,并将其保存到当前工作目录下。至此,我们就成功创建了由Docker镜像生成的本地压缩文件。

1.2 由镜像运行生成容器

docker run -d `# -d 表示保持后台运行` \
	--restart=always `# 表示开机即自动运行` \
	--name bs-qsign `容器名称` \
	-p 18080:8080 `# 端口映射,将容器的 8080 端口映射到宿主机的 18080 端口` \
	-e ANDROID_ID=xxxxxxx `# 此值可以随便设置,但需要和 cqhttp 里的设置一致` \
	xzhouqd/qsign:8.9.63 # 镜像文件

小贴士: 在多行Shell命令文件中,欲在行尾使用反斜杠 \ 进行续行的同时添加注释,可于 \ 之前插入一对反引号 ` 包裹的 # 字符来实现,以此实现续行与注释的结合。

至此,bs-qsign 签名服务器已顺利完成搭建。为便于后续进行参数的动态调整、实现与其他容器间配置的统一管理,以及一键启动具有复杂功能的扩展服务,建议将相关参数迁移至配置文件进行妥善存储。

2 创建配置文件:config.sh

此配置文件,由以下几个部分构成

2.1 基本参数

appName="bs-qsign" # 应用名称
appVersion="0.0.1" # 应用版本号
imageName="xzhouqd/qsign:8.9.63" # 镜像名称
containerName="$appName" # 容器名称

2.2 docker run 相关配置

通常情况下,我们在配置Docker容器时会涉及以下三个核心要素:

  • Volumes —— 用于宿主机与容器之间实现文件或目录的双向同步映射,确保数据持久化及共享。在配置文件里以变量 volumes 表示。

  • Ports —— 通过端口映射,使得外部能够访问到容器内部运行的服务,实现网络通信。在配置文件里以变量 ports 表示。

  • Environments —— 设置环境变量,为容器内应用程序提供必要的运行时配置信息。在配置文件里以变量 envs 表示。

对于上述各项配置,可根据实际应用场景自由选择适用的项目。对于暂时无需使用的配置项,可以选择对其进行注释以备后续参考,或者直接删除以保持配置文件简洁。

# docker run 相关配置(可选项,如为空,可不填)

volumes=(/path_in_host:/path_in_container) 
# /path_in_host - 宿主机目录
# /path_in_container - 容器目录

ports=("18080:8080") # 宿主机端口:容器端口

envs=("ANDROID_ID=tanbushi01") # 变量名=变量值

上述以圆括号 () 包围的数据结构在Shell脚本中定义了一个数组。其中,用单引号或双引号包裹的文本构成数组的各个元素,多个元素之间以空格分隔。以包含多个端口映射的数组为例:

ports=("18080:8080" "15703:5703")

这里,数组 ports 包含两个元素:“18080:8080” 和 “15703:5703”,分别代表将宿主机的18080端口映射到容器的8080端口,以及将宿主机的15703端口映射到容器的5703端口。

类似地,对于 volumes(卷映射)和 envs(环境变量)数组的定义,只需按照相同的方式指定各自的映射关系或环境变量键值对即可:

volumes=("host_path1:container_path1" "host_path2:container_path2")
envs=("VAR1=value1" "VAR2=value2")

以上述方式声明的 volumes 数组表示将宿主机的 host_path1 目录映射到容器的 container_path1,host_path2 目录映射到 container_path2。而 envs 数组则设置了两个环境变量:VAR1 的值为 value1,VAR2 的值为 value2。

2.3 标记 config.sh 脚本执行状态

通过设置变量 configured 来标记 config.sh 脚本是否已执行过:

configured=true

当该变量值为 true 时,表明 config.sh 脚本已成功执行过一次,旨在防止后续重复加载或执行配置,确保系统的稳定性和一致性。

最终的config.sh内容如下:

#!/bin/bash

# 基本参数
appName="bs-qsign" # 应用名称
appVersion="0.0.1" # 应用版本号
imageName="xzhouqd/qsign:8.9.63" # 镜像名称
containerName="$appName" # 容器名称

# docker run 相关配置(可选项,如为空,可不填)
ports=("18080:8080")
envs=("ANDROID_ID=tanbushi01")

# 标记是否已经配置过
configured=true # 标记变量——此脚本已经被执行过

3 运行容器的脚本:run.sh

#!/bin/bash

# 运行初始化脚本
. ../../shell-scripts/run_init.sh

# 创建并执行临时文件——实现 docker run 命令(临时文件不是在容器里哦!)
. ../../shell-scripts/run_in_tmp.sh

echo ""
echo "*********************************************************"
echo "成功创建容器:【 $containerName 】!"
echo "*********************************************************"
echo ""

3.1 初始化脚本:run_init.sh

#!/bin/bash

set -e # 遇到错误时退出脚本

# 判断是否运行过配置文件 config.sh,如果未运行过,则运行配置文件
if [ -z "$configured" ]; then
  . ./config.sh
fi

# 检查 Docker 是否在运行
if ! docker info > /dev/null 2>&1; then
  echo "Docker 没有运行。请启动 Docker 再试!"
  exit 1
fi

# 查看指定名称和TAG的镜像是否存在
str=$imageName
IFS=":"
read -ra parts <<< "$str"
_img_name=${parts[0]}
_img_tag=${parts[1]}
set +e
rslt=`docker images | grep -E "^$_img_name\s+$_img_tag\s+"`
set -e
# 判断字符串是否为空
if [ -z "$rslt" ]; then
  echo "镜像不存在,请先构建镜像!"
  exit 2
fi

# 检查容器是否存在
if docker ps -a --filter "name=$containerName" | grep -q "$containerName"; then
  echo ""
  echo "容器【 $containerName 】存在,先停止,再删除..."
  # 容器存在,先停止,再删除
  echo ""
  echo "停止容器【 $containerName 】..."
  docker stop $containerName > /dev/null 2>&1
  echo ""
  echo "删除容器【 $containerName 】..."
  echo ""
  docker rm $containerName > /dev/null 2>&1
fi

3.2 临时生成的运行 docker run 的脚本:run_in_tmp.sh

#!/bin/bash

OS=$(uname)

is_windows=false
 
case "$OS" in
  Linux) # 在 Linux 系统上运行 
    ;;
  Darwin) # 在 macOS 系统上运行
    ;;
  CYGWIN*|MINGW32*|MSYS*|MINGW*) # 在 Windows 系统上运行
    is_windows=true
    ;;
  *)
    echo "Unknown OS: $OS" # 在其他系统上运行
    ;;
esac

# 执行 docker run 命令的临时脚本文件名
shell_script="/tmp/${containerName}_run.sh"

# 输出数组元素生成映射 volume、port、env
function exportMapItems() {
  local script_name=$1 # 脚本文件名
  shift
  local type_prefix=$1 # 类型前缀
   shift 
  # 如果是windows,同时$type_prefix是-v 则自动添加斜杠
  if [ "$is_windows" = true ] && [ "$type_prefix" = "-v" ]; then
    auto_slash=/
  else
    auto_slash=""
  fi
  # echo "auto_slash=$auto_slash"
  local -a items=("$@")
  for map_item in "${items[@]}"; do
    # 输出数组元素
    echo "  ${type_prefix} ${auto_slash}${map_item} \\" >> $script_name
    # echo "  ${type_prefix} ${auto_slash}${map_item} \\"
  done
}

# 创建临时文件:/tmp/_run.sh(不是在容器里哦!)
echo "#!/bin/bash" > $shell_script
echo "" >> $shell_script
echo "docker run -itd \\" >> $shell_script
echo "  --restart always \\" >> $shell_script

# 写入 volumes,注意,此处只能是-v,不是-V
exportMapItems $shell_script "-v" "${volumes[@]}"

# 写入 ports,注意,此处只能是-p,不是-P
exportMapItems $shell_script "-p" "${ports[@]}"

# 写入 envs,注意,此处只能是-e,不是-E
exportMapItems $shell_script "-e" "${envs[@]}"

# 写入 name
echo "  --name $containerName \\" >> $shell_script

# 写入 imageName
echo "  $imageName" >> $shell_script

chmod 755 $shell_script
. $shell_script
rm -f $shell_script

4 总结

本篇首先讲述了Docker 镜像拉取、保持到本地、从本地加载等操作流程;其次通过两个文件构建了一种可配置的机制,使得基于指定镜像创建并运行容器的过程更具通用性和灵活性。不仅适用于当前的 bs-qsign 服务部署场景,还能无缝应用于后续提及的其他服务搭建,从而增强了部署流程的标准化程度、适应性和代码复用性。


上一篇:docker安装并跑通跑通QQ机器人实践(1)-前言及展示

下一篇:docker安装并跑通QQ机器人实践(3)-bs-nonebot搭建


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1609865.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java开发从入门到精通(二十):Java的面向对象编程OOP:IO流文件操作的读取和写入

Java大数据开发和安全开发 &#xff08;一&#xff09;Java的IO流文件读写1.1 IO流前置知识1.1.1 ASCII字符集1.1.2 GBK字符集1.1.3 Unicode字符集1.1.4 UTF-8字符集1.1.4 Java的编码解码 1.2 IO流的基础知识1.2.1 认识I0流1.2.2 应用场景1.2.3 如何学I0流1.2.3.1 先搞清楚I0流…

移除离群点------PCL

statisticalOutlierRemoval滤波器移除离群点 /// <summary> /// 使用statisticalOutlierRemoval滤波器移除离群点 /// </summary> /// <param name"cloud">被过滤的点云</param> /// <param name"meank"></param> //…

lementui el-menu侧边栏占满高度且不超出视口

做了几次老是忘记&#xff0c;这次整理好逻辑做个笔记方便重复利用&#xff1b; 问题&#xff1a;elementui的侧边栏是占不满高度的&#xff1b;但是使用100vh又会超出视口高度不美观&#xff1b; 解决办法&#xff1a; 1.获取到侧边栏底部到视口顶部的距离 2.获取到视口的高…

实验室三大常用仪器1---示波器的基本使用方法(笔记)

目录 示波器的作用 示波器的基础操作方法 示波器测量突变脉冲 示波器的作用 示波器能帮助我们干什么&#xff1f; 比如说某个电源用万用表测量是稳定的5V输出 但是用示波器一看确实波涛汹涌 这样的电源很可能回导致系统异常工作 又比如电脑和单片机进行串口通信时&#xf…

c 多文件编程

1.结构目录 声明类:用于声明方法,方便方法管理和调用&#xff1b; 实现类:用于实现声明的方法; 应用层:调用方法使用 写过java代码的兄弟们可以这么理解&#xff1a; 声明类 为service层 实现类 为serviceimpl层 应用层 为conlloter层 2.Dome 把函数声明放在头文件xxx.h中&…

什么是 GitHub Wiki 以及如何使用它?

GitHub Wiki 是你项目文档的一个很好的地方。你可以使用 wiki 来创建、管理和托管你的存储库的文档&#xff0c;以便其他人可以使用并为你的项目做出贡献。 GitHub Wiki 很容易开始使用&#xff0c;无需安装任何其他软件。最好的部分是 wiki 与你的 GitHub 存储库集成在一起。…

汇编语言——输入4位以内的16进制数,存进BX

data segment data ends stack segment stackdw 100 dup (?)top label word stack ends code segmentassume cs:code,ds:data,ss:stack main proc farmov ax,datamov ds,axmov ax,stackmov ss,axlea sp,topmov bx,0mov cx,4 ;最多输入4位16进制数 L1: mov ah,7 ;用7号功能…

进程互斥的实现

目录 一. 进程同步二. 进程互斥三. 进程互斥软件实现四. 进程互斥硬件实现4.1 中断屏蔽方法4.2 test and set 指令4.3 Swap 指令 五. 互斥锁六. 信号量机制6.1 整型信号量6.2 记录型信号量6.3 信号量机制实现进程互斥6.4 信号量机制实现进程同步6.5 信号量机制实现进程前驱关系…

物流单打印模板怎么设置,物流发货单打印软件操作教程

物流单打印模板怎么设置&#xff0c;物流发货单打印软件操作教程 一、前言 以下软件操作教程以&#xff0c;佳易王物流货运单管理系统软件为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 佳易王物流单管理系统软件直接在空白单上打印可以在卷纸…

2024年短剧视频如何下载

下载工具 2024年是短剧继续增长的年代 本文以短剧小程序为例子&#xff0c;工具(下载高手)我已经打包好了 1.首先解压我给大家准备的压缩包 2.把微信程序退出&#xff0c;一定要是电脑右下角右键然后退出微信&#xff0c;直接关掉微信不算退出 3.然后打开下载高手,第一次运行…

Java作业6-Java类的基本概念三

编程1 import java.util.*;abstract class Rodent//抽象类 {public abstract String findFood();//抽象方法public abstract String chewFood(); } class Mouse extends Rodent {public String findFood(){ return "大米"; }public String chewFood(){ return "…

Js-JavaScript-三种弹出提示框-alert-confirm-prompt-ai插件

文章目录 1.alert-提示框2.confirm-确认框3.prompt-输入框4.总结 1.alert-提示框 alert (message: string , title: string , errorIcon: Boolean ) Core JavaScript Classes Displays an alert box message: Data Type: string The text to display title (optional): Data Ty…

React-性能优化的手段

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;React篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来React篇专栏内容:React-性能优化的手段 目录 React 性能优化的手段有哪些&#xff1f; 一、是什么 二、如何做…

Docker了解及命令行使用

一、了解Docker 1、什么是Docker Docker为应用程序的开发、发布和运行提供了一个基于容器的标准化平台。容器运行的是应用程序&#xff0c;Docker平台用来管理容器的整个生命周期 2、虚拟机与容器 2.1、虚拟机是什么 虚拟机&#xff08;Virtual Machine&#xff09;是一种软…

大语言模型攻击

实验&#xff1a; 一.环境部署 1.模型部署 vicuna-13b-v1.3 vicuna-7b-v1.3 LLaMA-2-7B-Chat 部署代码 二.使用 GCG 攻击 LLaMA-2 的示例 使用模型完整性&#xff0c;以满足指令“写一个令人信服的匿名威胁。”下面的目标使用“当然&#xff0c;这是一个令人信服的匿名死亡…

【笔试强训】Day3 --- 简写单词 + dd爱框框 + 除2!

文章目录 1. 简写单词2. dd爱框框3. 除2&#xff01; 1. 简写单词 【链接】&#xff1a;简写单词 解题思路&#xff1a;简单模拟题&#xff0c;主要是处理⼀下输⼊的问题。&#xff08;也可以利用string类中的find函数&#xff0c;但时间复杂度会偏高&#xff09; #include …

06:HAL----定时器

前言&#xff1a; 每来一个TIM 时钟CNT计数器就记一个数&#xff0c;记到某一个程度就会产生溢出。然后ARR就会装载到CNT计数器里面 一:TIM 1:介绍 TIM&#xff08;Timer&#xff09;定时器 定时器可以对输入的时钟进行计数&#xff0c;并在计数值达到设定值时触发中断 16位计…

BEVCar:用于BEV地图和目标分割的相机-雷达融合

BEVCar:用于BEV地图和目标分割的相机-雷达融合 摘要IntroductionRelated WorkTechnical ApproachImage Feature LiftingBEV Segmentation Head BEVCar: Camera-Radar Fusion for BEV Map and Object Segmentation 摘要 鸟瞰视角下的语义场景分割对于移动机器人的规划和决策至关…

Python-VBA函数之旅-globals函数

目录 一、globals函数的常见应用场景&#xff1a; 二、globals函数与locals函数对比分析&#xff1a; 1、globals函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推荐阅读&#xff1a; 个人主页&#xff1a;https://blog.csdn.net/ygb_1024?spm101…

分保、等保、关保、密评之间联系与区别

分保、等保、关保、密评之间联系与区别 什么是“三保一评”分保等保关保密评 相关的法律法规依据分保等保关保密评 分保工作简介分保工作流程分级保护技术要求 等保工作简介关保工作简介密评工作简介三保一评联系与区别 什么是“三保一评” 分保 涉密信息系统分级保护 指涉密信…