原文作者:行云创新产品总监 John
概述
今天我们接着上一期的文章《玩转云原生 Terminal 之 TTY 的前世今生》,继续来聊一聊云原生 Terminal。为了在 TitanIDE 上玩转云原生 Terminal ,首先找到了 WeTTY,在这个过程中,花费了不少时间,虽然生命在于折腾,但折腾 WeTTY 的代价有点过大了。只能说 ,WeTTY,想说爱你不容易……
具体什么情况呢?请继续往下看。
WeTTY 是什么?
WeTTY = Web + TTY
Terminal over HTTP and https. WeTTY is an alternative to ajaxterm and anyterm but much better than them because WeTTY uses xterm.js which is a full fledged implementation of terminal emulation written entirely in JavaScript. WeTTY uses websockets rather than Ajax and hence better response time.
WeTTY 终端通过 HTTP 和 https 在浏览器访问。WeTTY是 ajaxterm 和 anyterm 的替代品,但比它们好得多,因为WeTTY 采用 xterm.js 来实现的,这是一个完全用 JavaScript 编写的完整的终端模拟器。WeTTY 使用 websockets 而不是 Ajax,因此响应时间更好。
TitanIDE 是什么?
本文所有涉及的所有操作都是在 TitanIDE 完成的,如果您还未了解过 TitanIDE,请点击这里(www.titanide.cn)了解详情,简单来说,TitanIDE 是一款云原生集成开发环境,特点是“安全、高效、体验”,最少只需一台虚拟机,十分钟即可安装好,即可开启您的全云端开发之旅!
体验TitanIDE>>(www.titanide.cn)
撸起袖子开干
要在 TitanIDE 运行一个全新的 WeTTY, 首先需要构建一个模板镜像,然后通过模板镜像创建模板,再通过模板创建项目。当然以上是一次性操作,以后就可以直接通过创建好的模板创建项目即可。
构建模板镜像
创建 TemplateMaker 项目
在 TitanIDE 上构建模板镜像,需要通过 TemplateMaker 模板来创建一个项目 template-wetty。
如果您不知道如何操作,README.md 有中英文详细说明,跟着操作就行了。
创建好的项目 template-wetty 包含以下文件。
.
├── Dockerfile # 镜像的 Dockerfile,根据用户需要修改
├── icon.png # 图标文件,如上图所示,每个模板都有一个图标,用户可以通过右侧栏文件管理工具上传
├── Makefile # Makefile,通过 make 命令直接构建镜像
├── README_CN.md # 中文说明文档
└── README.md # 英文说明文档
上传模板图标
在文件管理工具栏点击 template-wetty 进入项目文件夹内。
将准备好的图标文件 icon.png 拖拽到文件上传区域:
编辑 Dockerfile
在编辑 Dockerfile 之前,我们先准备一下 WeTTY 的启动脚本,并将保存为 ./bin/app。
#!/bin/bash
# 指定访问 WeTTY 的路径,这是 TitanIDE 访问服务所需要的设置,通过约定这个规则可以简化域名,所有的服务共享一个域名
BASE="/ide/${POD_NAMESPACE}/${PROJECT_NAME}/"
# WeTTY 的启动命令,指定两个入参,--port 为 WeTTY 的服务监听端口,--base 指定访问 WeTTY 的路径
node /usr/src/app --port ${WETTY_PORT} --base ${BASE}
接下来修改 Dockerfile,为了更好的说明,我将在 Dockefile 内部逐行备注里面的含义
# 我们之间基于官方提供的镜像进行定制,详情请查看:https://hub.docker.com/r/wettyoss/wetty
FROM wettyoss/wetty:2.5.0
# NODE_ENV=production 指定运行的 Profile 为 production
# COMMAND='/bin/bash' 告诉 WeTTY 启动后运行的命令,我们直接进入 Bash
ENV NODE_ENV=production \
WETTY_PORT=3000 \
COMMAND='/bin/bash'
# TitanIDE 的模板图标通过 icon 入参来指定,
ARG icon
# 镜像名字,默认取当前项目名称,如果用户没有修改的情况下,以本文创建的项目名称为例是 template-wetty,最终生成的镜像是 registry/ns/template-wetty:tag,例如
# 当然也可在构建镜像的时候由入参来覆盖,如 make app_name=foo, 则构镜像名称为 registry/ns/foo:tag
ARG app_name
# 镜像的版本(tag),如 titan.hub:5000/demo/template-wetty:v20230129-6a9aa54 中的 v20230129-6a9aa54 是有 TitanIDE 自动生成,用户也可以通过参数指定,如 make app_version=v0.1
ARG app_version
# 以下是 TitanIDE 启动必须要用到的标签,用来区分当前模板的一些自定义参数
# 镜像维护者
LABEL maintainer="John Deng <john.deng@outlook.com>"
# 镜像名称,在 ARG app_name 部分已经解释过
LABEL metadata.appname="${app_name}"
# 镜像版本,在 ARG app_version 部分已经解释过
LABEL metadata.version="${app_version} "
# 应用的类型,WeTTY 是 Web 原生应用,所以需要指定为 webapp
LABEL metadata.type="webapp"
# 模板的图标,在 ARG icon 部分已经解释过
LABEL metadata.icon="${icon}"
# 右侧工具栏定义,以下选择了 file,port 两个工具,表示 WeTTY 启动后再右侧栏会有这两个工具
LABEL devtools="file,port"
# Linux 操作系统用户目录
LABEL metadata.home="/root"
# WeTTY 监听的端口号,TitanIDE 会根据这个端口号来创建访问的链接
LABEL metadata.port="${WETTY_PORT}"
# WeTTY 运行在用户组 root 下面,所以用户组 GID 为 0
LABEL metadata.gid=0
# WeTTY 运行在用户 root 下面,所以用户 UID 为 0
LABEL metadata.uid=0
# WeTTY 以 root 用户运行
LABEL metadata.user="root"
# 告诉 TitanIDE,WeTTY 服务的访问路径 (URL base) 需要重写
LABEL metadata.rewritesubpath=true
# 指定的工作路径(打开 Terminal 后所在的文件夹路径)
WORKDIR /root/workspace
# 复制启动命令脚本到 /usr/bin 下
COPY ./bin /usr/bin
# 用户自定义安装的组件,先将默认的 alpine apk 源替换成国内的,以加快构建速度,如果您在公司离线环境下,请更换为企业内部的源
# 这里我们定制安装了 bash vim git curl 几个组件
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' \
/etc/apk/repositories \
&& apk add -U bash vim git curl \
&& chmod +x /usr/bin/app
# 暴露的端口
EXPOSE ${WETTY_PORT}
# 最后运行启动脚本
ENTRYPOINT "/usr/bin/app"
构建镜像
TitanIDE 内置了镜像构建工具,具体的命令行在 Makefile 里面,执行 make help查看帮助。
➜ template-wetty git:(master) make help
Usage:
make <target>
help Display this help.
build build container image
login login to registry, e.g. make login username=your-username
Dockerfile 编辑好之后就可以直接在当前项目文件夹下面执行 make命令进行镜像的构建。
复制镜像 URL
接下来大概等待一分钟左右,镜像就可以构建完成。( 镜像构建耗时取决于几个条件,一是网络,是否需要从外网拉取镜像和文件;二是安装了多少软件。TitanIDE 支持全离线环境镜像构建,只需要把从外网拉取的镜像与文件改成本地的即可。)
镜像构建好了会在 IDE 的终端提示已经推送到镜像仓库,您可以选择并复制镜像 URL 以备用。(如果你仔细看镜像的tag 是以 -dirty 结尾的,那是因为修改的工程文件还未提交到 Git 仓库,提交之后 tag 就没有 -dirty 结尾,当然,您也可以在构建的 make 命令后面加参数直接指定 tag,具体操作方法请参考 README )
将代码提交到 Git 之后再次构建。
➜ template-wetty git:(master) make
2023-01-29T18:14:01 info workdir: /home/ide/workspace/template-wetty
2023-01-29T18:14:02 info Already contains credential for user admin in titan.hub:5000, if you want to update it, pleas input with force argument, e.g. make login force=true
2023-01-29T18:14:02 info Building container image on TitanIDE ...
......
(1/13) Installing readline (8.1.2-r0)
(2/13) Installing bash (5.1.16-r2)
Executing bash-5.1.16-r2.post-install
(3/13) Installing ca-certificates (20220614-r0)
(4/13) Installing brotli-libs (1.0.9-r6)
(5/13) Installing nghttp2-libs (1.47.0-r0)
(6/13) Installing libcurl (7.83.1-r5)
(7/13) Installing curl (7.83.1-r5)
(8/13) Installing expat (2.5.0-r0)
(9/13) Installing pcre2 (10.40-r0)
(10/13) Installing git (2.36.4-r0)
(11/13) Installing xxd (8.2.5000-r0)
(12/13) Installing lua5.4-libs (5.4.4-r5)
(13/13) Installing vim (8.2.5000-r0)
Executing busybox-1.35.0-r17.trigger
Executing ca-certificates-20220614-r0.trigger
OK: 59 MiB in 42 packages
INFO[0045] Taking snapshot of full filesystem...
INFO[0049] EXPOSE ${WETTY_PORT}
INFO[0049] Cmd: EXPOSE
INFO[0049] Adding exposed port: 3000/tcp
INFO[0049] ENTRYPOINT "/usr/bin/app"
INFO[0049] Pushing image to titan.hub:5000/demo/template-wetty:v20230129-da35bea
INFO[0050] Pushed titan.hub:5000/demo/template-wetty@sha256:4f0119b458fd6954f3c0bfaaf09186034969f807b7b3fde56b958bf9d3076f31
2023-01-29T18:14:57 info build phase: Running
2023-01-29T18:14:57 info pushed titan.hub:5000/demo/template-wetty:v20230129-da35bea
创建模板
进入模板列表,点击「创建模板」按钮。
将之前复制好模板镜像 URL (例如:titan.hub:5000/demo/template-wetty:v20230129-da35bea)粘贴到模板镜像输入框,再指定模板名称,除了以上项必填之外,其它为选填项,您可以根据需要来填写,如显示名称,模板描述等。
通过简单的两步,再点击「创建」即可创建好 TitanIDE 的模板。
创建项目
在 TitanIDE 创建项目有两个途径,第一、在项目列表页面通过点击「创建项目」按钮进入,选择模板进行创建,第二、在模板页面选择模板直接创建并快速打开项目。这里我们选用第二种方法一键创建 WeTTY 项目。
创建好 WeTTY 项目打开后直接进入 bash 终端,接下来就可以使用了。
根据我们在上一篇文章《在 TitanIDE 玩转云原生 Terminal 系列(一):TTY 的前世今生》所了解到的,我们在 WeTTY 终端来验证一下 tty stty -a几个命令。
问题
以上看起来似乎一切都是那么顺风顺水,不香吗?怎么标题看起来有点危言耸听?您且慢,听我解释一下:
WeTTY 官方镜像默认使用 alpine 基础镜像,而 WeTTY 也主打远程 SSH 连接,对于 TitanIDE 这种开发环境来说,不是很友好,alpine 作为服务运行很好,但是作为开发环境就力不从心了。
那好,我能不能自己从源码开始构建一个 WeTTY,然后使用 ubuntu 作为基础镜像呢?我还真这么干了,结果就更悲剧了,从源码构建也是成功了的,也可以运行起来,不过,我自己从源构建出来的死活对 --command 参数不感冒,如果要去解决这个问题,目前作为一个用户,所花费的时间成本不低了,因此只好暂且作罢。
我已经将这个问题提到开发者的 GitHub issue,后续再跟进。
上图是我在 TitanIDE 创建了一个 VS Code 项目,克隆了 WeTTY 源码并运行起来了,指定了 --command 却不起作用,下面是完整的启动命令。
1、克隆代码
//github.com/butlerx/wetty.git
2、编译代码并运行调试
yarn install
yarn install v1.22.19
warning package-lock.json found. Your project contains lock files generated by tools other than Yarn. It is advised not to mix package managers in order to avoid resolution inconsistencies caused by unsynchronized lock files. To clear this warning, remove package-lock.json.
[1/5] Validating package.json...
[2/5] Resolving packages...
success Already up-to-date.
Done in 0.71s.
yarn build
yarn run v1.22.19
$ snowpack build
[21:24:44] [snowpack] ! building files...
[21:24:46] [sass] Command completed.
[21:24:46] [snowpack] ✔ files built. [1.59s]
[21:24:46] [snowpack] ! building dependencies...
[21:24:55] [tsc] Command completed.
[21:24:57] [tsc] Command completed.
[21:24:58] [esinstall] /home/ide/workspace/wetty-source/node_modules/file-type/index.js:1045:16 Use of eval is strongly discouraged, as it poses security risks and may cause issues with minification
[21:24:59] [snowpack] ✔ dependencies built. [13.20s]
[21:24:59] [snowpack] ! writing to disk...
[21:24:59] [snowpack] ✔ write complete. [0.24s]
[21:24:59] [snowpack] ▶ Build Complete!
Done in 16.80s.
yarn start --port=8080 --base / --command /bin/bash
yarn run v1.22.19
$ NODE_ENV=production node . --port=8080 --base / --command /bin/bash
{"base":"/","label":"Wetty","level":"info","message":"Starting server","port":8080,"timestamp":"2023-01-29T12:24:07.205Z","title":"WeTTY - The Web Terminal Emulator"}
{"connection":"http","label":"Wetty","level":"info","message":"Server started","port":8080,"timestamp":"2023-01-29T12:24:07.224Z"}
{"label":"Wetty","level":"info","message":"Connection accepted.","timestamp":"2023-01-29T12:24:10.598Z"}
{"label":"Wetty","level":"info","message":"Authentication Type: password","timestamp":"2023-01-29T12:24:10.599Z"}
作为一个开发者,我以前可能会直接想办法解决上面这个问题,但是现在我多了一层思考,我们遇到问题的时候,应该先跳出来,找找有没有其他选择,在更多的选择中找一个最优解,而不是一头扎进去。以上问题就让更专业的开发者去解决。
总结
总体来说 WeTTY 是一个不错的 Web 终端,简单的几步就构建了一个 TitanIDE 模板镜像,并用它新建项目,直接打开使用。从使用的角度来看,功能和性能都很不错,也可以在页面直接定制字体,主题颜色,操作系统适配等等。如果作为一般用途,比如代替 xshell 等工具做运维相关工作还是很有竞争力的。但是希望用 WeTTY 来作为日常开发用,我相信也是可以的,不过这就需要花更多的时间去折腾了。
本文是系列文章《在 TitanIDE 玩转云原生 Terminal 系列》,我将会在下一篇继续就这个话题展开探索,敬请期待!
最后,感谢阅读!