news 2026/10/10 6:07:33

Deis v1 Slug Runner 实战指南:在 Docker 容器中运行 Heroku 风格应用 Slug

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Deis v1 Slug Runner 实战指南:在 Docker 容器中运行 Heroku 风格应用 Slug
  • 后端
  • 云原生

【免费下载链接】deis

Deis v1, the CoreOS and Docker PaaS: Your PaaS. Your Rules.

项目地址:https://gitcode.com/gh_mirrors/de/deis
点击查看免费下载

Slug Runner 是 Deis v1(基于 CoreOS 与 Docker 的 PaaS)构建链路中的核心执行组件:它以 Docker 容器形态接收由 Slug Builder 编译出的 gzipped 应用 tarball(slug),并在应用环境中启动任意命令、交互式 Shell 或 Procfile 中定义的进程类型。读完本文你将掌握 slug 的三种装载方式(stdin、SLUG_URL、绑定挂载)、start命令与默认进程类型的解析机制、profile.d 环境注入、基于 sdutil 的服务发现配置,以及它在 Deis 整体 git push 部署流程中的真实调用位置。

Slug 与 Slug Runner 的定位

在 Heroku 风格的部署模型中,应用源码并不直接在服务器上运行,而是先被"编译"为一个称为slug的产物——一个包含已安装依赖、预编译产物与运行配置的 gzipped tarball。Deis 的 Builder 组件中同时存放着两个配套工具(见 builder/rootfs/usr/local/src/ 目录):

  • slugbuilder:把应用源码 tarball 通过官方及第三方 Heroku buildpack 编译成 slug.tgz;
  • slugrunner:把编译好的 slug 解压到容器内应用目录,并代为执行用户指定的命令或进程。

Slug Runner 官方定位是"运行由 slugbuilder 产生的 Heroku 风格 slug 的 Docker 容器"。它做的事情非常聚焦:通过 stdin 或 URL 接收一个 gzipped tarball,让你能够在应用环境中运行一条命令,或启动应用 Procfile 中定义的进程。

获取 Slug Runner 镜像

使用前需要先安装 Docker。有两种获取方式:

方式一:直接拉取公共镜像

$ docker pull flynn/slugrunner

方式二:从源码构建

$ cd slugrunner $ make

仓库中的 Makefile 揭示了构建过程的细节:它先通过git clone拉取sdutil工具源码并用godep go build编译出build/sdutil二进制(这是服务发现功能所依赖的可执行文件),随后执行docker build -t flynn/slugrunner .构建镜像。也就是说,make产出的镜像自带 sdutil,开箱即可支持下文的服务发现特性。

在 Deis 的 Builder 容器内部,slugrunner 的源码目录会被注册为可构建标签,相关路由定义见 builder/routes.go,其中/usr/local/src/slugrunner/目录对应deis/slugrunner镜像标签。

运行容器:三种装载 Slug 的方式

Slug Runner 的入口脚本是 runner/init(由 Dockerfile 的ENTRYPOINT ["/runner/init"]指定)。脚本启动后会按以下优先级加载应用 slug:

  1. 绑定挂载优先:如果/app(应用主目录)下已有内容(例如通过docker run -v挂载或 ONBUILD 注入),则直接使用;
  2. SLUG_URL 次之:通过curl -s "$SLUG_URL" | tar -xzC $HOME下载并解压,随后unset SLUG_URL防止变量泄漏到应用环境;
  3. stdin 兜底:cat | tar -xzC $HOME,从标准输入流式解压。

方式一:stdin 管道传入 slug

把本地myslug.tgz通过管道传给容器,并执行应用内的 Rake 任务(输出附加到 stdout):

$ cat myslug.tgz | docker run -i -a stdin -a stdout flynn/slugrunner rake mytask

-i -a stdin保证 stdin 保持开启且被附加,slug 二进制流才能被runner/init的cat正确读取。

方式二:SLUG_URL 环境变量加载

通过 URL 加载 slug 是目前唯一能交互式运行的方式,例如启动 Bash:

$ docker run -e SLUG_URL=http://example.com/slug.tgz -i -t flynn/slugrunner /bin/bash

-i -t分配伪终端。脚本内部unset SLUG_URL之后,应用环境里不会再残留该变量。

方式三:结合 ONBUILD 的镜像化 slug

Dockerfile 末尾定义了三条 ONBUILD 指令:

ONBUILD RUN mkdir -p /app ONBUILD WORKDIR /app ONBUILD ADD slug.tgz /app

这意味着你可以构建一个"把 slug.tgz 直接打进镜像"的派生镜像——这正是 Deis 在 builder/rootfs/etc/confd/templates/builder 中的做法:当应用仓库没有 Dockerfile 时,Builder 先用 slugbuilder 编译出 slug,再生成一个仅含FROM deis/slugrunner的 Dockerfile,最终docker build时 slug.tgz 通过 ONBUILD 被注入/app。此时 slugrunner 走的是第一种"绑定挂载/预置内容"分支,无需 stdin 或 URL。

命令执行环境:不只是解压那么简单

