首页
/ Dokku docker-options 插件完全指南:在 build / deploy / run 阶段精细化定制容器选项

Dokku docker-options 插件完全指南:在 build / deploy / run 阶段精细化定制容器选项

2026-09-09 16:03:33作者:申梦珏Efrain

本文基于 Dokku 核心插件 docker-options(自 0.3.17 起提供)编写。该插件允许你在应用的**构建(build)、部署(deploy)、一次性运行(run)**三个不同阶段,为 Dokku 创建的容器传入自定义的 Docker 容器选项(如 --ulimit--shm-size--gpus--label 等),并可进一步按 Procfile 中的进程类型(process type)进行作用域限定。读完本文,你将掌握 docker-options 的命令体系、阶段与进程语义、引号与转义规则、报告输出格式,以及底层属性存储与升级迁移机制,能够为 Dokku 应用精确配置容器运行参数。

为什么需要 docker-options

Dokku 负责把应用从源码构建成镜像、部署为容器并管理其生命周期,但它并不会把 Docker 的全部能力暴露成 Dokku 命令。docker-options 插件正是为此设计的"透传通道":你把 Docker 语法写好的容器选项交给它,Dokku 会在创建容器时把它们原样拼接到 docker run 的参数中。

插件提供的命令一览:

docker-options:add [--process PROC...] <app> <phase(s)> OPTION    # 为应用在指定阶段添加 Docker 选项
docker-options:clear [--process PROC...] <app> [<phase(s)>...]    # 清空应用的 docker options
docker-options:list <app> [--process PROC] --phase PHASE          # 列出某一进程+阶段组合下的选项
docker-options:remove [--process PROC...] <app> <phase(s)> OPTION # 从应用的指定阶段移除 Docker 选项
docker-options:report [<app>] [<flag>] [--format json|stdout]     # 展示一个或多个应用的 docker options 报告

三个核心阶段:build、deploy、run

Dokku 在应用生命周期的多个"阶段"创建容器,docker-options 插件允许你为不同阶段分别配置参数,阶段由 docker-options:add 等命令的第二个位置参数(可逗号分隔多个)指定。

  • build(构建阶段):提供在构建过程中、各 builder 构建镜像时可用的容器选项。
    • 需要特别注意的是,某些 builder 可能会丢弃或忽略自身不支持的选项。例如 dockerfile builder 不支持挂载卷(mounted volumes)。这一过滤逻辑在源码中有明确体现:triggers.go 中的 emitFilteredOptions 会针对 dockerfilenixpacksrailpack 三类 image source 过滤掉 --link-v--volume 前缀的选项,而对 herokuish 则过滤 --file--build-args
  • deploy(部署阶段):作用于已部署的进程类型。覆盖应用 Procfile 中声明的每个进程类型以及应用默认部署的进程。
    • 对于运行中的容器而言,deploy 通常是你最应该使用的阶段。deploy 阶段的选项会在每次进程部署时通过 docker-args-process-deploy 触发机制注入,参见 triggers.go 中的 TriggerDockerArgsProcessDeploy
  • run(运行阶段):作用于 dokku rundokku run:detached 创建的一次性容器,以及 app.json 中声明的 cron 任务所创建的容器。

[!IMPORTANT] run 阶段并不docker rundocker container run 命令一一对应。在 run 阶段指定的容器选项只会被 run 插件与 cron 任务创建的容器使用。请务必根据自己的用例,把选项添加到正确的阶段。

此外,docker options 的增删不会影响任何已经运行的容器,只会作用于修改之后创建的容器。因此修改应用的 docker options 后,必须执行 dokku ps:rebuild 或重新部署才能生效。

从源码看,阶段集合被定义为固定的三个:availablePhases = []string{"build", "deploy", "run"}(见 internal-functions.go)。任何不属于这三个值的阶段参数都会在 parsePhases 中直接报错:Phase(s) must be one of [build deploy run]

支持的 Docker 选项范围

