Docker 加持的安卓手机:随身携带的知识库(一)

news2024/12/23 20:51:17

这篇文章聊聊,如何借助 Docker ,尝试将一台五年前的手机,构建成一个随身携带的、本地化的知识库。

写在前面

本篇文章,我使用了一台去年从二手平台购入的五年前的手机,K20 Pro。

用于实验的设备:K20 Pro

为了让它能够稳定持续的运行,我还为它准备了一个“加强版”的散热壳。

加强的“散热装备”

设想中的平时使用场景也非常简单,不需要插卡、不需要联网,一根 Type-C 数据线把它和电脑连在一起,就可以通过“本地连接”来访问手机中运行的提供服务的软件。

因为手机本身自带“UPS”(电池),所以即使突然断电,也不会出现数据的丢失,除此之外,因为手机已经是五年前的规格了,即使大手笔的购入顶配中的至尊版,成本也并不高,但是却可以比较轻松的获得一台 8核心、12GB 内存、500GB 的硬盘设备。甚至还有一块可以用来调试或者展示内容的“全面屏”,没有任何摄像头打孔的完整玻璃屏幕。

至于性能,如果能够完全配置正常,应该是非常有性价比,但是这应该需要一些折腾,所以本篇文章是第一篇,先验证可行性。

本文中的许多资料来自开源项目 CGCL-codes/Android-Container,感谢作者的辛苦劳动。不过项目距今为止已有三年没有更新,我个人推荐只做验证使用,一如本文中的使用方案。

为什么选择这台 K20 Pro

翻阅之前的文章,我发现我差不多每年都会折腾一下小米的手机。

  • 今年早些时候,聊过使用搭载 8Gen3 的红米 K70 Pro 跑模型《使用搭载骁龙 8 Gen 3 的安卓手机运行 AI 大模型》
  • 2023 年的时候,折腾过闲置的小米 12 Pro《小米 12 PRO 刷 MIUI 14 海外版(Android 12)》
  • 2022 年的时候,折腾过红米 11T Pro 《红米 11T PRO 刷机 MIUI 13 海外版》
  • 2021 年的时候,折腾过 K30 Pro《小米 K30 PRO 刷机 MIUI 12.5 海外版》
  • 2019 年的时候,折腾过 K20 Pro《小米 K20Pro 体验 Android 10》

因为种种原因,目前的小米开发者生态没有了过去的开放,开发者难以获取 Bootloader 权限,各种有趣的功能要排队内测,甚至 GitHub 上都出现了一些离谱的项目,比如 “小米高考题库”,来解决解锁刷机权限必须度过的大量八股测试题;“小米解锁项目”,“小米解锁方案合集” 等等项目。

**虽然,看起来现在的小米手机型号已经不再适合折腾。**但是,过去的手机,有没有可能变成一台比较有趣的设备,做一些比较有趣的事情呢?

毕竟,过去的小米手机还是很顶的!“守门员”、“焊门员”、“小金刚”这些产品形容词不光包含了营销成分,也有来自粉丝们的赞许。

准备工作

这次的准备工作非常简单,首先是“适合折腾的手机”,我选择的是 K20 Pro,你可以选择你喜欢的设备。

然后,是一台协助手机重获新生的“电脑”,Windows 或者 macOS 桌面系统的设备会比较方便,我使用的是 macOS。

最后,需要一根 Type-C 口的数据线,能够将手机连到电脑上。

第一步:解锁手机 Bootloader 权限

你可以参考上文中,我分享的之前的相关手机折腾记录,来将手机解锁,以便我们能够刷入 TWRP,并在后续过程中刷入验证 Docker 使用的新的安卓系统镜像。

如果你使用的设备也是 K20 Pro(Mi 9T Pro),可以从这里下载该设备的 TWRP 引导镜像。

更新设备的 BootLoader 非常简单,只需要电脑侧执行下面两条命令即可:

fastboot flash recovery twrp.img
fastboot reboot

第二步:按顺序刷入设备使用的系统镜像

在项目子目录文档的底部,我们能够找到用于验证的安卓镜像。

