有些用户对 Fox-Edge 存在 k3s 的容器化部署需求,所以灵狐提供了 docker 部署的参考教程。
该文档是面向k3s的docker运营人员的高阶文档,每一个项目的docker镜像具有甲方项目的针对性。
docker运营人员需要根据自己的甲方市场项目,需要做一些必要的服务裁剪。
Fox-Edge通常被用户当作被部署在边缘端的软件系统,主要的硬件安装环境是 物理设备 ,比如 arm/x86 这类小型嵌入式设备、软路由、工控机。
此时,设备环境对Fox-Edge来说,是一个在可读/可写上有 充分权限 的用户环境。
Fox-Edge同样也支持被用户安装在性能较强的中型设备上,比如x86的工控机、小型服务器上。此时,工控机、服务器的资源比较丰富, 用户会采用k3s的 docker 方案,将硬件环境划分为多个 用户名空间 ,按docker的方式进行各子系统的管理,Fox-Edge只是众多子系统之一。
此时,doccer容器环境对Fox-Edge来说,是在可读/可写上,比较受限 的用户环境。
如果对此不理解的话,可以理解为类似某款软件,它的硬盘版和光盘版之间的区别。
用户环境的受限与不受限,是真机部署和docker部署之间,最主要的差异。在k3s下为Fox-Edge子系统制作镜像的时候,请时刻注意这点。
k3s也是面向小型化设备的一种精简版容器管理方案。有些用户用它来作为设备的集中管理平台。
由于小型化设备的资源有限,此时会倾向于使用docker作为管理节点。
每个小型化设备,只是一个硬件平台,而k3s是作为一个docker管理系统。
每个java进程和mysql/redis/nginx基础服务进程,都各自部署在一个docker容器之中, 并且上述对应的docker容器,在整个小型化设备都只有一个运行实例。
注意:该方案不是传统服务端Docker的1个JAVA应用1个Docker镜像,每个Docker镜像启动N个Docker容器实例,每个Docker容器只内含1个JAVA进程的并行部署方案。
这是针对小型设备Docker部署实例,它是一批JAVA应用一个Docker镜像,该Docker镜像所启动每一个Docker实例都是作为一个"独立主机",该"独立主机"的Docker容器 中含N个JAVA进程的单机部署方案。
Fox-Edge原来是直接部署在物理设备之中,并自带应用的远程部署、升级、卸载、配置的管理方案,这是灵狐所推荐的技术方案。
k3s的docker方案,也是远程部署、升级、卸载、配置的管理方案。
这意味着,是不能采用Fox-Edge自带的部署、升级、卸载、配置的部件部件管理方案,即不能使用通过Fox-Edge的仓库界面进行安装的方案。
所以,k3s的docker方案的高阶技术方案如下:
1、先在一台物理样机之中,安装部署一套Fox-Edge系统,并根据甲方项目的需要,并在其中安装所需要的各种服务、解码器、模板。
2、从部署完Fox-Edge的样机之中,剥离出/opt/fox-edge的完整目录
3、针对后台和前台,分别制作一个Dockerfile.fox-edge-server和Dockerfile.fox-edge-ui文件
4、为需要访问外部设备,制作提供数据卷,让它能够加载到宿主机上的/dev 和 /tmp 目录
5、通过上述素材,制作出面向某甲方物联网项目的匹配的前端、后端docker镜像
6、在k3s之中应用这些docker镜像,在每个小型设备之中,启动一套Fox-Edge进程相关的docker容器实例
现在找一台物理样机,或者用虚拟机建立一个样机环境,然后在其中安装一套 Fox-Edge.
具体安装过程,可以参考前文的Fox-Edge x86部署篇
以Ubuntu 22.0版本作为范例,通过下面的命令,进行Docker的一键式安装
apt-get update -y && \
apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common -y && \
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - && \
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" && \
apt-get install docker-ce docker-ce-cli containerd.io -y
docker的安装结果如下:
以下为制作Fox-Edge的后端Dockerfile.fox-edge-server和前端Dockerfile.fox-edge-ui为范例。
在Fox-Edge的样机环境中,创建一个工程目录/opt/fox-docker,并将/opt/fox-edge系统目录复制到其下。
参考命令行如下:
#准备工作
mkdir -p /opt/fox-docker/opt
cp -r /opt/fox-edge /opt/fox-docker/opt
cd /opt/fox-docker
相关目录如下:
制作后端的docker
新建一个Dockerfile.fox-edge-server文件,内容如下
#指定基础镜像为openjdk 11环境
#注意:该版本提供了jmap,而fox-edge会通过jmap的智能gc能力,进行内存老化周期的释放,来达到多服务下的内存管理能力,
#传统的-Xms配置,是面向服务器领域开发的单服务的配置,它并不适用于fox-edge所在精简设备下,特别是多服务场景的内存管理。
FROM openjdk:11
#维护者信息
MAINTAINER fox-edge
#工作路径
WORKDIR /opt/fox-edge
#用于指定持久化目录,方便各容器共享该目录
#引用到宿主机的数据卷/dev
#注意,docker容器启动时,要带上--privileged 和 -v /dev:/dev 两个参数,否则容器中会出现无权限和空的错误
VOLUME ["/dev","/tmp"]
#在容器中,提取安装好需要用到的LINUX命令,如下:
#更新安装源
RUN apt-get update -y
#安装TOP命令:这是查询CPU占用率的命令包
RUN apt-get install procps -y
#安装dmidecode命令:这是查询CPUID的命令包
RUN apt-get install dmidecode -y
#在容器中预先创建 /jar /template /shell /conf目录
RUN mkdir -p /opt/fox-edge/jar
RUN mkdir -p /opt/fox-edge/template
RUN mkdir -p /opt/fox-edge/shell
RUN mkdir -p /opt/fox-edge/conf
#将本地文件复制到容器中
COPY /opt/fox-edge/jar /opt/fox-edge/jar
COPY /opt/fox-edge/template /opt/fox-edge/template
COPY /opt/fox-edge/shell /opt/fox-edge/shell
COPY /opt/fox-edge/conf /opt/fox-edge/conf
#在容器中预先创建bin目录
RUN mkdir -p /opt/fox-edge/bin/kernel/gateway-service/
RUN mkdir -p /opt/fox-edge/bin/kernel/manager-service/
RUN mkdir -p /opt/fox-edge/bin/system/device-service/
RUN mkdir -p /opt/fox-edge/bin/system/persist-service/
RUN mkdir -p /opt/fox-edge/bin/system/controller-service/
RUN mkdir -p /opt/fox-edge/bin/service/channel-simulator-service/
RUN mkdir -p /opt/fox-edge/bin/service/channel-serialport-service/
RUN mkdir -p /opt/fox-edge/bin/service/channel-tcp-server/
#将本地bin文件复制到容器中
COPY /opt/fox-edge/bin/kernel/gateway-service/fox-edge-server-manager-gateway.jar /opt/fox-edge/bin/kernel/gateway-service/fox-edge-server-manager-gateway.jar
COPY /opt/fox-edge/bin/kernel/manager-service/fox-edge-server-manager-system.jar /opt/fox-edge/bin/kernel/manager-service/fox-edge-server-manager-system.jar
COPY /opt/fox-edge/bin/system/device-service/fox-edge-server-device-service.jar /opt/fox-edge/bin/system/device-service/fox-edge-server-device-service.jar
COPY /opt/fox-edge/bin/system/persist-service/fox-edge-server-persist-service.jar /opt/fox-edge/bin/system/persist-service/fox-edge-server-persist-service.jar
COPY /opt/fox-edge/bin/system/controller-service/fox-edge-server-controller-service.jar /opt/fox-edge/bin/system/controller-service/fox-edge-server-controller-service.jar
COPY /opt/fox-edge/bin/service/channel-simulator-service/fox-edge-server-channel-simulator-service.jar /opt/fox-edge/bin/service/channel-simulator-service/fox-edge-server-channel-simulator-service.jar
COPY /opt/fox-edge/bin/service/channel-serialport-service/fox-edge-server-channel-serialport-service.jar /opt/fox-edge/bin/service/channel-serialport-service/fox-edge-server-channel-serialport-service.jar
COPY /opt/fox-edge/bin/service/channel-tcp-server/fox-edge-server-channel-tcp-server.jar /opt/fox-edge/bin/service/channel-tcp-server/fox-edge-server-channel-tcp-server.jar
#映射端口
#9000 gateway-service的服务端口:必须配置的端口
#9101 manager-service的服务端口:必须配置的端口
#9301 9302 channel-tcp-server配置中提供的两个服务端口:可选端口,这只是一个其他服务端口的使用范例
#注意,docker容器启动时,要带上 -p 9000:9000 -p 9101:9101 参数,否则没有完成内外端口的映射
EXPOSE 9000 9101 9301 9302
#配置容器,使其可执行化,相当于在环境中执行命令java -jar xxx.jar --输入参数
#配置容器,使其可执行化,相当于在环境中执行命令java -jar xxx.jar --输入参数
#以下内容的生成方式:
#1、在样机中启动Fox-Edge后,执行linux命令行 ps -aux|grep fox-edge,获得样机中的各服务启动命令行内容
#2、从返回的一批内容之中,每行只保留java xxx xxx的部分
#3、将localhost全体替换为docker的网关IP 172.17.0.1
#4、将每一行的--env_type=device参数,替换为--env_type=docker
#5、在每一行的末尾处,添加 & \ 作为全体xxx.jar启动的命令拼接
#6、最后得到如下内容,作为批量Docker容器中的批量启动命令
CMD \
java --add-opens java.base/java.net=ALL-UNNAMED -jar /opt/fox-edge/bin/kernel/gateway-service/fox-edge-server-manager-gateway.jar --app_type=kernel --app_name=gateway-service --env_type=docker -Dspring.profiles.active=prod --server.port=9000 --spring.redis.host=172.17.0.1 --spring.redis.port=6379 --spring.redis.password=12345678 --spring.datasource.username=fox-edge --spring.datasource.password=12345678 --spring.datasource.url=jdbc:mysql://172.17.0.1:3306/fox_edge & \
java --add-opens java.base/java.net=ALL-UNNAMED -jar /opt/fox-edge/bin/kernel/manager-service/fox-edge-server-manager-system.jar --app_type=kernel --app_name=manager-service --env_type=docker -Dspring.profiles.active=prod --server.port=9101 --spring.redis.host=172.17.0.1 --spring.redis.port=6379 --spring.redis.password=12345678 --spring.datasource.username=fox-edge --spring.datasource.password=12345678 --spring.datasource.url=jdbc:mysql://172.17.0.1:3306/fox_edge & \
java --add-opens java.base/java.net=ALL-UNNAMED -jar /opt/fox-edge/bin/system/controller-service/fox-edge-server-controller-service.jar --app_type=system --app_name=controller-service --env_type=docker -Dspring.profiles.active=prod --server.port=9021 --spring.redis.host=172.17.0.1 --spring.redis.port=6379 --spring.redis.password=12345678 --spring.datasource.username=fox-edge --spring.datasource.password=12345678 --spring.datasource.url=jdbc:mysql://172.17.0.1:3306/fox_edge & \
java --add-opens java.base/java.net=ALL-UNNAMED -jar /opt/fox-edge/bin/system/device-service/fox-edge-server-device-service.jar --app_type=system --app_name=device-service --env_type=docker -Dspring.profiles.active=prod --server.port=9024 --spring.redis.host=172.17.0.1 --spring.redis.port=6379 --spring.redis.password=12345678 --spring.datasource.username=fox-edge --spring.datasource.password=12345678 --spring.datasource.url=jdbc:mysql://172.17.0.1:3306/fox_edge & \
java --add-opens java.base/java.net=ALL-UNNAMED -jar /opt/fox-edge/bin/system/persist-service/fox-edge-server-persist-service.jar --app_type=system --app_name=persist-service --env_type=docker -Dspring.profiles.active=prod --server.port=9015 --spring.redis.host=172.17.0.1 --spring.redis.port=6379 --spring.redis.password=12345678 --spring.datasource.username=fox-edge --spring.datasource.password=12345678 --spring.datasource.url=jdbc:mysql://172.17.0.1:3306/fox_edge & \
java --add-opens java.base/java.net=ALL-UNNAMED -jar /opt/fox-edge/bin/service/channel-tcp-server/fox-edge-server-channel-tcp-server.jar --app_type=service --app_name=channel-tcp-server --env_type=docker -Dspring.profiles.active=prod --server.port=9008 --spring.redis.host=172.17.0.1 --spring.redis.port=6379 --spring.redis.password=12345678 --spring.datasource.username=fox-edge --spring.datasource.password=12345678 --spring.datasource.url=jdbc:mysql://172.17.0.1:3306/fox_edge & \
java --add-opens java.base/java.net=ALL-UNNAMED -jar /opt/fox-edge/bin/service/channel-serialport-service/fox-edge-server-channel-serialport-service.jar --app_type=service --app_name=channel-serialport-service --env_type=docker -Dspring.profiles.active=prod --server.port=9014 --spring.redis.host=172.17.0.1 --spring.redis.port=6379 --spring.redis.password=12345678 --spring.datasource.username=fox-edge --spring.datasource.password=12345678 --spring.datasource.url=jdbc:mysql://172.17.0.1:3306/fox_edge & \
java --add-opens java.base/java.net=ALL-UNNAMED -jar /opt/fox-edge/bin/service/channel-simulator-service/fox-edge-server-channel-simulator-service.jar --app_type=service --app_name=channel-simulator-service --env_type=docker -Dspring.profiles.active=prod --server.port=9001 --spring.redis.host=172.17.0.1 --spring.redis.port=6379 --spring.redis.password=12345678 --spring.datasource.username=fox-edge --spring.datasource.password=12345678 --spring.datasource.url=jdbc:mysql://172.17.0.1:3306/fox_edge
这是样机下Linux环境,查询命令行信息的 ps -aux|grep fox-edge 命令

