🐳 Docker

记录 Docker 常用的内容。

Docker 几个常用工具

Write by GPT-4o:

工具 说明
Docker 用于创建和管理容器的基础工具,允许开发者将应用程序及其依赖打包成轻量级的容器,实现环境一致性和快速部署。
Docker Compose 用于定义和运行多容器Docker应用的工具,通过一个YAML文件配置应用的服务、网络和卷,简化了多容器应用的管理。
Docker Desktop 提供了在Windows和macOS上运行Docker容器的本地开发环境,包括Docker引擎、Docker CLI、Kubernetes和Docker Compose。
Docker Hub Docker的公共镜像仓库,用户可以在此存储、分发和管理Docker镜像,也可以从社区共享的镜像中拉取需要的镜像。

常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 查看正在运行的容器
docker ps

# 镜像列表
docker images

# 删除镜像
docker rmi <image_id>

# 通过docker-compose启动容器
docker-compose up

# 重新构建并启动容器
docker-compose up --build

Dockerfile 模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 使用 Node.js 20 作为基础镜像
FROM node:20-alpine
# FROM node:20

# 创建并设置工作目录
WORKDIR /data/app

# 复制项目文件
COPY . .

# 安装项目依赖
RUN yarn
RUN yarn build

# 暴露端口,默认使用 3000,实际端口将通过 docker-compose.yml 或命令行传入
EXPOSE 3000

# 启动项目
CMD ["yarn", "start"]

docker-compose.yml 模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

services:
app:
container_name: my_container_name
image: my_image_name:${IMAGE_TAG:-latest}
network_mode: bridge
build:
context: .
dockerfile: Dockerfile
ports:
# 4000是容器外部端口,3000是容器内部端口
- "4000:3000"
environment:
- PORT=3000
- NODE_ENV=production


场景:Mac 上构建 Docker 支持构建多平台镜像

在 Mac 上构建多平台镜像的时候会因缺少模拟器而报错,这时候需要安装 tonistiigi/binfmt 来支持多平台镜像构建。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# Step 1
# 安装 binfmt 支持多平台镜像构建
docker run --privileged --rm tonistiigi/binfmt --install all
# 或者只安装 arm64 和 amd64
docker run --privileged --rm tonistiigi/binfmt --install arm64,amd64

# Step 2
# 创建 buildx 构建器
docker buildx create --use --name my_builder --driver docker-container

# Step 3
# 检查和启动构建器
# 检查 builder 的配置,还会启动 BuildKit 容器(如果尚未启动)并确保 builder 准备好用于构建任务
# 查看当前 Driver 和 Platforms
# 需要确认 Driver 是 docker-container 不是 docker,Platforms 包含多个平台
docker buildx inspect --bootstrap

# Step 4
# 构建多平台镜像,--platform 参数指定要构建的平台,--load 参数表示构建完成后加载镜像(该情况只能支持一个 platform),--push 表示构建完成后推送镜像
# 构建并加载镜像
docker buildx build --platform linux/amd64 -t my_image_name:amd64 --load .
# 仅构建
docker buildx build --platform linux/arm64 -t my_image_name:arm64 .
# 构建并推送
docker buildx build --platform linux/amd64,linux/arm64 -t my_image_name:latest --push .

# Step 5
# 通过docker-compose运行镜像
docker-compose up -d

场景:手动部署镜像,Docker 镜像导出和导入

当不借助 Docker Hub 时,可以通过导出和导入镜像的方式来,把镜像打成压缩包,通过文件方式上传到服务器上。

1
2
3
4
5
6
# 导出镜像
docker save -o ./my_image_name.tar my_image_name:latest

# 导入镜像
docker load -i ./my_image_name.tar

场景:在 CentOS 上安装 Docker

在 CentOS 上安装 Docker 时通常会遇到 container-selinux 依赖问题,这时候手动下载 container-selinux 安装解决。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# Step 1
# 配置 Docker 安装源
curl -o /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 查看版本,如果有版本,说明配置源正确
yum list docker-ce --showduplicates | sort -r

# Step 2
# 下载 container-selinux,到一个临时目录
# https://pkgs.org/download/container-selinux
# 找到对应的版本,点进详情页,在 Download 里选择 Binary Package 下载
# 例如:
wget https://mirror.stream.centos.org/9-stream/AppStream/x86_64/os/Packages/container-selinux-2.232.1-1.el9.noarch.rpm
# 下载后,安装
rpm -ivh container-selinux-2.232.1-1.el9.noarch.rpm