docker-options 支持的选项以 Docker 官方 docker run[OPTIONS] 部分为准。插件不会用它来修改容器运行的进程或命令,也就是说:

docker run [OPTIONS] [CONTAINER_COMMAND] [ARG...]

其中 [OPTIONS] 正是由 docker-options 插件拼接的部分,而 [CONTAINER_COMMAND][ARG] 是容器中启动的进程及其参数,它们来自 Dokku 的进程模型。若你想修改 Dockerfile 构建出的容器所运行的命令,请参考 Dockerfile builder 文档中自定义运行命令一节,或通过 Procfile 定义多进程 来实现。

调度器(Scheduler)支持差异

Docker options 使用 Docker 自身的词汇书写,在 docker-local 调度器下会被逐字原样传递给 docker run。而其他调度器只翻译自身运行时中有对应物的子集,忽略其余部分。

  • k3s 调度器会将其中的 --cap-add--cap-drop--privileged--sysctl 翻译为 Kubernetes 等价物。具体细节(包括"只能设置 namespaced sysctl"的限制)参见 k3s 调度器文档
  • 例如给应用设置非特权端口起始值:
dokku docker-options:add node-js-app deploy "--sysctl net.ipv4.ip_unprivileged_port_start=1024"

从源码实现看,docker-local 调度器通过 docker-args-* 系列触发机制消费这些选项:triggers.go 中的 TriggerDockerArgs 会原样回显 stdin,再追加默认作用域下该阶段的选项;而 TriggerDockerArgsProcessDeploy 则负责追加进程作用域的 deploy 选项。

挂载卷与宿主目录:优先使用 storage 插件

Docker 通过 -v / --volume 标志支持卷与宿主目录挂载。为了简化用法,Dokku 提供了 storage 插件作为持久化存储的抽象层。在大多数情况下,Dokku 项目推荐使用持久化存储插件,而不是直接在不同阶段操作 docker options。如何为应用挂载持久化存储,请参阅 持久化存储文档

命令实战

添加 Docker 选项(docker-options:add)

docker-options:add 接收:应用名、逗号分隔的阶段列表、以及要添加的 docker option。

给应用在 deploy 阶段添加 --ulimit nofile=12

dokku docker-options:add node-js-app deploy "--ulimit nofile=12"

同时指定多个阶段(用逗号分隔):

dokku docker-options:add node-js-app deploy,run "--ulimit nofile=12"

一次调用添加多个 docker 选项。每个 --flag [value] 组按 flag 边界被识别,为引号安全做 shell 分词,并作为独立条目存储,因此可以完整地通过 docker-options:reportdocker-options:list 往返:

dokku docker-options:add node-js-app deploy "--ulimit nofile=12" "--shm-size 256m"

这一行为对应源码中的 SplitOptionString(见 dockeroptions.go):它用 shell 解析器做字面量分词(literalFields),再通过 groupOptionTokens 按 flag 边界分组——--build-arg X=Y --link a 会被拆成 ["--build-arg" "X=Y"]["--link" "a"] 两个独立条目,每个条目单独存储。

引号、转义与 shell 展开语义

选项值会按原样存储并传递给容器。引号只控制一个值如何被拆分成单词——不会发生任何 shell 展开,因此 $(...)、反引号、$VAR 与 glob 通配符都会被当作字面量处理,而不是被 shell 解释。这正是 Traefik 路由规则这类值可以被原样应用的原因:

dokku docker-options:add node-js-app deploy '--label "traefik.http.routers.web.rule=Host(`node-js-app.example.com`) && PathPrefix(`/api`)"'

从源码看,dockeroptions.go 中的 literalFields 使用 mvdan.cc/sh/v3/syntax 解析器直接分词:引号界定单词并被剥离,但参数展开、命令替换等元字符被逐字保留;存储时 quoteShellArg 只对含 shell 特殊字符的 token 加单引号包裹,保证存储形式可读且能通过 eval set -- "$line" 完整往返。