将查询的内容复制出来,然后进行相应修改,变成dockerfile中的内容

2.2、说明
1、为什么要批量执行一批java的服务?
实际上一个甲方物联网企业项目,用户对频繁升级是比较反感的,将后台各服务xxx.jar统一打包成一个docker
镜像,并在一个容器运行,减少现场项目的实施成本。并且,各服务之间,彼此是存在关联性的。为每一个服务
单独打包成一个docker,除了增加复杂性,并没有明显的收益。
2、为什么要新建一个相邻的/opt/fox-docker目录,并将/opt/fox-edge复制到/opt/fox-docker/opt/fox-edge之中?
docker容器的打包,它的根目录实际上是以/opt/fox-docker为当前“根目录”的,此时复制一份/opt/fox-edge到它下
面,dockerfile才能找到该这些文件
3、为什么docker版本启动后,不再支持fox-edge的部件安装和升级了
因为k3s的容器管理,实际上是linux的进程管理,fox-edge也有自己的进程管理,双方是彼此冲突的二选一方案,要
把fox-edge对本地进程的启停操作全部禁止掉。否则,对容器中的子进程进行任何的启动、停止、修改操作,都将导致容器从运行中退出。
Linux下的Docker,本质上只是一组进程空间的用户隔离,它只是一个容器的like,并不能像虚拟机一样进行真正的物理隔离。
2.3、dockerfile的使用
#生成后端fox-edge-server的docker镜像,并启动该容器
docker build -f Dockerfile.fox-edge-server -t fox-edge-server .
#使用该镜像,启动该容器,注意为容器传递宿主机的端口映射参数,权限,以及数据卷
docker run --privileged -p 9000:9000 -p 9101:9101 -p 9301:9301 -p 9302:9302 -v /dev:/dev -v /tmp:/opt/fox-edge/logs -d fox-edge-server
#检查容器启动状态
docker ps
#进入容器中查看
docker exec -it 容器ID /bin/bash
打包镜像
启动容器
制作前端的docker
新建一个Dockerfile.fox-edge-server文件,内容如下
#指定基础镜像为nginx
FROM nginx:alpine
#维护者信息
MAINTAINER fox-edge
#在容器中预先创建 /opt/fox-edge 目录
RUN mkdir -p /opt/fox-edge
#将本地文件复制到容器中
COPY /opt/fox-edge/dist /opt/fox-edge/dist
COPY /opt/fox-edge/doc/nginx/conf.d/fox-edge.com.ipadr.conf /etc/nginx/conf.d
#将主机版本的nginx文件中的127.0.0.1,修改为容器版本下的172.17.0.1
RUN sed -i s/127.0.0.1/172.17.0.1/g /etc/nginx/conf.d/fox-edge.com.ipadr.conf
#映射端口
EXPOSE 80
#配置容器,使其可执行化,相当于在环境中执行命令java -jar xxx.jar --输入参数
CMD ["nginx", "-g", "daemon off;"]
3.2、dockerfile的使用
#生成前端fox-edge-ui的docker镜像,并启动该容器
docker build -f Dockerfile.fox-edge-ui -t fox-edge-ui .
#启动前端镜像
docker run -p 80:80 -d fox-edge-ui
#检查容器启动状态
docker ps
#进入容器中查看,注意,该容器不支持/bin/bash,只支持/bin/sh
docker exec -it 容器ID /bin/sh
这是docker版的fox-edge
它没有仓库菜单,并且进程界面的启动、停止、重启操作也被禁用了。
它的后续升级,是通过不断的制作新版本的docker镜像来完成的。