# Step 3
# 安装docker
yum install docker-ce

# Step 4
# 启动 docker
systemctl start docker
# 设置开启启动
systemctl enable docker
# 测试
docker run hello-world
# 查看运行实例,验证是否成功
docker ps

...

👨🏻‍💻 工具集合

我的好用又好看的软件和开发工具 ❤️

Mac 新机必备

类别 APP
浏览器 Chrome
沟通 微信飞书
文档 WPS
脑图 XMind
网盘 百度网盘
输入法 微信输入法
辅助工具 iShot 截图FastZip 解压
开发工具 VSCode IDEPostman APIDocker

VSCode 插件

Plugins
中文支持 Chinese
标签重命名 Auto Rename Tag
英文拼写检查 Code Spell Checker
格式化 PrettierEditorConfigNginx ConfigHTML CSS SupportPrisma
语法提示 ESLintESLint ChineseSonarLintTailwind
Git 记录 Git History
代码快速执行 Code Runner
彩色注释 Better Comments
美化 VSCode IconsDracula Official 主题indent-rainbowOutput ColorizerHighlight on Copy
快捷键 Sublime Text Keymap
查看文件大小 Filesize
AI 助写代码 Github Copilot
TODO

Chrome 插件

Chrome

Plugins
Gmail Checker Plus for Gmail™
翻译 划词翻译
二维码生成 二维码生成
密码管理 LastPass
截屏 FireShot 截屏
GitHub GitZip for Github
Tab 书签 Toby 页签
查字体 WhatFont
脚步注入 暴力猴
格式化 JSON Formatter
DevTools Material DevTools Theme Collection
浏览净化 Wash baidu

Terminal 终端

• 软件安装器 HomeBrew
• 管理服务器命令终端 XTerminal
• AI 命令终端 Warp
• 命令终端 iTerm2
• Shell ZSH
• 美化 Starship
• NodeJS 版本管理 NVM

Theme 主题

• 主题 Dracula 包含了 iTerm2、VSCode、Zsh、Chrome…
• 字体 Nerd Font 终端(mononoki Nerd Font)

AI 工具

• 大语言模型 Llama3 8b 版本可以本地运行
• RAG 工具 Dify 支持聊天、RAG、工作流编排

其他

• MongoDB 客户端 Studio 3T
• Beyond Compare 文件对比工具 下载




—————————— 上次更新 2024.8.18 ——————————

...

🐘 koot.js 回忆录

koot.js 的历史到现在,大概有 5 个年头了,我打算停止投入,所以写下这篇回忆录。

初心

2015 年我开始接触 React 觉得很有趣,和 jQuery 相比页面开发思路更清晰,不需要用 js 直接操作 DOM 就可以完成页面交互逻辑。
在学习 React 的同时也接触到了 Redux、Webpack 这些技术,直到现在他们也非常流行。

我第一次完整的使用 React 进行项目实践是 2016 年 5 月,做了一款多人在线贪吃蛇 snakes游戏。
大概用的技术有:React、Redux、Socket.io、Less、Babel、Webpack…
同期也做了一次团队的技术分享,在现场会上大家通过浏览器加入了游戏场景,一起试玩。

问题来了,因为之前有开发游戏的经验,对游戏的设计和编码并不难,所以整个项目花费时间最多的是项目技术搭建,差不多占了一半的时间成本。在工作中,大家不敢轻易使用 React,担心遇到配置问题搞不定而卡住,为了解决团队在使用 React 的疑虑,我开始有了搭建 React 技术框架的想法。

内部孵化 super-project

随后,我就基于之前尝试的 React 项目开始思考如何搭建项目结构、如何选型合适的技术,并动手开发了一个非常基础的 React 开发框架,命名为 super-project,2016 年 8 月 17 日第一次 Commit 到公司内部的 Gitlab 上。
当时的前端 Leader 是李阳,我们在技术上有较好的共识,他开始支持我的 super-project 想法,并召集了当时团队几个技术不错的同学一起搞,所以在此我感谢当时在 super-project 付出的人:李阳、胡昕、孙驰、张攀(排名不分先后)。

目标 & 探索 & 实践

目标