[!WARNING] 0.38.25 之前添加的选项,在创建容器时会被 shell 展开。任何依赖 shell 展开($(...)、反引号或 $VAR)的选项,在升级后都会被当作字面字符串处理,必须以已解析的值重新添加:

dokku docker-options:remove node-js-app deploy "--group-add \$(getent group docker | cut -d: -f3)"
dokku docker-options:add node-js-app deploy "--group-add $(getent group docker | cut -d: -f3)"

关于 --process 的位置

一个放错位置的 --process PROC(即放在应用名之后而不是之前)会被当作子命令 flag 处理,而不是存储为 docker option。因此下面两种调用行为完全一致:

dokku docker-options:add --process web node-js-app deploy "--ulimit nofile=12" "--shm-size 256m"
dokku docker-options:add node-js-app deploy "--ulimit nofile=12" "--shm-size 256m" --process web

原因在于子命令使用 pflag 且设置了 SetInterspersed(false)(见 src/subcommands/subcommands.go):出现在应用名之后的 --process 会成为位置参数,被拼入 option 字符串后,SplitOptionString 会把它从选项内容中"提升"回进程列表,而不是作为 docker option 存储。

移除 Docker 选项(docker-options:remove)

docker-options:remove 接收:应用名、逗号分隔的阶段列表、要移除的 docker option。

dokku docker-options:remove node-js-app run "--ulimit nofile=12"

多阶段移除:

dokku docker-options:remove node-js-app deploy,run "--ulimit nofile=12"

一次调用移除多个选项(与 add 的分词规则一致):

dokku docker-options:remove node-js-app deploy "--ulimit nofile=12" "--shm-size 256m"

已存储的选项按 shell 单词匹配,而不是按精确字符串匹配,因此只要值与存储值等价即可,无需字节级一致。用一种引号方式存储的选项,可以用另一种引号方式移除:

dokku docker-options:add node-js-app deploy "--label 'com.example.owner=platform team'"
dokku docker-options:remove node-js-app deploy '--label "com.example.owner=platform team"'

这一"等价匹配"由 dockeroptions.go 中的 optionsEqual 实现:先做精确字符串相等短路,否则对两侧分别做 shell 字面量分词后逐词比较。

清空应用的 Docker 选项(docker-options:clear)

docker-options:clear 可移除应用的所有 docker options:

dokku docker-options:clear node-js-app
-----> Clearing docker-options for node-js-app on all phases

也可以指定一个或多个合法阶段,阶段用逗号分隔;指定非法阶段会报错:

dokku docker-options:clear node-js-app run
-----> Clearing docker-options for node-js-app on phase run
dokku docker-options:clear node-js-app build,run
-----> Clearing docker-options for node-js-app on phase build
-----> Clearing docker-options for node-js-app on phase run

查看 docker-options 报告(docker-options:report)

[!IMPORTANT] 自 0.8.1 起提供。

docker-options:report 可以查看应用的 docker options 状态。不带应用名时,输出所有应用的信息:

dokku docker-options:report
=====> node-js-app docker options information
       Docker options build:
       Docker options deploy: --ulimit nofile=12 --shm-size 256m
       Docker options run:  --ulimit nofile=12 --shm-size 256m
=====> python-sample docker options information
       Docker options build:
       Docker options deploy:
       Docker options run:
=====> ruby-sample docker options information
       Docker options build:
       Docker options deploy:
       Docker options run:

也可以针对单个应用:

dokku docker-options:report node-js-app
=====> node-js-app docker options information
       Docker options build:
       Docker options deploy: -v /var/log/node-js-app:/app/logs
       Docker options run:  -v /var/log/node-js-app:/app/logs

还可以传入 flag,只输出你关心的那部分信息:

dokku docker-options:report node-js-app --docker-options-build

当配置了进程级选项(见下文)时,报告会为每一个已配置的 process.deploy 组合额外暴露一个动态 flag,命名为 --docker-options-deploy.<process>