我们需要先刷入来自小米官方的 miui_RAPHAEL_V12.0.5.0.QFKCNXM_d03168fb55_10.0.zip 镜像,这个镜像发布自 2020 年 10 月 18 日,基于 Android 10 构建。如果项目页面下载比较慢,你可以从这里下载官方镜像。

在刷入官方镜像后,我们就可以刷入项目作者构建好的镜像 PixelExperience_raphael-10.0-20201204-0354-UNOFFICIAL-48bit-docker-criu.zip,来进行功能验证了。

在这个文档的上面,作者简单解释了如何进行镜像构建,而在另外一个目录中文档,则包含了另外一些比较重要的信息,包括如何给镜像内核做调整,来让 Docker 能够运行起来。

当我们完成镜像的更新后,就需要手动来完善运行环境,让 Docker 运行起来啦。

第三步:修复 Docker 运行环境

首先在一个命令行终端中执行:

adb shell

在进入一个交互式终端后,输入下面的命令,让我们能够修改系统中的只读目录:

mount -o rw,remount /

接着,我们将项目 Docker 目录和项目 files 目录的 files/dockerd.sh 使用 adb push 命令,传送到手机的 /system/bin/ 目录下,一个基本的 Docker 运行环境就就绪啦。

# adb push ./dockerd.sh /system/bin/dockerd.sh

./dockerd.sh: 1 file pushed, 0 skipped. 7.7 MB/s (4016 bytes in 0.000s)

...

为了我们操作 Docker 程序更方便,我们可以手动修复 docker-compose 命令,在 Compose 项目的发布页面,我们找到最新版本的 docker-compose-linux-aarch64 文件,下载,并使用上面的方式传送到手机环境中,并设置正确的执行权限。

# adb push ./docker-compose-linux-aarch64 /system/bin/docker-compose

./docker-compose-linux-aarch64: 1 file pushed, 0 skipped. 32.2 MB/s (61276577 bytes in 1.815s)

adb shell su -c "chmod +x /system/bin/docker-compose"

改进的 dockerd.sh

我对原始项目的 dockerd.sh 做了一些简单调整:

#!/system/bin/sh

mount -o rw,remount /

# 创建 Docker 相关的目录
root_dirs=("/var" "/run" "/tmp" "/opt" "/usr" "/system/etc/docker")
for dir in "${root_dirs[@]}"; do
    if [ ! -d "$dir" ]; then
        mkdir "$dir"
    fi
done


# 创建 /data 目录相关的目录
data_dirs=("/data/var:/var" "/data/run:/run" "/data/tmp:/tmp" "/data/opt:/opt" "/data/etc/docker:/etc/docker")
for dir in "${data_dirs[@]}"; do
    # 分割目录路径和挂载点
    paths=$(echo "$dir" | tr ':' ' ')
    data_dir=$(echo "$paths" | cut -d ' ' -f 1)
    mount_dir=$(echo "$paths" | cut -d ' ' -f 2)
    # 如果 /data/var 目录存在,清理目录中的 ./run 目录
    if [ "$data_dir" = "/data/var" ] && [ -d "$data_dir" ]; then
        rm -rf /data/var/run
    fi
    # 尝试创建并挂载目录
        mkdir -p "$data_dir"
        mount --bind "$data_dir" "$mount_dir"
        echo "mount $data_dir to $mount_dir"
done


# 创建 /dev 目录相关的目录,并挂载 cgroup
cgroup_dirs=("cpu" "cpuacct" "devices" "freezer" "hugetlb" "net_cls" "net_prio" "perf_event" "pids" "rdma")
for dir in "${cgroup_dirs[@]}"; do
    if [ ! -d "/dev/$dir" ]; then
        mkdir -p "/dev/$dir"
        case "$dir" in
            "cpu"|"cpuacct")
            ;;
        *)
            echo "mount -t cgroup -o $dir none /dev/$dir"
            mount -t cgroup -o $dir none /dev/$dir
            ;;
        esac
    fi
done