当时 GitHub 社区上就有 create-react-app 脚手架可以快速开始一个 React 项目,但那太基础了,我们开始结合日常的工作思考 🤔

  • 如何一键开启开发环境?
  • css 使用 css-loader 还是 css-in-js 方式?css 的开发能不能像之前一样独立书写 class 又能做的易读、不担心重复?
  • 面对公司的国际化业务,能不能把国际化能力加进去,语音定义能不能更简单?
  • 开发的时候能不能是热更新?(当时的开源例子大部分是保存代码整页刷新)
  • MPA → SPA → Isomorphic,能不能做到“同构”? 能不能用一套代码可以打出 SPA 和 SSR 的代码包?
  • 能不能真正做到按需加载资源?包括 HTML、JS、CSS、Image…
  • 能不能把首屏渲染做到最小且内容非常完整?
  • 后来,关心是否可以直接把 PWA 也实现了

探索

带着这样的目标我们开始了技术的探索。

还记得当时我在做样式处理这部分探索的时候,css-loader 和 css-in-js 两种方式都觉得还不够。
css-loader 和 style-loader 在 webpack 处理的样式是可以满足日常需求的,但是在打包后,class 名的阅读性和唯一性则变得冲突起来,作为前端 geeker,我希望能把鱼和熊掌都需要,把 class 名的阅读性和唯一性都保持下来,另外希望配合按需加载把页面所需要的最少 css 提取出来。所以自己开发了处理 css 的 webpack loader 叫wrapper-css-loader,后来进化成 koot-css-loader 合并到 koot 里。

 还有多语言,当时是胡昕主要负责的模块,期望目标是尽量不改变 JSX 的组件结构,又同时能满足 SPA 和 SSR 两种模式,实现多语言切换双标准。

当然,注入此类的探索还有很多,这里不多说了…

实践验证 PhotoGrid & InstaNews

又过了一段时间,大概 2017 年初,刚好有两个重要性没那么强的项目,我们基于 super-project 开发了 PhotoGrid 网页版和 InstaNews 的网页版。使用了 Isomorphic 技术,也就是同构。成功的把 React 页面通过 Node Server 渲染出来,并且在浏览器端展示出来之后又保持了 SPA 的特性。
满足网页 SEO 的同时又保持着 WebAPP 单页面应用的体验。从此也验证了 super-project 的可行性。

PhotoGrid 的网页版是胡昕开发的,InstaNews 的网页版是李晓改开发的,在此感谢你们的勇于尝试。

坚持

super-project 在向好的方向发展,我从中学习到了很多,这个框架也帮助到了业务,但大家的技术理念不会一直很相同。
一年后,李阳离开了公司,其他同学在 super-project 上的贡献不多,只有胡昕一直还在与我为此奋斗。
当然,他在这个项目上也有较多的成长,所以很长一段时间我们可以一起搞技术研究。

对外公开改名 koot

当技术框架被验证之后,我们想帮助到更多的开发者,让 super-project 发挥更大的价值,所以我们讨论把它放到开源社区 GitHub 上。开始的时候我们想简化一点,比如叫 super.js 或者 superjs,但这些都被别人占用了。胡昕提议看看有哪些简单的字母开源拼起来,我们经过多次尝试发现,koot 这个词简单又没有人注册过 NPM 包,所以我们就定它了。

注册了 NPM 包 koot,也注册了免费域名 koot.js.org,看起来不错,是个好的开始。
随后又有一些新同学的加入:马振雨、王一奇、陈钦洋

技术的推广

团队内部

李阳走之后我成为了前端团队的新 Leader,我发现团队里大部分项目使用的前端技术都不同,有的用 jQuery、有的用 AngularJS、React、Vue。这对团队协作大大增加了成本,于是我做了一个霸王决定,团队项目全部使用 koot 作为开发框架,开发 UI 全部是切换到了 React 上。这样的好处是大家有相同的技术基础,那么团队在技术上的积累和沉淀也有了 koot 这个落脚点。

我的工作从主力开发变成了主要把控方向和技术推广。
大概有一年的时间,前端团队的项目几乎全部切换到了 koot 上。

公司内部

为了扩大 koot 的价值,让技术的能力传递的更广泛,我们在公司内部和开源社区上都做了响应的推广和分享。
2018 年 12 月,我联合培训部和一些热爱技术的同学一起搞了“豹前端主题分享月”,12 月里每周都会做面向全公司的技术分享,大部分内容和 koot 有关,帮助其他部门的前端同学了解 koot、使用 koot。很快公司有很多业务使用上了 koot,到 2019 年底公司与前端相关的业务有 80%都用到了 koot。

开源社区

在开源社区上的推广我们经验不足,通过 GitHub 自动检测发现虽然有一些项目在用,但数量不多,Star 也不多,如果让我再搞一次,我可能会选择多在一些自媒体平台上发布一下技术文章宣传。

选择不投入

背景