README 明确说明:命令在应用环境中执行、工作目录是应用根目录、带有默认环境变量,并且会 source 应用.profile.d目录下的脚本。runner/init脚本具体实现了这套环境准备逻辑:

export HOME=/app mkdir -p $HOME ... ## Load profile.d and release config shopt -s nullglob mkdir -p .profile.d # If a file is created in slugbuilder with the wrong UID, change it. find . -user 1000 -exec chown slug:slug {} \; if [[ -s .release ]]; then ruby -e "require 'yaml';(YAML.load_file('.release')['config_vars'] || {}).each{|k,v| puts \"#{k}='#{v}'\"}" > .profile.d/config_vars fi for file in .profile.d/*; do source $file done hash -r

关键点如下:

  • 用户与权限修复:slug 是由 slugbuilder 以 UID 1000 的用户编译的,而容器内应用用户是slug(UID 2000,见 Dockerfile)。脚本会把所有属主为 1000 的文件改归slug:slug,但不动 UID 0(root)拥有的文件,避免破坏系统文件权限。
  • .release 配置变量注入:如果 slug 根目录存在.release文件(slugbuilder 编译时由 buildpack 的/bin/release脚本生成),其中的config_vars会被 Ruby 解析后写入.profile.d/config_vars,随后与其他 profile 脚本一起被source,从而成为进程的默认环境变量。
  • profile.d 脚本顺序执行:所有.profile.d/*脚本按字典序逐个 source,这使 buildpack 可以为应用注入 PATH、语言运行时版本等默认环境。
  • hash -r:清空 shell 命令哈希表,确保新加入 PATH 的二进制(如 ruby、rake)能被正确找到。

start 命令:按 Procfile 启动进程

Slug Runner 内置一个start子命令,用于启动应用 Procfile 中定义的进程类型,或 buildpack 提供的默认进程类型:

$ cat myslug.tgz | docker run -i -a stdin -a stdout -a stderr flynn/slugrunner start web

runner/init中start的解析逻辑是:

case "$1" in start) if [[ -f Procfile ]]; then command="$(ruby -e "require 'yaml';puts YAML.load_file('Procfile')['$2']")" else command="$(ruby -e "require 'yaml';puts (YAML.load_file('.release')['default_process_types'] || {})['$2']")" fi ;; *) command="$@" ;; esac
  • 若应用根目录存在Procfile(YAML 格式),则直接读取其中对应进程类型的命令;
  • 若没有 Procfile,则回退到.release文件中的default_process_types(由 buildpack 声明,是 Heroku 官方一度非正式弃用、但 Deis 仍兼容的默认进程类型来源);
  • 其他任何参数则原样作为 shell 命令执行。

Deis 的 Builder 在构建完成后也会做同样的判断:优先读取应用 Procfile,否则从slug.tgz内提取./Procfile或./.release中的进程类型(见 builder/rootfs/etc/confd/templates/builder),并将结果作为 build 钩子的PROCFILE数据上报给 controller,以便调度器按进程类型启动容器。默认的web进程类型会由调度器(如 controller/scheduler/fleet.py)实际拉起。

服务发现:通过 sdutil 注册

Slug Runner 支持基于go-discover的服务发现,实际执行时通过sdutil exec包装用户命令。runner/init中的相关逻辑如下:

if [[ $SD_NAME && $PORT ]]; then if [[ $SD_HOST ]]; then runner="sdutil exec -h $SD_HOST -s $SD_NAME:$PORT bash -c" unset SD_HOST else runner="sdutil exec -s $SD_NAME:$PORT bash -c" fi unset SD_NAME elif [[ $SD_ARGS ]]; then runner="sdutil $SD_ARGS bash -c" unset SD_ARGS else runner="bash -c" fi exec $runner "$command"

三种模式的优先级与行为:

环境变量行为
SD_NAME+PORT命令通过sdutil exec -s $SD_NAME:$PORT bash -c ...运行,向服务发现注册$SD_NAME:$PORT;SD_NAME在执行前被 unset(避免递归注册),PORT保留,因为应用常在不使用服务发现时也读取它
上述两者再加SD_HOST追加-h $SD_HOST指定服务发现的后端主机地址,随后SD_HOST被 unset
SD_ARGS完全自定义 sdutil 命令行:sdutil $SD_ARGS bash -c ...,随后SD_ARGS被 unset
均未设置退化为普通bash -c,不涉及服务发现

注意这里最终通过exec替换当前 shell 进程,保证应用进程成为容器的 PID 1 进程,信号与日志处理语义与直接运行一致。

基础镜像环境

镜像基于 Heroku 官方Cedar镜像(FROM heroku/cedar:14),这是 Heroku 经典运行环境,内置了 ruby、python、node 等语言运行时,与 buildpack 编译出的 slug 天然兼容。Dockerfile 中的其他关键设置:

  • 创建slug系统用户(UID/GID 2000),主目录为/app;USER slug使容器内所有进程以非 root 身份运行;
  • 默认暴露端口:ENV PORT 5000+EXPOSE 5000,应用可通过$PORT环境变量感知监听端口(可在运行容器时覆盖);
  • WORKDIR /app、ENV HOME /app与runner/init中的export HOME=/app保持一致;
  • ENV DEIS_RELEASE 1.13.4标记了当前 Deis 版本。

在 Deis v1 中的完整调用链

把以上内容串起来,一次git push deis master触发部署时,Slug Runner 的完整生命周期是:

  1. Builder 的 git receive-pack 钩子(builder/rootfs/etc/confd/templates/builder)接收到代码后,若无 Dockerfile,则以deis/slugbuilder运行编译容器,把$TMP_DIR:/tmp/app与$CACHE_DIR:/tmp/cache:rw挂载进去;
  2. slugbuilder 依据 buildpacks 把源码编译成/tmp/slug.tgz,Builder 通过docker cp把它取回应用目录;
  3. Builder 写入FROM deis/slugrunner的 Dockerfile 并追加ENV GIT_SHA ...,docker build时触发 ONBUILD 将slug.tgz注入/app;
  4. 镜像被打上HOST:PORT/app:git-xxxx标签推送到私有 registry(见 push-images 模板 中deis/slugrunner:latest的推送逻辑);
  5. 之后调度器(fleet)在集群节点上用该镜像启动应用容器,容器入口/runner/init检测到/app已预置内容,直接跳过 stdin/URL 分支,source 完 profile.d 后执行start <process-type>或调度器注入的命令。

小结

Slug Runner 的职责虽小,却是 Deis v1"buildpack 式部署"模式的最后一环:它把 buildpack 生态(Procfile、.release、.profile.d、slug 格式)与 Docker 运行时无缝衔接,并以环境变量方式原生支持服务发现,是整个 git push 部署链路从"编译"到"运行"的收尾组件。其核心实现集中在 runner/init(约 76 行 Bash),配合 Dockerfile 阅读即可完整掌握其行为。项目采用 BSD 许可,源码目录同时附带 LICENSE 文件可供查阅。

  • 后端
  • 云原生

【免费下载链接】deis

Deis v1, the CoreOS and Docker PaaS: Your PaaS. Your Rules.

项目地址:https://gitcode.com/gh_mirrors/de/deis
点击查看免费下载
上一篇:Flint 溢出处理机制深度解析:200个类目的图表如何依然可读(过滤策略与警告系统)
下一篇:xmpp4cj调试技巧:3种调试器+报文拦截器,10分钟掌握XMPP通信观测方法

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/10 6:06:42

蓝桥杯选素数题解:质因数分解与反向推导的妙用

第一次看到 P8795《选素数》这个题&#xff0c;我不由自主地先去找素数判断模板——结果发现这是 2022 年蓝桥杯国赛 A 组的第一道编程题&#xff0c;难度定位在“普及”&#xff0c;考的根本不是判断素数&#xff0c;而是质因数分解、反向推导&#xff0c;外加一个让不少人误会…

作者头像 李华
网站建设 2026/10/10 6:06:34

元数据驱动数据安全策略:网约车平台实战解析

干大数据平台的人&#xff0c;对“元数据管理”这个词应该不陌生。但说实话&#xff0c;很长一段时间里&#xff0c;我都觉得它不就是一份表结构说明&#xff0c;建数仓的时候顺手维护一下而已&#xff0c;优先级排得很靠后。真正让我转变想法的&#xff0c;是后来负责的一次数…

作者头像 李华
网站建设 2026/10/10 6:06:33

Wireshark Lua插件开发:解析自定义UDP协议实战指南

简介&#xff1a;本资源是一份面向网络协议开发与测试工程师、Wireshark高级使用者的技术实践文档&#xff0c;聚焦解决自定义私有协议在Wireshark中无法解析的典型痛点。文档以基于UDP的员工信息查询服务&#xff08;QueryRequest/QueryResponse&#xff09;为真实案例&#x…

作者头像 李华
网站建设 2026/10/10 6:06:32

智能汽车网络安全标准:计算平台、可信计算与隔离架构工程拆解

简介&#xff1a;这份PPT资料聚焦智能汽车网络安全标准与技术&#xff0c;面向汽车电子、车载软件及信息安全方向的工程师与研究人员&#xff0c;帮助读者系统理解智能网联汽车在安全与功能安全层面的标准框架与落地实践。内容围绕关键零部件计算平台、可信计算、基于隔离的体系…

作者头像 李华
网站建设 2026/10/10 6:05:37

多台PS5统一管理实战:从系统版本、SSD扩容到存档同步

1. 先说清楚&#xff1a;这个"AnyPS5"到底是什么如果你打开我的备忘录&#xff0c;会看到一份命名为"AnyPS5"的文件夹。里面没有一行代码&#xff0c;也没有任何高深的配置文件&#xff0c;有的只是三张表格、一套检查清单&#xff0c;以及一篇我手打的排障…

作者头像 李华
网站建设 2026/10/10 6:04:22

【单片机课设毕设项目】基于单片机的室内环境五项指标同步采集可视化远程监控系统设计 基于单片机的居室空气污染与烟雾隐患无线监测智能预警装置设计(030110)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于嵌入式单片机&#xff0c;Java、小程序技术领域和毕业项目实战 ✌️…

作者头像 李华