dokku docker-options:report node-js-app --docker-options-deploy.web

JSON 格式报告

通过 --format json 可获得机器可读的 JSON 视图:

dokku docker-options:report node-js-app --format json

JSON 报告包含既有的字符串键(builddeployrun,以及配置了进程时额外的 deploy.<process>),并为这些简写键提供并行的 -list 键。每个 -list 的值是 JSON 数组,数组元素对应 docker-options:add原始存储的每一条选项,这样导出工具可以无损往返包含空格的选项,而无需拆分旧式的空格拼接字符串。空阶段输出空数组([])。已弃用的 docker-options-* 前缀键保持不变,不增加 -list 同伴键。

{
  "build": "",
  "build-list": [],
  "deploy": "-v /logs:/logs --memory=512m",
  "deploy-list": ["-v /logs:/logs", "--memory=512m"],
  "run": "",
  "run-list": [],
  "deploy.web": "-p 8080:5000",
  "deploy.web-list": ["-p 8080:5000"],
  "docker-options-build": "",
  "docker-options-deploy": "-v /logs:/logs --memory=512m",
  "docker-options-run": "",
  "docker-options-deploy.web": "-p 8080:5000"
}

JSON 组装逻辑见 report.go 中的 buildJSONReportData:默认作用域的三个阶段都会生成 -list 数组,进程作用域的每个 deploy.<process> 同样有 -list 同伴。注意 --format json 不能与 info flag 同时指定,否则会报错。

列出某一进程+阶段的选项(docker-options:list)

docker-options:list 打印存储在单个进程+阶段组合下的选项,每行一条。省略 --process 时列出默认作用域:

dokku docker-options:list node-js-app --process web --phase deploy
dokku docker-options:list node-js-app --phase deploy

从源码看(CommandList,见 functions.go),--phase 是必填参数,且必须是 build/deploy/run 之一;当指定 --process 时,若阶段不是 deploy 会报错:--process is only supported for the deploy phase

进程级选项(Process-Specific Options)

[!IMPORTANT] 自 0.38.0 起提供。

docker options 可以通过一个或多个 --process flag 限定到应用 Procfile 中声明的特定进程类型。这在某个 deploy 阶段选项(例如端口映射)只适用于一种进程类型、却会与其他进程冲突时非常有用——典型场景是 web 进程需要发布 -p 6789:5000,而 worker 进程绝不能绑定该端口。

作用域规则

  • 进程作用域仅支持 deploy 阶段build 阶段每个应用只运行一次,run 阶段面向临时命令与 cron 任务,两者都没有 Procfile 进程类型的概念,因此都会拒绝 --process
  • 没有 --global flag。省略 --process 保持历史行为:选项作用于应用中的每一个容器。刻意不设 --global 是有意为之:在 Dokku 其他位置,--global 表示"跨所有应用"(如 dokku config:set --global),在这个永远只作用于单个应用的插件里会造成误导。
  • 进程作用域的约束在源码 internal-functions.goValidateProcessFlag 中强制校验:processScopedPhases 仅包含 deploy,且 _default_ 作为保留值不可传给 --process

设置进程级选项

# 只给 web 进程添加端口映射
dokku docker-options:add --process web node-js-app deploy "-p 6789:5000"

# 只给 worker 进程添加 GPU 挂载
dokku docker-options:add --process worker node-js-app deploy "--gpus all"

多个 --process flag 可以组合,在一次调用中把同一选项应用到多个进程类型:

dokku docker-options:add --process web --process api node-js-app deploy "-v /shared:/shared"

如果 --process 指定的进程类型当前不在应用的 Procfile 中,命令仍会成功,但会输出一条警告(WarnIfProcessNotInProcfile,见 internal-functions.go)。这允许你在一次会新增该进程类型的部署之前,提前配置好选项。

_default_ 值是内部保留值,不能传给 --process

移除与清空进程级选项