# 为 Docker 添加路由表
ip_rule1=$(ip rule | grep "from all lookup main" | wc -l)
if [ "$ip_rule1" -ne 1 ]; then
    ip rule add pref 1 from all lookup main
fi
ip_rule2=$(ip rule | grep "from all lookup default" | wc -l)
if [ "$ip_rule2" -ne 1 ]; then
    ip rule add pref 2 from all lookup default
fi


# 设置 Docker 镜像加速
echo "{\"registry-mirrors\":[\"https://mirror.baidubce.com\"],\"experimental\":true}" > /etc/docker/daemon.json
# 关闭默认防火墙,允许外部访问 Docker 容器端口
setenforce 0
# 启动 Docker
export DOCKER_RAMDISK=true
dockerd --add-runtime crun=/bin/crun -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock > /dev/null 2>&1 &

搭配注释,做了什么应该都非常清楚啦,这里就不展开赘述了。等到重新构建镜像的时候,我们再进行进一步的优化(内置 & 精简)。

第四步:启动 Docker 后台进程

当我们将所有文件都传输到手机上之后,在 adb shell 环境中把 docker 进行拉起来,Docker 运行环境就准备就绪啦。

# dockerd.sh                                                                                                                                                                       

mount /data/var to /var
mount /data/run to /run
mount /data/tmp to /tmp
mount /data/opt to /opt
mount /data/etc/docker to /etc/docker
mount -t cgroup -o devices none /dev/devices
mount -t cgroup -o freezer none /dev/freezer
mount -t cgroup -o hugetlb none /dev/hugetlb
mount -t cgroup -o net_cls none /dev/net_cls
mount -t cgroup -o net_prio none /dev/net_prio
mount -t cgroup -o perf_event none /dev/perf_event
mount -t cgroup -o pids none /dev/pids
mount -t cgroup -o rdma none /dev/rdma

这个时候,执行 docker info 就能够看到 docker 的基础运行环境状况啦:

# docker info

Client:
 Debug Mode: false

Server:
 Containers: 1
  Running: 1
  Paused: 0
  Stopped: 0
 Images: 7
 Server Version: 19.03.13
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Native Overlay Diff: false
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: runc crun
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 8fba4e9a7d01810a393d5d25a3621dc101981175
 runc version: dc9208a3303feef5b3839f4323d9beb36df0a9dd
 init version: fec3683
 Security Options:
  seccomp
   Profile: default
 Kernel Version: 4.14.180-F1xy-0.19-pe-ten/71771c10be
 OSType: linux
 Architecture: aarch64
 CPUs: 8
 Total Memory: 11.25GiB
 Name: localhost
 ID: LLQY:OOXR:BKTQ:M2ZP:MGUJ:Q3NY:RPZL:EV7D:YGQY:H45D:BKUY:RXMA
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: true
 Insecure Registries:
  127.0.0.0/8
 Registry Mirrors:
  https://mirror.baidubce.com/
 Live Restore Enabled: false
 Product License: Community Engine

WARNING: API is accessible on http://0.0.0.0:2375 without encryption.
         Access to the remote API is equivalent to root access on the host. Refer
         to the 'Docker daemon attack surface' section in the documentation for
         more information: https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface

第五步:创建一个 Docker 应用

Docker 环境就绪后,我们来测试 Docker 应用能否运行。先创建一个目录,用于后续存放 Docker 应用数据:

mkdir -p kb
cd kb

随后,在目录中创建一个内容如下的 docker-compose.yml 配置文件:

version: '3'

services:

  wordpress:
    image: soulteary/sqlite-wordpress:6.5.2
    restart: always
    ports:
      - 8080:80
    volumes:
      - ./wordpress:/var/www/html

没错,这个配置来自项目 soulteary/docker-sqlite-wordpress,在之前的文章《WordPress 告别 MySQL:Docker SQLite WordPress》、《WordPress SQLite Docker 镜像封装细节》中,讲的比较详尽了,就不在此展开啦。

当我们准备好 docker-compose.yml 后,执行 docker-compose up -d

