## 获取图文详细信息 > 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[] | 模块信息 | 参见 [功能模块](features.md) | | 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 | | | **示例:** ```shell 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' ```
查看响应示例: ```json { "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 } ```