2020 年,疫情来了,企业的工作方式发生了很大的变化,这一年我们公司的变动也很大,有不少业务收到影响,感觉一整年都在不停的调整架构。我们团队这一年里大部分的工作是交接和对接,技术的推进不多,主要是 koot 上了 Serverless。业务和团队的缩减,让我们在技术基建方面的投入变得少,我的主要工作偏向管理,胡昕也很少有时间去维护,koot 的在这一年里发展不多。

迭代落后

react-router 已经出了 v5、redux 已经出了 v4、webpack 也出了 v5,等等很多技术生态库已经迭代升级一圈了,但 koot 跟不上了…
现在的市场上已经术业有专攻,React SSR 的解决方案有 Next.js,项目脚手架有 umi ,后台系统组件库有 antd 等等… 此时 koot 解决的问题大部分可以在前端行业里找到相似或者更好的方案。koot 如果不改变就无法为使用者带来较好的技术价值,如果继续投入精力就需要做的比 umi、Next.js 等开源技术做的好,那其实非常难,因为这些开源项目已经建立了很好的生态,有使用者和生产者的自循环。

认知边界

另一方面是到了认知边界。技术的根本是为了解决实际的问题,在最早的 super-project 是为了解决 👆 上面列出的一系列问题而诞生的,这些问题都是我们认知范围内知道要解决的。当我们已经把自己认知范围内的问题都解决掉了,而且业内也有更好解决方案的时候,我们没必要追赶,而是应该去洞察技术开发过程中还有什么问题需要被解决。解决了新的问题才回有新的价值,但不要为了解决问题而创造问题!

站在公司角度的选择

选择不投入,这是我代表公司做出的选择,因为在公司层面是需要考虑投入与产出比的,如果不能为公司带来更多价值,我会果断选项停止投入。但这不代表个人行为的停止投入,胡昕在这个项目上也注入了大量的心血,我们会把 koot 当做玩技术的一个途径,基于它仍然可以做各种尝试。

历史

2016 年 8 月 17 日在猎豹移动的 Gitlab 上提交了第一次代码
贡献者:我、胡昕、孙驰、李阳、张攀

2017 年 7 月 3 日在 GitHub 上提交了第一次代码
贡献者:我、胡昕、马振雨、王一奇、陈钦洋

2018 年 8 月 8 日在 NPM 上提交了第一个 koot 包

2020 年 5 月 15 日 在腾讯云 采访 koot 在 serverless 上的实践
https://serverlesscloud.cn/best-practice/2020-05-15-ssr-interview

2020 年 7 月 9 日 在 ServerlessDay · China 大会上的 koot 案例分享
https://serverlesscloud.cn/blog/2020-07-09-serverlessdays-tencent-2

2017 年 11 月 猎豹十佳技术文章《2017 年的 WEB 前端开发 - 单页面终于嫁给了多页面》
https://twiki.cmcm.com/pages/viewpage.action?pageId=11339894

案例

猎豹移动官网
https://www.cmcm.com

Bitrue 交易所
https://www.bitrue.com

...

2020 Serverless 实践,腾讯云采访

采访实录

问:董老师您好,请简要介绍一下您所在的团队。

答:我的团队是平台前端部,负责公司 AI、机器人、广告系统等业务和对外网站业务,团队成员包括前端工程师和 Node 全栈工程师。

问:基于什么背景和问题,您的团队考虑采用 SSR 的技术方案?

答:当然是追求极致的用户体验,虽然 HTML、CSS、JS 以及其他资源都做到了按需加载,但这里的 SSR 更是 Isomorphic(前后端同构),把 SSR (Server Side Rendering) 和 CSR (Client Side Render) 的优点结合,让用户浏览网页的时候不管是首屏还是随后操作的其他页都能更快的展示响应。

问:您的团队使用 SSR 技术方案时,有没有进行一些调研?

答:我们团队在 2016 年的时候开始使用 React,2017 年就开始研究并尝试 React Server Render,同期 Facebook 的网站已经采用 Isomorphic 技术实现,性能非常好。为了满足公司业务需求和技术传承,我们自研了猎豹的前端技术框架 Koot.js,目前已成为猎豹前端的主要技术方案。

问:能否从技术的角度介绍一下目前使用的 SSR 方案的前端技术框架 Koot.js,是基于什么样的架构,有哪些模块?

答:Koot.js 包含了 SSR,也是我们团队自研的方案,所以都是在用它.