# docker-compose up -d
WARN[0000] /kb/docker-compose.yml: `version` is obsolete 
[+] Running 1/0
 ✔ Container kb-wordpress-1  Running 

WordPress 就很快的通过容器的方式启动起来啦。

启动应用后,我们使用下面的命令,可以简单验证服务是否正常运行:

docker exec kb-wordpress-1 curl -L http://0.0.0.0:80

不出意外,我们将得到类似下面的结果:

使用命令行验证手机上的 Docker 应用

上面的图片中,我们使用命令行来验证了 WordPress 中的程序渲染出了 HTML 页面,虽然执行时间非常长(需要排查或重新构建 Android 验证),但是证明了 Android 上运行 Docker 程序是可行的。

第六步:如何在电脑侧访问手机的应用

Android Debug Bridge(ADB)中有一个很有用的命令叫做 forward,我们可以通过这个命令,将电脑上的端口和手机上应用的端口进行打通。

 forward --list           list all forward socket connections

 forward [--no-rebind] LOCAL REMOTE
     forward socket connection using:
       tcp:<port> (<local> may be "tcp:0" to pick any open port)
       localabstract:<unix domain socket name>
       localreserved:<unix domain socket name>
       localfilesystem:<unix domain socket name>
       dev:<character device name>
       jdwp:<process pid> (remote only)
       vsock:<CID>:<port> (remote only)
       acceptfd:<fd> (listen only)

 forward --remove LOCAL   remove specific forward socket connection

 forward --remove-all     remove all forward socket connections

命令支持四种参数调用方法,分别是:

  • 以列表形式获取所有的转发映射
  • 进行本地和远程端口的转发映射
  • 撤销一个本地端口的转发映射
  • 撤销所有的转发映射

我们以实际的情况举例,上文中,我们在手机上将 WordPress 默认运行的 80 端口,映射到了手机的 8080 端口。如果我们将电脑的 8088 端口和手机上的 8080 端口打通,那么我们需要执行下面的命令:

adb forward tcp:8088 tcp:8080

当命令执行完毕后,我们就可以在浏览器中访问 http://localhost:8088 来访问手机上的应用啦。

使用电脑直接访问手机容器应用

当然,这里也会遇到和上面一样的问题,访问应用的时间会比较长。这是一个需要继续排查和解决的问题。毕竟除了 PHP 程序执行外的资源路径的响应都在 ms 级别。

当然,如果你希望这台设备上运行的 Docker 程序,能够在局域网共享,只需要让手机连上 Wi-Fi,然后在浏览器中访问手机在局域网中的 IP 地址,和对应的程序端口即可。

使用局域网访问手机上的容器应用

是不是十分简单,如果你想离线本地化使用,就不需要给手机网络,如果你想局域网共享,得到一台低成本、高性价比的 Linux 服务器,就让它连上 Wi-Fi。

最后

写到这里,本文提到的验证目标就结束啦。接下来相关的文章里,我们来聊聊本文遇到的性能问题,以及如何在 2024 年更简单的构建支持 Docker 运行的安卓内核和镜像。

我们下篇文章再见。

–EOF


我们有一个小小的折腾群,里面聚集了一些喜欢折腾、彼此坦诚相待的小伙伴。

我们在里面会一起聊聊软硬件、HomeLab、编程上、生活里以及职场中的一些问题,偶尔也在群里不定期的分享一些技术资料。

关于交友的标准,请参考下面的文章:

苏洋:致新朋友:为生活投票,不断寻找更好的朋友

当然,通过下面这篇文章添加好友时,请备注实名和公司或学校、注明来源和目的,珍惜彼此的时间 😄

苏洋:关于折腾群入群的那些事


本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 署名 4.0 国际 (CC BY 4.0)

本文作者: 苏洋

创建时间: 2024年05月03日
统计字数: 9721字
阅读时间: 20分钟阅读
本文链接: https://soulteary.com/2024/05/03/docker-powered-android-phone-knowledge-base-you-can-carry-with-you-1.html

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

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

相关文章

如何让 PDF 书签从杂乱无序整洁到明丽清新

