图文详细
获取图文详细信息
https://api.bilibili.com/x/polymer/web-dynamic/v1/opus/detail
请求方法: GET
鉴权方式: Cookie
中 buvid3
存在且不为空
URL 参数:
参数名 | 类型 | 内容 | 必要性 | 备注 |
---|---|---|---|---|
id | string | 动态 id | 必要 | 数字 |
timezone_offset | number | 时区偏移 | 非必要 | 如 -480 |
features | string | 功能 | 非必要 | onlyfansVote,onlyfansAssetsV2,decorationCard,htmlNewStyle,ugcDelete,editable,opusPrivateVisible,tribeeEdit,avatarAutoTheme,avatarTypeOpus |
JSON 回复:
根对象:
字段 | 类型 | 内容 | 备注 |
---|---|---|---|
code | number | 返回值 | 0: 成功 -352: 风控校验失败 |
data | object | 数据本体 | |
message | string | 错误信息 | 成功时为 0 |
ttl | number | 1 |
data
对象:
字段 | 类型 | 内容 | 备注 |
---|---|---|---|
item | object | 项 | 套了个娃 |
data.item
对象:
字段 | 类型 | 内容 | 备注 |
---|---|---|---|
basic | object | 基本信息 | |
id_str | string | 动态 id | |
modules | object[] | 模块信息 | 参见 功能模块 |
type | number | 类型 | |
fallback | number | 回滚信息 | 请检查请求参数 features |
data.item.basic
对象:
字段 | 类型 | 内容 | 备注 |
---|---|---|---|
comment_id_str | string | 评论对象 id 字符串 | |
comment_type | number | 评论区类型 | |
like_icon | object | 点赞图标? | |
rid_str | string | 关联 id 字符串 | |
title | string | 图文标题 | |
uid | number | 作者 mid (UID) |
data.item.basic.like_icon
对象:
字段 | 类型 | 内容 | 备注 |
---|---|---|---|
action_url | string | ||
end_url | string | ||
id | number | ||
start_url | string |
示例:
curl -G 'https://api.bilibili.com/x/polymer/web-dynamic/v1/opus/detail' \
--url-query 'id=933099353259638816' \
--url-query 'features=onlyfansVote,onlyfansAssetsV2,decorationCard,htmlNewStyle,ugcDelete,editable,opusPrivateVisible,tribeeEdit,avatarAutoTheme,avatarTypeOpus' \
-b 'buvid3=awa'
查看响应示例:
{
"code": 0,
"data": {
"item": {
"basic": {
"comment_id_str": "34646640",
"comment_type": 12,
"like_icon": {
"action_url": "",
"end_url": "",
"id": 0,
"start_url": ""
},
"rid_str": "34646640",
"title": "【服务搭建】零开销在线运行代码!glot.io服务私有化部署 - 哔哩哔哩",
"uid": 293793435
},
"id_str": "933099353259638816",
"modules": [
{
"module_title": {
"text": "【服务搭建】零开销在线运行代码!glot.io服务私有化部署"
},
"module_type": "MODULE_TYPE_TITLE"
},
{
"module_author": {
"avatar": {
"container_size": {
"height": 1.375,
"width": 1.375
},
"fallback_layers": {
"is_critical_group": true,
"layers": [
{
"general_spec": {
"pos_spec": {
"axis_x": 0.6875,
"axis_y": 0.6875,
"coordinate_pos": 2
},
"render_spec": {
"opacity": 1
},
"size_spec": {
"height": 0.787,
"width": 0.787
}
},
"layer_config": {
"is_critical": true,
"tags": {
"AVATAR_LAYER": {},
"GENERAL_CFG": {
"config_type": 1,
"general_config": {
"web_css_style": {
"borderRadius": "50%"
}
}
}
}
},
"resource": {
"res_image": {
"image_src": {
"placeholder": 6,
"remote": {
"bfs_style": "widget-layer-avatar",
"url": "https://i0.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg"
},
"src_type": 1
}
},
"res_type": 3
},
"visible": true
},
{
"general_spec": {
"pos_spec": {
"axis_x": 0.6875,
"axis_y": 0.6875,
"coordinate_pos": 2
},
"render_spec": {
"opacity": 1
},
"size_spec": {
"height": 1.375,
"width": 1.375
}
},
"layer_config": {
"tags": {
"PENDENT_LAYER": {}
}
},
"resource": {
"res_image": {
"image_src": {
"remote": {
"bfs_style": "widget-layer-avatar",
"url": "https://i0.hdslb.com/bfs/garb/item/4f8f3f1f2d47f0dad84f66aa57acd4409ea46361.png"
},
"src_type": 1
}
},
"res_type": 3
},
"visible": true
},
{
"general_spec": {
"pos_spec": {
"axis_x": 0.7560000000000001,
"axis_y": 0.7726666666666667,
"coordinate_pos": 1
},
"render_spec": {
"opacity": 1
},
"size_spec": {
"height": 0.41666666666666663,
"width": 0.41666666666666663
}
},
"layer_config": {
"tags": {
"GENERAL_CFG": {
"config_type": 1,
"general_config": {
"web_css_style": {
"background-color": "var(--bg1)",
"border": "2px solid var(--bg1)",
"borderRadius": "50%",
"boxSizing": "border-box"
}
}
},
"ICON_LAYER": {}
}
},
"resource": {
"res_image": {
"image_src": {
"local": 1,
"src_type": 2
}
},
"res_type": 3
},
"visible": true
}
]
},
"layers": [
{
"is_critical_group": true,
"layers": [
{
"general_spec": {
"pos_spec": {
"axis_x": 0.6875,
"axis_y": 0.6875,
"coordinate_pos": 2
},
"render_spec": {
"opacity": 1
},
"size_spec": {
"height": 0.787,
"width": 0.787
}
},
"layer_config": {
"is_critical": true,
"tags": {
"AVATAR_LAYER": {},
"GENERAL_CFG": {
"config_type": 1,
"general_config": {
"web_css_style": {
"borderRadius": "50%"
}
}
}
}
},
"resource": {
"res_image": {
"image_src": {
"placeholder": 6,
"remote": {
"bfs_style": "widget-layer-avatar",
"url": "https://i0.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg"
},
"src_type": 1
}
},
"res_type": 3
},
"visible": true
}
]
},
{
"layers": [
{
"general_spec": {
"pos_spec": {
"axis_x": 0.6875,
"axis_y": 0.6875,
"coordinate_pos": 2
},
"render_spec": {
"opacity": 1
},
"size_spec": {
"height": 1.375,
"width": 1.375
}
},
"layer_config": {
"tags": {
"PENDENT_LAYER": {}
}
},
"resource": {
"res_animation": {
"webp_src": {
"remote": {
"bfs_style": "widget-layer-avatar",
"url": "https://i0.hdslb.com/bfs/garb/item/fe0b83b53e2342b16646f6e7a9370d8a867decdb.webp"
},
"src_type": 1
}
},
"res_type": 4
},
"visible": true
}
]
},
{
"layers": [
{
"general_spec": {
"pos_spec": {
"axis_x": 0.7560000000000001,
"axis_y": 0.7726666666666667,
"coordinate_pos": 1
},
"render_spec": {
"opacity": 1
},
"size_spec": {
"height": 0.41666666666666663,
"width": 0.41666666666666663
}
},
"layer_config": {
"tags": {
"GENERAL_CFG": {
"config_type": 1,
"general_config": {
"web_css_style": {
"background-color": "var(--bg1)",
"border": "2px solid var(--bg1)",
"borderRadius": "50%",
"boxSizing": "border-box"
}
}
},
"ICON_LAYER": {}
}
},
"resource": {
"res_image": {
"image_src": {
"local": 1,
"src_type": 2
}
},
"res_type": 3
},
"visible": true
}
]
}
],
"mid": "293793435"
},
"decorate_card": {
"big_card_url": "https://i0.hdslb.com/bfs/garb/item/c0cf2235089ed314d92f30efa855c9b5611fa2cd.png",
"card_type": 2,
"card_type_name": "免费",
"card_url": "https://i0.hdslb.com/bfs/garb/item/c0cf2235089ed314d92f30efa855c9b5611fa2cd.png",
"fan": {
"color": "#07b6d5",
"color_format": {
"colors": [
"#07b6d5FF",
"#07b6d5FF"
],
"end_point": "0,100",
"gradients": [
0,
100
],
"start_point": "0,0"
},
"is_fan": 1,
"name": "初音未来周年纪念",
"num_desc": "005638",
"number": 5638
},
"id": 2513,
"image_enhance": "https://i0.hdslb.com/bfs/garb/item/c0cf2235089ed314d92f30efa855c9b5611fa2cd.png",
"item_id": 2513,
"jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=2513&isdiy=0&part=card&from=post&f_source=garb&vmid=293793435&native.theme=1&navhide=1",
"name": "初音未来粉丝专属"
},
"face": "https://i0.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg",
"face_nft": false,
"following": true,
"jump_url": "//space.bilibili.com/293793435",
"label": "",
"mid": 293793435,
"more": {
"three_point_items": [
{
"label": "举报",
"type": "THREE_POINT_REPORT"
}
]
},
"name": "社会易姐QwQ",
"official": {
"desc": "",
"role": 0,
"title": "",
"type": -1
},
"pendant": {
"expire": 0,
"image": "https://i0.hdslb.com/bfs/garb/item/4f8f3f1f2d47f0dad84f66aa57acd4409ea46361.png",
"image_enhance": "https://i0.hdslb.com/bfs/garb/item/fe0b83b53e2342b16646f6e7a9370d8a867decdb.webp",
"image_enhance_frame": "https://i0.hdslb.com/bfs/garb/item/127c507ec8448be30cf5f79500ecc6ef2fd32f2c.png",
"n_pid": 2511,
"name": "初音未来13周年",
"pid": 2511
},
"pub_location_text": "",
"pub_time": "编辑于 2024年05月19日 12:18",
"pub_ts": 1716092523,
"views_text": "",
"vip": {
"avatar_icon": {
"icon_resource": {},
"icon_type": 1
},
"avatar_subscript": 1,
"avatar_subscript_url": "",
"due_date": 1770825600000,
"label": {
"bg_color": "#FB7299",
"bg_style": 1,
"border_color": "",
"img_label_uri_hans": "",
"img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/8d4f8bfc713826a5412a0a27eaaac4d6b9ede1d9.png",
"img_label_uri_hant": "",
"img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/VEW8fCC0hg.png",
"label_theme": "annual_vip",
"path": "http://i0.hdslb.com/bfs/vip/label_annual.png",
"text": "年度大会员",
"text_color": "#FFFFFF",
"use_img_label": true
},
"nickname_color": "#FB7299",
"role": 3,
"status": 1,
"theme_type": 0,
"tv_due_date": 1640793600,
"tv_vip_pay_type": 0,
"tv_vip_status": 0,
"type": 2,
"vip_pay_type": 0
}
},
"module_type": "MODULE_TYPE_AUTHOR"
},
{
"module_content": {
"paragraphs": [
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "感谢 "
}
},
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"color": "#ff968d",
"font_size": 17,
"style": {},
"words": "来笙云 Laysense.cn"
}
},
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": " 提供算力"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "作为一个全栈工程师,开发、维护和测试一些软件系统时,必然会涉及到多种编程语言,有时还需要测试一些编程语言的安全特性,常常需要敏捷地了解它们并立即上手。在朋友的推荐和社区分享下,我了解到一个名叫 glot.io 的开源项目。"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "它支持40多种编程语言,无论是热门的 Python、Go、Rust、Kotlin,还是冷门的 COBOL、Erlang、Haskell 只需在网页上选择对应的语言,即可开始编写。为使用者提供了一个 Sandbox(沙箱)和 Playground(游乐场)环境,既不需要配置它们的 Runtime(运行环境)和 IDE(集成开发环境),也不需要担心误操作对系统产生破坏性,还不会占用任何用户端的系统资源,实现真正的零开销运行代码。"
}
}
]
}
},
{
"align": 0,
"para_type": 2,
"pic": {
"pics": [
{
"height": 1120,
"live_url": null,
"size": null,
"url": "https://i0.hdslb.com/bfs/article/06582181a80a3f367ae0486aec34759f293793435.png",
"width": 1776
}
],
"style": 2
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "在代码编写界面,可以创建多个源码文件,完成后点击Run就能执行它并得到输出,类似我们平时编程那样,将输出打在终端上。整个过程不会生成任何可执行文件,所以它的应用场景不是在线编译,而是在线运行代码片段。"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "\n"
}
}
]
}
},
{
"align": 0,
"para_type": 2,
"pic": {
"pics": [
{
"height": null,
"live_url": null,
"size": null,
"url": "https://i0.hdslb.com/bfs/new_dyn/bb4e8fc35a33ba0b771478f4bc5aaca7293793435.png",
"width": null
}
],
"style": 2
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "glot.io 这个网站提供了公开的代码片段执行和分享功能,任何人在注册后都可以分享自己的代码片段,并使用它的 API。但有时为了安全性和访问速度考量,需要自行搭建这个开源平台,这篇文章将介绍 Glot 的私有化部署。"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 24,
"style": {
"bold": true
},
"words": "Glot是什么"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "根据项目 README 上的一句介绍:"
}
}
]
}
},
{
"align": 0,
"para_type": 4,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "an open source pastebin with runnable snippets and API."
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "这是一个开源的共享剪切板和代码片段执行器,并提供 API。它使用 MIT 协议开源,代码托管于 github 之上。"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "https://github.com/glotcode/glot"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "Glot 并不是一个独立的工程,它分为多个组件,这样设计底层架构有利于业务解耦,降低后期维护和升级开发的难度,它们之间的逻辑关系如下:"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "\n"
}
}
]
}
},
{
"align": 0,
"para_type": 2,
"pic": {
"pics": [
{
"height": null,
"live_url": null,
"size": null,
"url": "https://i0.hdslb.com/bfs/new_dyn/808dd5fa58016f392b15a36a0df27a29293793435.png",
"width": null
}
],
"style": 2
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "由下面这些组件构成,也全部使用 MIT 协议开源,均托管于 Github:"
}
}
]
}
},
{
"align": 0,
"list": {
"items": [
{
"level": 1,
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"color": "#ff968d",
"font_size": 17,
"style": {},
"words": "glot-www"
}
},
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": ":提供 B/S 前端应用"
}
}
],
"order": 1
},
{
"level": 1,
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"color": "#ff968d",
"font_size": 17,
"style": {},
"words": "docker-run"
}
},
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": ":提供执行 glot-images 镜像能力的微服务"
}
}
],
"order": 2
},
{
"level": 1,
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"color": "#ff968d",
"font_size": 17,
"style": {},
"words": "glot-images"
}
},
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": ":按需构建的执行器镜像"
}
}
],
"order": 3
},
{
"level": 1,
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"color": "#ff968d",
"font_size": 17,
"style": {},
"words": "code-runner"
}
},
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": ":容器内的执行调度器"
}
}
],
"order": 4
}
],
"style": 2
},
"para_type": 5
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "其中 glot-www 是一个 B/S 架构应用的服务器,用来提供一个面向用户的 WebUI(网站),它包含前后端的组件,后端使用 Haskell 语言编写。实现代码片段保存和共享、用户登录、以及共享剪切板所的功能,由 pgSQL 提供存储支持。与此同时,它与实际的代码执行业务互相解耦,使用 RestAPI 进行 RPC 调用,可做到前端服务器和后端代码执行服务器逻辑上隔离。"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "Glot 的代码执行沙箱基于 Docker,在容器中编译和运行,不但与宿主机隔离,且容器之间也相互隔离,还能对运行资源进行限制,防止宿主机被不信任的代码破坏。当然,各编程语言的执行容器构成不尽相同,这样才能在节约存储空间的同时最大保持运行效率,比如 C 和 C++ 共用了glot/clang这个镜像,C"
}
},
{
"rich": {
"jump_url": "//search.bilibili.com/all?keyword=%20%E5%92%8C%20F",
"orig_text": "# 和 F#",
"text": "# 和 F#",
"type": "RICH_TEXT_NODE_TYPE_TOPIC"
},
"type": "TEXT_NODE_TYPE_RICH"
},
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": " 的镜像都有 mono 这个依赖……这些 Docker 镜像由 glot-images 项目进行生成,它并非使用传统的 Dockerfile,而是使用了 nix 进行构建,支持多种主流编程语言。"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "\n"
}
}
]
}
},
{
"align": 0,
"para_type": 2,
"pic": {
"pics": [
{
"height": null,
"live_url": null,
"size": null,
"url": "https://i0.hdslb.com/bfs/new_dyn/8627bd181a4c0ef3f5985f2d80ed49a5293793435.png",
"width": null
}
],
"style": 2
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "宿主机与沙箱的通讯,实际上就构建并将代码传入容器。这个传递方式不使用文件,而使用 stdi(基本输入)的方式传递 json,例如这样的形式:"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "echo '{\n "language": "python",\n "files": [\n {\n "name": "main.py",\n "content": "print(42)"\n }\n ]\n}' | docker run --rm -i --read-only --tmpfs /tmp:rw,noexec,nosuid,size=65536k --tmpfs /home/glot:rw,exec,nosuid,uid=1000,gid=1000,size=131072k -u glot -w /home/glot glot/javascript:latest",
"lang": "language-bash"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "执行完成之后以 stdo(基本输出)的方式输出 json,stdout、stderr 流、以及错误信息在序列化后拆分成各个字段:"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "{\n "stdout": "42\\n",\n "stderr": "",\n "error": ""\n}",
"lang": "language-json"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "一般编程语言分为编译型、解释型和虚拟机型,其中解释型直接执行文本文件中的内容,编译型则需将其编译为可执行文件再执行,而虚拟机型在编译完之后,还需用 vm 执行字节码。glot-images 将各类编程语言生成的工作流统一归做 json 格式的文本流,这样标准化更利于开发和扩展,这种能力归功于 code-runner 这个组件。"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "code-runner 作为 glot 的一个特殊组件,并不运行在宿主机中,它是一个 cli 工具,运行在执行容器中,使用 Rust 语言开发。在 glot-images 的每个镜像中,均以相同方式工作在底层。它支持多种编程语言从编译到运行的生命周期管理,同时接管运行时的 stdio(基本输入输出)"
}
},
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {
"bold": true
},
"words": ","
}
},
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "例如 C 语言,首先会将输入的文本反序列化,写入到文件,接着调用 clang 编译这个文件,最后再运行编译器生成的可执行文件,执行过程中也会将预定义的 stdi 发送给程序,程序的 stdo/stderr 流被它记录下来随后序列化为 json 文本返回。实际上在使用docker run这类命令执行 glot-images 镜像时,就是调用了之中的 code-runner,而不是调用了clang这种编译器。"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "使用 stdi 传递 json 给它,就会调用相应的编译执行流程:"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "echo '{\n "language": "python",\n "files": [\n {\n "name": "main.py",\n "content": "print(42)"\n }\n ]\n}' | code-runner",
"lang": "language-bash"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "与 glot-images 的镜像相同,执行后也会使用 stdo 以 json 格式返回:"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "{\n "stdout": "42\\n",\n "stderr": "",\n "error": ""\n}",
"lang": "language-json"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "要将这些跑在 Docker 上的执行器服务化、RPC(远程过程调用)化,必须有一个 daemon 在底层进行调度,一边开放 HTTP 服务,另一边通过 unix socket 操纵 DockerEngine,执行容器操作。提供这个能力的就是 docker-run 组件,它也使用 Rust 语言开发。"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "例如这样访问 docker-run,和上文中的例子相同:"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "curl 'http://localhost:8088/run' \\\n -H 'X-Access-Token: some-secret-token' \\\n -H 'Content-type: application/json' \\\n -d '{\n "image": "glot/python:latest",\n "payload": {\n "language": "python",\n "files": [\n {\n "name": "main.py",\n "content": "print(42)"\n }\n ]\n }\n}'",
"lang": "language-bash"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "有了这些组件,就可以自行私有化搭建一个 glot 服务,因为各组件的标准化和解耦,可以随意进行裁剪和二次开发。"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "接下来将介绍 docker-run 和 glot-images 这两个基本组件的搭建(不搭建前端 WebUI 和共享服务)。"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 24,
"style": {
"bold": true
},
"words": "Glot服务搭建"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "首先应该准备一台性能不错的服务器,要求 CPU 核心数和 RAM 不能太低。以下步骤使用 Debian 12 系统进行操作,整个过程需要有稳定的网络环境,并且已更新包管理器的索引。"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 24,
"style": {
"bold": true
},
"words": "安装Docker和运行环境"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "首先需要安装前置依赖,其中 git 和 gcc 安装 Rust 时需要,runsc 是 gVisor 运行环境"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "sudo apt-get install ca-certificates curl git gcc runsc",
"lang": "language-bash"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "安装 Docker,这里参考了官方文档的安装方式,先进行软件源的添加,再安装各组件"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "https://docs.docker.com/engine/install/debian/"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "sudo install -m 0755 -d /etc/apt/keyrings\nsudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc\nsudo chmod a+r /etc/apt/keyrings/docker.asc\necho \\\n "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \\\n $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \\\n sudo tee /etc/apt/sources.list.d/docker.list > /dev/null\nsudo apt update\n\nsudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin",
"lang": "language-bash"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "gVisor 作为谷歌开源的一款轻量容器运行时沙箱,可作为 Docker 的运行时中间件,隔离容器内的 syscall,提升容器安全性,具体可以参考官网 https://gvisor.dev"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "对于 Docker,需要配置 gVisor 为 DockerEngine 插件,创建配置文件后写入以下内容:"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "vi /etc/docker/daemon.json",
"lang": "language-bash"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "\n"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "{\n "default-runtime": "runsc",\n "runtimes": {\n "runsc": {\n "path": "/usr/bin/runsc"\n }\n }\n}",
"lang": "language-json"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "在修改配置文件后,应重启 DockerEngine"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "systemctl restart docker",
"lang": "language-bash"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "可以使用以下命令检查检查 Docker 和 gVisor 安装状态"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "docker system info\ndocker system info | grep 'runsc'",
"lang": "language-bash"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "\n"
}
}
]
}
},
{
"align": 0,
"para_type": 2,
"pic": {
"pics": [
{
"height": null,
"live_url": null,
"size": null,
"url": "https://i0.hdslb.com/bfs/new_dyn/f2a9046662ce5bdc93a5bbe7393dd2b4293793435.png",
"width": null
}
],
"style": 2
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "\n"
}
}
]
}
},
{
"align": 0,
"para_type": 2,
"pic": {
"pics": [
{
"height": null,
"live_url": null,
"size": null,
"url": "https://i0.hdslb.com/bfs/new_dyn/888de2ab19dede7ec6880f407269519c293793435.png",
"width": null
}
],
"style": 2
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "接者我们创建名为glot的用户,作为 daemon 的运行角色"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "useradd -m glot\nusermod -aG docker glot",
"lang": "language-bash"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "安装 Rust,这里参考官方文档,使用脚本进行安装"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "https://rustup.rs/"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh",
"lang": "language-bash"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "\n"
}
}
]
}
},
{
"align": 0,
"para_type": 2,
"pic": {
"pics": [
{
"height": null,
"live_url": null,
"size": null,
"url": "https://i0.hdslb.com/bfs/new_dyn/2d7118b743cd2f10cd289e59969eeb01293793435.png",
"width": null
}
],
"style": 2
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "安装完毕后,可以使用以下命令检查 Rust 的安装"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "cargo -V",
"lang": "language-bash"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "\n"
}
}
]
}
},
{
"align": 0,
"para_type": 2,
"pic": {
"pics": [
{
"height": null,
"live_url": null,
"size": null,
"url": "https://i0.hdslb.com/bfs/new_dyn/0e40ab6cc26aa95bcaf7458159316d7c293793435.png",
"width": null
}
],
"style": 2
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "因官方的 crates 源速度很慢,如果国内使用可以换为镜像源,这里使用了 SJTU 镜像"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "vi ~/.cargo/config.toml",
"lang": "language-bash"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "\n"
}
}
]
}
},
{
"align": 0,
"para_type": 2,
"pic": {
"pics": [
{
"height": null,
"live_url": null,
"size": null,
"url": "https://i0.hdslb.com/bfs/new_dyn/4b8b4b8e7550009d6fd0c4439922564a293793435.png",
"width": null
}
],
"style": 2
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 24,
"style": {
"bold": true
},
"words": "编译docker-run"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "克隆 docker-run 项目,准备使用源码进行编译安装"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "git clone https://github.com/glotcode/docker-run glot-docker-run",
"lang": "language-bash"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "进入仓库目录,使用 cargo 编译 Rust 工程"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "cd glot-docker-run\ncargo b -r",
"lang": "language-bash"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "\n"
}
}
]
}
},
{
"align": 0,
"para_type": 2,
"pic": {
"pics": [
{
"height": null,
"live_url": null,
"size": null,
"url": "https://i0.hdslb.com/bfs/new_dyn/7c39ed2031e7932c1bc24926ea1c3025293793435.png",
"width": null
}
],
"style": 2
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "检查编译结果,在工程目录的target/release中将会生成名为docker-run的可执行文件"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "\n"
}
}
]
}
},
{
"align": 0,
"para_type": 2,
"pic": {
"pics": [
{
"height": null,
"live_url": null,
"size": null,
"url": "https://i0.hdslb.com/bfs/new_dyn/51d7ad2ddf5dd75c531e267965c6ddb6293793435.png",
"width": null
}
],
"style": 2
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "复制可执行文件和 systemd 服务模板"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "cp target/release/docker-run /home/glot/bin/\ncp systemd/docker-run.service /etc/systemd/system/",
"lang": "language-bash"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "docker-run 服务使用 systemd 进行托管,作为 daemon 运行,它对外提供一个 http 服务,其他应用使用 RestAPI 与之对接\n编辑 systemd 服务配置文件"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "vi /etc/systemd/system/docker-run.service",
"lang": "language-bash"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "docker-run 的配置文件全部为环境变量,一些重要的参数已经给出了注释"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "其中SERVER_LISTEN_ADDR和SERVER_LISTEN_PORT决定了 daemon 监听的 ip 和端口号,可以根据需求修改"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "SERVER_WORKER_THREADS为 worker 线程数,根据实际业务并发量修改,即越多可同时执行的任务越多"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "API_ACCESS_TOKEN是 RestAPI 的访问 Token,设定一个较复杂的值,可防止未授权访问,在调用中以 HTTP 请求 Header 的X-Access-Token字段进行传递"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "RUN_MAX_EXECUTION_TIME参数用来限制任务执行的超时时间,其单位为秒,如果一个任务大于这个时间没有执行完毕,docker-run 就会销毁这个容器,并会返回一个 400 错误"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "RUN_MAX_OUTPUT_SIZE参数是用来限制最大输出量的,它的单位是 Byte,如果输出的内容过大,同样会被丢弃并报错\n这些参数的详细配置也可以参考 docker-run 项目的 README: https://github.com/glotcode/docker-run?tab=readme-ov-file#environment-variables"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "[Unit]\nDescription=docker-run\n\n[Service]\nUser=glot\nGroup=glot\nRestart=always\nRestartSec=10\nExecStart=/home/glot/bin/docker-run\n# 服务绑定 ip\nEnvironment="SERVER_LISTEN_ADDR=0.0.0.0"\n# 服务监听端口\nEnvironment="SERVER_LISTEN_PORT=8088"\n# worker 线程数\nEnvironment="SERVER_WORKER_THREADS=10"\n# API Token\nEnvironment="API_ACCESS_TOKEN=some-secret-token"\n# Docker socket 路径\nEnvironment="DOCKER_UNIX_SOCKET_PATH=/var/run/docker.sock"\nEnvironment="DOCKER_UNIX_SOCKET_READ_TIMEOUT=3"\nEnvironment="DOCKER_UNIX_SOCKET_WRITE_TIMEOUT=3"\n# 容器主机名\nEnvironment="DOCKER_CONTAINER_HOSTNAME=glot"\n# 容器用户\nEnvironment="DOCKER_CONTAINER_USER=glot"\n# 容器最大内存限制\nEnvironment="DOCKER_CONTAINER_MEMORY=1000000000"\n# 容器内是否禁用网络支持\nEnvironment="DOCKER_CONTAINER_NETWORK_DISABLED=true"\nEnvironment="DOCKER_CONTAINER_ULIMIT_NOFILE_SOFT=90"\nEnvironment="DOCKER_CONTAINER_ULIMIT_NOFILE_HARD=100"\nEnvironment="DOCKER_CONTAINER_ULIMIT_NPROC_SOFT=90"\nEnvironment="DOCKER_CONTAINER_ULIMIT_NPROC_HARD=100"\nEnvironment="DOCKER_CONTAINER_CAP_DROP=MKNOD NET_RAW NET_BIND_SERVICE"\nEnvironment="DOCKER_CONTAINER_READONLY_ROOTFS=true"\nEnvironment="DOCKER_CONTAINER_TMP_DIR_PATH=/tmp"\nEnvironment="DOCKER_CONTAINER_TMP_DIR_OPTIONS=rw,noexec,nosuid,size=65536k"\n# 容器工作目录\nEnvironment="DOCKER_CONTAINER_WORK_DIR_PATH=/home/glot"\nEnvironment="DOCKER_CONTAINER_WORK_DIR_OPTIONS=rw,exec,nosuid,size=131072k"\n# 容器执行超时时间\nEnvironment="RUN_MAX_EXECUTION_TIME=15"\n# 最大允许输出\nEnvironment="RUN_MAX_OUTPUT_SIZE=100000"\n# 日志级别\nEnvironment="RUST_LOG=debug"\n\n[Install]\nWantedBy=multi-user.target",
"lang": "language-yaml"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "修改完配置文件就可启动服务了,并将它设为开机自启"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "systemctl daemon-reload\nsystemctl enable --now docker-run.service",
"lang": "language-bash"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "GET 请求刚才配置的那个地址的根路径,测试服务运行状态正常,我这里是 http://localhost:8088/"
}
}
]
}
},
{
"align": 0,
"para_type": 2,
"pic": {
"pics": [
{
"height": null,
"live_url": null,
"size": null,
"url": "https://i0.hdslb.com/bfs/new_dyn/7e0a6d73cdb1ba63bcfcbe94df9c7b39293793435.png",
"width": null
}
],
"style": 2
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 24,
"style": {
"bold": true
},
"words": "拉取Docker镜像"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "glot-images 构建了各编程语言的执行镜像,这些镜像使用 nix 构建,但因为 nix 的配置比较复杂,且占用存储空间巨大,这里直接使用上传在 DockerHub 的镜像了(弊端就是语言版本比较旧)"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "https://hub.docker.com/u/glot"
}
}
]
}
},
{
"align": 0,
"para_type": 2,
"pic": {
"pics": [
{
"height": null,
"live_url": null,
"size": null,
"url": "https://i0.hdslb.com/bfs/new_dyn/e63013e3c15cd556ec7ce82048d43889293793435.png",
"width": null
}
],
"style": 2
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "通过 docker pull命令拉取各个镜像,可以按照自己的需求拉取,比如你只需要执行某几个编程语言"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "docker pull glot/assembly\ndocker pull glot/ats\ndocker pull glot/bash\ndocker pull glot/clang\ndocker pull glot/clisp\ndocker pull glot/clojure\ndocker pull glot/cobol\ndocker pull glot/coffeescript\ndocker pull glot/crystal\ndocker pull glot/csharp\ndocker pull glot/dart\ndocker pull glot/elixir\ndocker pull glot/elm\ndocker pull glot/erlang\ndocker pull glot/fsharp\ndocker pull glot/golang\ndocker pull glot/groovy\ndocker pull glot/guile\ndocker pull glot/hare\ndocker pull glot/haskell\ndocker pull glot/idris\ndocker pull glot/java\ndocker pull glot/javascript\ndocker pull glot/julia\ndocker pull glot/kotlin\ndocker pull glot/lua\ndocker pull glot/mercury\ndocker pull glot/nim\ndocker pull glot/nix\ndocker pull glot/ocaml\ndocker pull glot/pascal\ndocker pull glot/perl\ndocker pull glot/php\ndocker pull glot/python\ndocker pull glot/raku\ndocker pull glot/ruby\ndocker pull glot/rust\ndocker pull glot/sac\ndocker pull glot/scala\ndocker pull glot/swift\ndocker pull glot/typescript\ndocker pull glot/zig",
"lang": "language-bash"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "这些全部拉取下来大概需要38GB,可以使用docker images命令检查拉取情况"
}
}
]
}
},
{
"align": 0,
"para_type": 2,
"pic": {
"pics": [
{
"height": null,
"live_url": null,
"size": null,
"url": "https://i0.hdslb.com/bfs/new_dyn/82a01995548eb266d59f7fd22f75e542293793435.png",
"width": null
}
],
"style": 2
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "如果已经拉取了所有的镜像,可以执行单元测试脚本,来验证各编程语言执行容器的正确性,在 docker-run 的目录下的scripts目录内"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "cd glot-docker-run/scripts/\n./test_glot.sh 'http://localhost:8088' 'some-secret-token'",
"lang": "language-bash"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "\n"
}
}
]
}
},
{
"align": 0,
"para_type": 2,
"pic": {
"pics": [
{
"height": null,
"live_url": null,
"size": null,
"url": "https://i0.hdslb.com/bfs/new_dyn/004e79df950a4bc93ff42fae8017d0aa293793435.png",
"width": null
}
],
"style": 2
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 24,
"style": {
"bold": true
},
"words": "使用Glot服务"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "docker-run 这个组件对外提供 RestAPI 接口,其他进程或者其他主机可以直接调用,它共有三个功能对应其路径:"
}
}
]
}
},
{
"align": 0,
"para_type": 2,
"pic": {
"pics": [
{
"height": null,
"live_url": null,
"size": null,
"url": "https://i0.hdslb.com/bfs/new_dyn/a28b283d2075bbd78c12e1d2859fd40d293793435.png",
"width": null
}
],
"style": 2
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "查询服务状态"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "curl http://localhost:8088/",
"lang": "language-bash"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "返回 daemon 的服务名、版本等"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "{\n "name": "docker-run",\n "version": "1.4.0",\n "description": "Api for running code in transient docker containers"\n}",
"lang": "language-json"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "查询宿主机 DockerEngine 信息,访问这个接口需要在请求 Header 的X-Access-Token字段中携带 Token"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "curl http://localhost:8088/version \\\n -H 'X-Access-Token: some-secret-token'",
"lang": "language-bash"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "执行成功将会返回 DockerEngine 的版本信息"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "{\n "docker": {\n "version": "26.1.2",\n "apiVersion": "1.45",\n "gitCommit": "ef1912d",\n "goVersion": "go1.21.10",\n "os": "linux",\n "arch": "amd64",\n "kernelVersion": "6.2.16-3-pve",\n "buildTime": "2024-05-08T13:59:59.000000000+00:00",\n "platform": {\n "name": "Docker Engine - Community"\n },\n "components": [\n {\n "name": "Engine",\n "version": "26.1.2"\n },\n {\n "name": "containerd",\n "version": "1.6.31"\n },\n {\n "name": "runsc",\n "version": "0.0~20221219.0"\n },\n {\n "name": "docker-init",\n "version": "0.19.0"\n }\n ]\n }\n}",
"lang": "language-json"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "执行响应的代码前,需要构建一个 json 请求体,用来描述创建的执行任务的行为,下表是它的定义:"
}
}
]
}
},
{
"align": 0,
"para_type": 2,
"pic": {
"pics": [
{
"height": null,
"live_url": null,
"size": null,
"url": "https://i0.hdslb.com/bfs/new_dyn/752ce6ef76a448158eb97222befa7c92293793435.png",
"width": null
}
],
"style": 2
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "payload 结构:"
}
}
]
}
},
{
"align": 0,
"para_type": 2,
"pic": {
"pics": [
{
"height": null,
"live_url": null,
"size": null,
"url": "https://i0.hdslb.com/bfs/new_dyn/752ce6ef76a448158eb97222befa7c92293793435.png",
"width": null
}
],
"style": 2
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "文件对象的结构:"
}
}
]
}
},
{
"align": 0,
"para_type": 2,
"pic": {
"pics": [
{
"height": null,
"live_url": null,
"size": null,
"url": "https://i0.hdslb.com/bfs/new_dyn/752ce6ef76a448158eb97222befa7c92293793435.png",
"width": null
}
],
"style": 2
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "eg:"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "{\n "image": "glot/python:latest",\n "payload": {\n "language": "python",\n "files": [\n {\n "name": "main.py",\n "content": "print(42)"\n }\n ]\n }\n}",
"lang": "language-json"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "访问这个接口也需要在请求 Header 中携带 Token:"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "curl 'http://localhost:8088/run' \\\n -H 'X-Access-Token: some-secret-token' \\\n -H 'Content-type: application/json' \\\n -d '{\n "image": "glot/python:latest",\n "payload": {\n "language": "python",\n "files": [\n {\n "name": "main.py",\n "content": "print(42)"\n }\n ]\n }\n}'",
"lang": "language-bash"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "我们可以直接将它与自己熟悉的编程语言对接,实现给应用或者平台提供运行任意代码的能力。"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "这里使用 Python 通过 RestAPI 调用 glot(docker-run),实现运行一段 rust 代码并取回输出为字符串:"
}
}
]
}
},
{
"align": 0,
"code": {
"content": "import requests\n\ndef run_code(image, lang, file_name, code):\n resp = requests.post(\n url="http://localhost:8088/run",\n headers={\n "X-Access-Token": "some-secret-token",\n },\n json={\n "image": image,\n "payload": {\n "language": lang,\n "files": [\n {\n "name": file_name,\n "content": code,\n },\n ],\n },\n },\n )\n json_content = resp.json()\n return json_content\n\n\nimage = "glot/rust:latest"\nlang = "rust"\nfile_name = "main.rs"\ncode = """\nfn main() {\n for i in 1..=9 {\n for j in 1..=i {\n print!("{}x{}={:2} ", j, i, j * i);\n }\n println!();\n }\n}\n"""\n\nresult = run_code(image, lang, file_name, code)\nprint(result["stdout"])",
"lang": "language-python"
},
"para_type": 7
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "测试可以正确输出执行内容"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "\n"
}
}
]
}
},
{
"align": 0,
"para_type": 2,
"pic": {
"pics": [
{
"height": null,
"live_url": null,
"size": null,
"url": "https://i0.hdslb.com/bfs/new_dyn/21e396261fb607d4823f7ec4327908b1293793435.png",
"width": null
}
],
"style": 2
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "有了通用接口的能力,我们就有了将其集成进自己平台的可能,只要发挥创造力,就可以围绕在线执行代码提供相关的业务,或者作为微服务连接上游的业务,比如搭建 OJ(在线判题)平台等。以及 glot 项目以 MIT 协议开源,这意味着我们可以随意修改底层代码,比如增加网络和共享路径支持、增加第三方库等。总之,这是一个完成度很高、十分推荐的开源项目。"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "由 "
}
},
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"color": "#ff968d",
"font_size": 17,
"style": {},
"words": "来笙云 Laysense.cn"
}
},
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": " 强力支持"
}
}
]
}
},
{
"align": 0,
"para_type": 1,
"text": {
"nodes": [
{
"type": "TEXT_NODE_TYPE_WORD",
"word": {
"font_size": 17,
"style": {},
"words": "原文链接:https://shakaianee.top/archives/1002/"
}
}
]
}
}
]
},
"module_type": "MODULE_TYPE_CONTENT"
},
{
"module_extend": {
"items": [
{
"icon": null,
"jump_url": "//search.bilibili.com/all?keyword=%E8%BF%90%E7%BB%B4",
"text": "运维"
},
{
"icon": null,
"jump_url": "//search.bilibili.com/all?keyword=%E6%9C%8D%E5%8A%A1%E6%90%AD%E5%BB%BA",
"text": "服务搭建"
},
{
"icon": null,
"jump_url": "//search.bilibili.com/all?keyword=glot.io",
"text": "glot.io"
}
]
},
"module_type": "MODULE_TYPE_EXTEND"
},
{
"module_bottom": {
"share_info": {
"pic": "https://static.hdslb.com/mobile/img/app_logo.png",
"summary": "感谢 来笙云 Laysense.cn 提供算力 作为一个全栈工程师,开发、维护和测试一些软件系统时,必然会涉及到多种编程语言,有时还需要测试一些编程语言的安全特性,常常需要敏捷地了解它们并立即上手。在朋友的推荐和社区分享下,我了解到一个名叫 glot.io 的开源项目。 它支持40多种编程语言,无论是热门的 Python、Go、Rust、Kotlin,还是冷门的 COBOL、Erlang、Haskell 只需在网页上选择对应的语言,即可开始编写。为使用者提供了一个 Sandbox(沙箱)和 Playground(游乐场)环境,既不需要配置它们的 Runtime(运行环境)和 IDE(集成开发环境),也不需要担心误操作对系统产生破坏性,还不会占用任何用户端的系统资源,实现真正的零开销运行代码。 [图片] 在代码编写界面,可以创建多个源码文件,完成后点击Run就能执行它并得到输出,类似我们平时编程那样,将输出打在终端上。整个过程不会生成任何可执行文件,所以它的应用场景不是在线编译,而是在线运行代码片段。 [图片] glot.io 这个网站提供了公开的代码片段执行和分享功能,任何人在注册后都可以分享自",
"title": "【服务搭建】零开销在线运行代码!glot.io服务私有化部署"
}
},
"module_type": "MODULE_TYPE_BOTTOM"
},
{
"module_stat": {
"coin": {
"count": 1,
"forbidden": false,
"status": false
},
"comment": {
"count": 3,
"forbidden": false
},
"favorite": {
"count": 4,
"forbidden": false,
"status": false
},
"forward": {
"count": 0,
"forbidden": false
},
"like": {
"count": 17,
"forbidden": false,
"status": false
}
},
"module_type": "MODULE_TYPE_STAT"
}
],
"type": 1
}
},
"message": "0",
"ttl": 1
}