# 从单个进程移除单个选项
dokku docker-options:remove --process web node-js-app deploy "-p 6789:5000"

# 清空某个进程+阶段的全部选项
dokku docker-options:clear --process worker node-js-app deploy

不带 --process 时,:remove:clear 只作用于默认作用域——进程级列表不会被触碰。

进程+阶段组合的存储模型

从源码看,每个选项条目存储在形如 <processType>.<phase> 的属性键下(propertyKey,见 dockeroptions.go),例如 web.deploy_default_.build。默认作用域使用保留键 _default_DefaultProcessType 常量),docker-options:report 把它渲染成固定的 build/deploy/run 键,进程级配置则动态生成 deploy.<process> 键。应用被克隆或重命名时,这些属性会通过 TriggerPostAppCloneSetup / TriggerPostAppRenameSetuptriggers.go)随应用一起复制或迁移。

内部属性与升级迁移机制

以下属性由 docker-options 插件内部记录,不会通过 docker-options:report 暴露:

属性 作用域 说明 源码位置
migrated-from-files 全局 全局迁移哨兵,记录旧的 DOCKER_OPTIONS_<PHASE> 扁平文件存储已排空进插件属性 functions.go 在安装期迁移运行后写入 "true"
migrated-build 每应用 记录应用的旧 DOCKER_OPTIONS_BUILD 文件已排空进 _default_.build 属性列表。仅当旧文件包含非空内容时设置 functions.go 在每个阶段排空后写入 "true"
migrated-deploy 每应用 记录旧 DOCKER_OPTIONS_DEPLOY 文件已排空进 _default_.deploy 属性列表。仅当旧文件包含非空内容时设置 functions.go 在每个阶段排空后写入 "true"
migrated-run 每应用 记录旧 DOCKER_OPTIONS_RUN 文件已排空进 _default_.run 属性列表。仅当旧文件包含非空内容时设置 functions.go 在每个阶段排空后写入 "true"
migrated-traefik-backticks 全局 全局哨兵,记录存储的 Traefik label 中带多余反斜杠的反引号已被修复 functions.go 安装期修复运行后写入 "true"
migrated-canonical-options 全局 全局哨兵,记录存储的选项已被重写为规范形式:为旧扁平文件排空时未加引号的 shell 元字符值补上引号,并把携带多个 flag 的条目拆分 functions.go 安装期重写运行后写入 "true"

这些迁移体现了插件的演进路径:早期版本把选项存为每个应用目录下的 DOCKER_OPTIONS_<PHASE> 扁平文件,后来迁移为 Dokku 的属性(property)存储,并附带多层幂等保护(每阶段全局哨兵 + 每应用哨兵)。安装触发(TriggerInstall,见 triggers.go)会依次执行:属性目录初始化 → 旧文件迁移 → Traefik label 反引号修复 → 规范化重写。此外,升级周期还会把上一版本遗留的 .migrated 文件哨兵转换为新的每阶段属性(convertLegacyMigratedMarker)。

最佳实践小结

  1. 运行容器用 deploy,一次性命令用 run,构建期才用 build,并且要意识到 builder 可能忽略不支持的选项(如 dockerfile builder 不支持挂载卷)。
  2. 卷挂载优先用 storage 插件,而不是直接操作 docker options。
  3. 记住修改后必须 dokku ps:rebuild 或重新部署,docker options 不会作用于已运行的容器。
  4. 多进程应用利用 --process 做作用域隔离(如 web 发布端口、worker 挂载 GPU),但要注意进程作用域只在 deploy 阶段合法。
  5. 选项值是字面量,不做 shell 展开——依赖 $(...) 等展开的旧配置(0.38.25 之前)升级后需以已解析的值重新添加。
  6. 导出备份时优先用 --format json-list,它能保留每条选项的原始边界,避免空格拼接带来的往返失真。
登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
docsdocs
暂无描述
Markdown
899
5.83 K
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
925
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
601
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
395
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.04 K
525