1、拉取书签&#xff08;详细步骤看文末扩展阅读&#xff09; 原状态 —— 杂乱无序 自动整理后的状态 —— 错落有致&#xff0c;但摩肩接踵 2、开始整理 全选自动整理后的书签&#xff0c;剪切 访问中英混排排版优化 - 油条工具箱 https://utils.fun/cn-en 1 粘贴 → 2 …

SwiftUI 5.0(iOS 17.0,macOS 14.0+)新 Inspector 辅助视图之趣味漫谈

概览 在 SwiftUI 开发中,苹果为我们提供了多种辅助视图用来显示额外信息从而极大丰富了应用的表现力,比如:Alert、Sheet、ContextMenu 等等。 从 SwiftUI 5.0(iOS 17+)开始, 又增加了一种全新的辅助视图:Inspector。 在本篇博文中,您将学到如下内容: 概览1. Inspe…

自定义拦截器jwt登录校验接口模拟账号登录

五一闲在宿舍&#xff0c;本来想写一个自己的简易博客网站&#xff0c;发现vue基础太差&#xff0c;做不出来页面效果于是便放弃&#xff0c;但也没有完全放弃。于是我分析了一下简易博客的后端实现流程&#xff0c;除了最基本的crud以外&#xff0c;在自己目前的对接口的分析中…

MATLAB 微积分

MATLAB 微积分 MATLAB提供了多种方法来解决微分和积分问题&#xff0c;求解任意程度的微分方程式以及计算极限。最重要的是&#xff0c;您可以轻松求解复杂函数的图&#xff0c;并通过求解原始函数及其导数来检查图上的最大值&#xff0c;最小值和其他文具点。 本章将讨论微…

Linux专栏08:Linux基本指令之压缩解压缩指令

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Linux专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Linux基本指令之压缩解压缩指令 编号&#xff1a;08 文章目录 Linu…

在2-3-4树上实现连接与分裂操作的算法与实现

在2-3-4树上实现连接与分裂操作的算法与实现 引言1. 维护2-3-4树结点的高度属性伪代码示例 2. 实现连接操作伪代码示例 3. 证明简单路径p的划分性质4. 实现分裂操作伪代码示例 C代码示例结论 引言 2-3-4树是一种平衡搜索树&#xff0c;它保证了树的高度被有效控制&#xff0c;…

python实验一 简单的递归应用

实验一 实验题目 1、兔子繁殖问题(Fibonacci’s Rabbits)。一对兔子从出生后第三个月开始&#xff0c;每月生一对小兔子。小兔子到第三个月又开始生下一代小兔子。假若兔子只生不死&#xff0c;一月份抱来一对刚出生的小兔子&#xff0c;问一年中每个月各有多少只兔子。 &…

uniapp 应用闪退、崩溃异常日志捕获插件(可对接网络上报)插件 Ba-Crash

应用闪退、崩溃异常日志捕获插件&#xff08;可对接网络上报&#xff09; Ba-Crash 简介&#xff08;下载地址&#xff09; Ba-Crash 是一款uniapp应用闪退、崩溃异常日志捕获插件&#xff0c;支持对接网络上报、设置提示等等&#xff0c;方便对一些远程问题、原生问题进行分…

【云原生】Docker 实践(五):搭建私有镜像 Harbor

【Docker 实践】系列共包含以下几篇文章&#xff1a; Docker 实践&#xff08;一&#xff09;&#xff1a;在 Docker 中部署第一个应用Docker 实践&#xff08;二&#xff09;&#xff1a;什么是 Docker 的镜像Docker 实践&#xff08;三&#xff09;&#xff1a;使用 Dockerf…

基于node.js+css+html+mysql博客系统

博主介绍&#xff1a; 大家好&#xff0c;本人精通Java、Python、Php、C#、C、C编程语言&#xff0c;同时也熟练掌握微信小程序、Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我有丰富的成品Java、Python、C#毕设项目经验&#xff0c;能够为学生提供各类…

C#描述-计算机视觉OpenCV(4):图像分割