Koot.js 是基于 React、Koa、Webpack 来架构的,其中用 Koa 搭建的 Node 作为开发服务和部署时候的 SSR 服务,页面渲染主要是用 React+Redux 完成的一套代码在浏览器环境和 Node 环境通用,利用 Webpack 可编程性动态生成配置并执行,打包出多场景(开发、测试和线上环境等)多端代码(前端、服务端)部署。

同时在开发过程中配合了自研工具和模块来辅助开发,如 koot-router、koot-redux、koot-webpack 进行了封装简化调用方法,提升开发效率;koot-cli 完成脚手架模板选择、项目配置等;koot-i18n 提供了多模式多语言方案,可以做到正常开发,打包后多语言内容按需加载的效果;集成了 koot-analyze 分析代码、预制 eslint 规范的 koot 版本等满足了日常工作所需的大部分技术点。

具体落地的时候,我们把自研的 Koot.js 使用 Serverless Framework 进行了封装,做了一个 Serverless 组件,这样在其他业务场景需要用的时候就可以直接复用,可以节省不少成本,避免了重复造轮子,降低了出错的概率。

问:SSR 的技术方案在落地时过程是否顺畅,遇到了哪些问题,是如何解决的?

答:SSR 项目落地的时候通常不是很顺畅,项目部署的时候需要具备服务器技术能力才能和运维顺畅沟通,所以项目落地不仅要前端同学掌握后端开发能力还要对运维技术、并发等问题多方面考虑,这对前端技术同学的技术全面行有较高要求。

在这种情况下,去年我们开始接触 Serverless 技术,Serverless 技术可以降低前端对服务端和运维的技术能力但要求,更适合大部分要做 SSR 的前端团队。调研了几大云厂商 Serverless 服务,最后综合比较后,选择了腾讯云作为我们实现 SSR 的 Serverless 服务支持。

腾讯云 Serverless 提供了比较全面的组件支持,与 Serverless Framework 基本是无缝结合,周边社区和生态支持也比较到位,使用过程应该会少踩一些坑。在选定了平台之后就比较顺畅了,因为 Serverless Framework 提供了很多标准化的接口,在封装 Koot.js Serveless 组件的过程中也比较省心。

问:目前的 SSR 方案推动了您所在团队哪些协作模式或分工的优化?

答:我们很早就做了前端分离的开发,前后端完全使用 API 对接,协作改变不大。因为我们做了 Isomorphic,所以对 API 的要求变高,用户的请求不止来源于 Node 服务器,还有来自浏览器的请求,对安全性要求会高一些。

问:从您的视角,目前 SSR 方案是否还需要一些改进?

答:我认为将来的 SSR 都应该是 Isomorphic 的模式,带来的好处是减少传输成本,分摊渲染压力,用户体验也会有所提升。体验的提升其实非常小,网路情况好时,用户几乎感知不到,但小小的提升在技术开发中却做出了非常多的工作,因此我们会把技术框架做的越来越完善,让业务开发同学能够快速开发出需求,同时又享有 Isomorphic 带来的技术体验。

问:对于还未开始做 SSR 的团队您有什么建议吗?

答:如果要做 ToC 的产品,建议做 SSR 尝试,让用户尽快的看见页面内容总是更好的。

前端的 SSR 一定会考虑是否需要 Isomorphic,如果小团队建议先从比较流行的框架着手尝试,如 Next.js、Nuxt.js 等,也推荐体验我们的 Koot.js。Next.js、Nuxt.js 这些框架在腾讯云 Serverless Framework 都现成的组件支持,Koot.js 也可以用我们的方案。无论是 SSR 还是 Serverless,最好都是基于现有框架,从零开始搭建框架坑太多了,如果没有足够业务支持不要浪费精力自己去做框架,学会一个框架的成本要远小于维护一个框架的成本。

采访人:王俊杰

More: https://serverlesscloud.cn/best-practice/2020-05-15-ssr-interview

...

sp-boilerplate (super-project 模板项目)(废弃)

super-project 是 koot.js 的前身。

目录 /apps 说明

apps下承载一下子项目,每个子项目可能有自己的前端和后端。

  • api 接口服务模板
  • doc React同构模板 & 文档站点
  • www EJS网站模板
  • saas 第三方服务功能模板

Debug

使用debug模块做控制台输出,类型:info|error|debug|log

Log

之前的没有记载,从现在开始记录

  • 2017-11-16

    移除/apps/saas 项目,使用sp-service-wx \sp-service-* 代替,
    原因是用域名方式在服务器本机内请求效率没有程序内请求效率高。

  • 2017-12-1

    修复了sp-css-import引用1个classname时,会多一个空格bug。

...