C#描述-计算机视觉OpenCV&#xff08;4&#xff09;&#xff1a;图像分割 前言用 GrabCut 算法分割图像实例展示 前言 本文中如果有什么没说明的地方&#xff0c;大概率在前文中描述过了。 C#描述-计算机视觉OpenCV&#xff08;1&#xff09;&#xff1a;基础操作 C#描述-计算…

第十五届蓝桥杯省赛大学B组(c++)

很幸运拿了辽宁赛区的省一,进入6月1号的国赛啦... 这篇文章主要对第十五届省赛大学B组(C)进行一次完整的复盘,这次省赛2道填空题6道编程题: A.握手问题 把握手情景看成矩阵: 粉色部分是7个不能互相捂手的情况 由于每个人只能和其他人捂手, 所以黑色情况是不算的 1和2握手2和…

快速掌握Element-Ul,构建高效网页应用【AI写作】

首先&#xff0c;这篇文章是基于笔尖AI写作进行文章创作的&#xff0c;喜欢的宝子&#xff0c;也可以去体验下&#xff0c;解放双手&#xff0c;上班直接摸鱼~ 按照惯例&#xff0c;先介绍下这款笔尖AI写作&#xff0c;宝子也可以直接下滑跳过看正文~ 笔尖Ai写作&#xff1a;…

JavaScript继承的方法和优缺点

原型链继承 让一个构造函数的原型是另一个类型的实例&#xff0c;那么这个构造函数new出来的实例就具有该实例的属性。 优点&#xff1a; 写法方便简洁&#xff0c;容易理解。 缺点&#xff1a; 在父类型构造函数中定义的引用类型值的实例属性&#xff0c;会在子类型原型上…

逻辑回归实战 -- 是否通过考试

http://链接: https://pan.baidu.com/s/1-uy-69rkc4WjMpPj6iRDDw 提取码: e69y 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 数据集下载链接 这是个二分类问题&#xff0c;通过x1,x2两个指标得出是否通过考试的结论。 逻辑回归的激活函数是sigmoid函数&…

STM32单片机实战开发笔记-EXIT外部中断检测

嵌入式单片机开发实战例程合集&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/11av8rV45dtHO0EHf8e_Q0Q?pwd28ab 提取码&#xff1a;28ab EXIT模块测试 功能描述 外部中断/事件控制器由19个产生事件/中断要求的边沿检测器组成。每个输入线可以独立地配置输入类型&a…

P9422 [蓝桥杯 2023 国 B] 合并数列

P9422 [蓝桥杯 2023 国 B] 合并数列 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 用队列即可 当两个队列队首&#xff1a;a b &#xff0c;弹出 当a < b&#xff0c;把a加给其后一个元素&#xff0c;弹出a 当b < a&#xff0c;把b加给其后一个元素&#xff0c;弹出…

Eclipse 开创性地集成 Neon Stack,将 EVM 兼容性带到 SVM 网络

2024年5月2日&#xff0c;全球——在塑造区块链网络的战略联盟的过程中&#xff0c;Eclipse 通过集成 Neon EVM 核心团队开发的技术堆栈 Neon Stack&#xff0c;成为首个打破 EVM-SVM 兼容性障碍的生态。 Eclipse 旨在通过结合以太坊和 Solana 的最佳特性&#xff0c;来重构区…

2024年钉钉群直播回放如何永久保存

工具我已经打包好了&#xff0c;有需要的自己取一下 链接&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;1234 --来自百度网盘超级会员V10的分享 1.首先解压好我给大家准备好的压缩包 2.再把逍遥一仙下载器压缩包也解压一下 3.打开逍遥一仙下载器文件夹里面的M3U8…

华为云耀云服务器开放端口

博客主页&#xff1a;花果山~程序猿-CSDN博客 关注我一起学习&#xff0c;一起进步&#xff0c;一起探索编程的无限可能吧&#xff01;让我们一起努力&#xff0c;一起成长&#xff01; 目录 一.华为云控制台开放端口 寻找到安全组信息 2. 添加开放的端口信息 3. 检查是否成…