docker compose alpha generate 详解:从已有容器反向生成 Compose 文件的实验性命令
docker compose alpha generate 是 docker/compose 提供的一个实验性(EXPERIMENTAL)子命令,它的核心能力是"逆向工程":把一台主机上已经存在的 Docker 容器(包括已停止的)作为输入,反向生成一份标准 Compose 项目模型,并以 YAML 或 JSON 形式打印到标准输出。读完本文,你将理解该命令的完整参数、它对容器配置的实际提取范围(镜像、环境变量、健康检查、端口、卷、网络、secrets)、服务命名与副本(Scale)推断规则,以及它在"遗留应用迁移到 Compose"这一场景下的落地方式。
命令定位与实验性状态
generate 并不挂在 docker compose 的主命令树顶层,而是注册在隐藏的 alpha 实验性命令组下。从 alpha 命令组定义 可以看到,alphaCommand 被标记为 experimentalCLI 且 Hidden: true,其下仅挂接了 viz、publish、generate 三个子命令:
cmd.AddCommand(
vizCommand(p, dockerCli, backendOptions),
publishCommand(p, dockerCli, backendOptions),
generateCommand(p, dockerCli, backendOptions),
)
因此调用入口是 docker compose alpha generate [OPTIONS] [CONTAINERS...]。由于属于 alpha 命令,命令入口 在执行时会先向 stderr 打印一条提示:
generate command is EXPERIMENTAL
这意味着它的接口与行为可能随版本变化,生产流水线中建议先验证输出再使用。
基本用法
命令要求至少指定一个容器作为输入参数(可以是容器名,也可以是容器 ID):
# 为单个容器生成 Compose 文件
docker compose alpha generate my-app
# 同时纳入多个容器
docker compose alpha generate my-app redis
# 指定项目名并输出 JSON
docker compose alpha generate --name my-stack --format json my-app redis
runGenerate 的入口逻辑很直接:容器列表为空时直接返回 at least one container must be specified 错误;否则构建 Compose 后端服务,调用 backend.Generate,最后根据 --format 将得到的项目模型序列化为 project.MarshalJSON() 或 project.MarshalYAML() 并打印到 stdout。输出只走标准输出,因此可以方便地重定向或管道:
docker compose alpha generate my-app > compose.generated.yaml
完整参数说明
根据 官方参考文档 与 cobra 命令定义,该命令的完整参数如下:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
--dry-run |
bool |
false |
以 dry run 模式执行命令(全局持久标志,定义于 compose.go) |
--format |
string |
yaml |
输出格式,取值 yaml 或 json;其他取值会在 格式分支 中触发 unsupported format %q 错误 |
--name |
string |
空 | 写入生成 Compose 文件的项目名(name 字段) |
--project-dir |
string |
空 | 项目使用的目录(Compose 全局项目选项之一) |
其中 --dry-run 与 --project-dir 是 docker compose 根命令上声明的持久标志,被 alpha generate 继承;--name 和 --format 则是 generateOptions 自己声明的专属参数。--name 最终会进入 GenerateOptions 的 ProjectName 字段:
type GenerateOptions struct {
// ProjectName to set in the Compose file
ProjectName string
// Containers passed in the command line to be used as reference for service definition
Containers []string
}
实现原理:容器如何变成 Compose 模型
整个"反向生成"逻辑集中在 pkg/compose/generate.go,可以分为容器收集、服务归并、配置抽取三个阶段。
1. 容器收集:按名称与 ID 双重过滤
Generate 会发起两次 ContainerList 请求:
- 第一次按
name过滤,匹配用户传入的容器名; - 第二次按
id过滤,允许用户直接传入容器 ID(或 ID 前缀)。
两次请求都设置了 All: true,即已停止的容器同样可以参与生成。两次结果按 ID 去重合并后,如果最终一个容器都没找到,则报错 no container(s) found with the following name(s): ...。
2. 服务命名与副本数推断
createProjectFromContainers 决定每个容器映射到哪个 Compose 服务:
- 如果容器带有
com.docker.compose.service标签(ServiceLabel),说明它本身就是由某个 Compose 应用创建的,此时直接复用该历史服务名,实现"同一 Compose 应用多次部署后仍能还原出一致的服务定义"; - 否则回退到
getCanonicalContainerName对容器名做规范化,作为新服务名; - 凡是归到同一服务名的容器,其
Scale计数都会累加(service.Scale = increment(service.Scale))。换句话说,如果你手工起了 3 个同名前缀的副本容器,生成的 Compose 文件会自动体现scale: 3的语义。
每个服务初始只写入 Name、Image(容器当前镜像引用)和 Labels,其余字段在随后的 inspect 阶段补充。
3. 配置抽取:实际能恢复哪些字段
对每个容器执行 ContainerInspect 后,extractComposeConfiguration 负责把引擎侧的容器配置翻译成 Compose 模型:
| Compose 字段 | 数据来源 | 说明 |
|---|---|---|
environment |
inspect.Config.Env |
通过 types.NewMappingWithEquals 转换为 key/value 映射 |
healthcheck |
inspect.Config.Healthcheck |
逐项映射 test、timeout、interval、start_period、start_interval、retries(见 toComposeHealthCheck),零值项会被省略 |
ports |
inspect.HostConfig.PortBindings |
生成 target/published/protocol/host_ip 形式的短语法端口映射 |
volumes |
inspect.Mounts |
区分命名卷与 bind mount,详见下文 |
networks |
inspect.NetworkSettings.Networks |
记录网络别名(aliases),并 inspect 网络本身以恢复 internal 标记 |
卷与 secrets 的识别由 toComposeVolumes 完成,规则值得注意:
mount.TypeVolume(命名卷):写入顶层volumes定义;只有当驱动不是local时才显式声明driver,local驱动保持模型简洁;mount.TypeBind(bind mount):直接映射为 Compose 的 bind 挂载;- 特殊场景:如果 bind 挂载的目标路径以
/run/secrets开头,会被识别为 Compose secret——secret 名取目标路径的最后一个元素,file字段取挂载源路径(并剥掉/host_mnt前缀),从而把通过 docker secret 机制注入的文件恢复为secrets声明。
网络由 toComposeNetwork 处理:对容器连接的每个网络调用 NetworkInspect,若能 inspect 成功则记录 internal: true 标记;同时把容器在该网络上的 aliases 写入服务的 networks.<name>.aliases。
标签清洗:生成的服务标签会经过 cleanDockerPreviousLabels 过滤,剔除所有 com.docker.compose. 前缀和 desktop.docker.io 前缀的标签。这样做的目的是避免把旧 Compose 部署留下的状态标签(旧服务名、项目名等)重新写回新生成的 Compose 文件,造成二次部署时的命名冲突。
生成结果的形态
综合以上逻辑,输出是一个完整的 Compose 项目模型(types.Project),包含 name(当指定 --name 时)、services、volumes、networks、secrets 四大块。以同时生成一个带命名卷、端口映射的 web 容器和一个带网络别名的 app 容器为例,yaml 输出在结构上类似:
name: my-stack
services:
web:
image: <容器当前镜像>
ports:
- target: 80
published: "8080"
protocol: tcp
volumes:
- type: volume
source: web_data
target: /data
app:
image: <容器当前镜像>
networks:
backend:
aliases:
- app-1
networks:
backend:
volumes:
web_data:
(以上为基于源码抽取逻辑整理的输出结构示例,实际字段以真实容器状态为准。)切换到 --format json 时,同样的模型会以 JSON 形式打印,便于程序化处理。
适用场景与能力边界
典型场景:接管遗留系统。当一台服务器上存在一批"只有容器、没有 Compose 文件"的历史应用时(早期用裸 docker run 部署、或旧 Compose 文件已丢失),alpha generate 可以快速产出一份可审查、可版本化的基线,再人工补全 build、depends_on、启动命令等字段后,即可用 docker compose up 重新纳管。
需要留意的边界(从源码结构看):
- extractComposeConfiguration 只覆盖环境变量、健康检查、挂载、网络、端口绑定这几类字段,不会恢复容器的启动命令、entrypoint、
depends_on、重启策略、资源限制等未列入抽取范围的配置,生成结果应视为"骨架"而非"完整还原"; - 镜像字段取自容器当前的
Image引用,若容器由本地构建镜像启动且标签为<none>或未打 tag,生成文件中会出现无法拉取的引用,需要人工改为build定义; - 输入容器不存在时命令会快速失败,且必须显式给出容器列表,不支持"导出全部容器";
- 命令输出到 stdout 且带有
EXPERIMENTAL提示写到 stderr,脚本化使用时注意分离两个流。
小结
docker compose alpha generate 以极小的参数面(--name、--format,外加继承的 --dry-run、--project-dir)提供了一条从"容器实例"回到"声明式配置"的逆向通道:名称/ID 双路收集容器、按 Compose 服务标签或规范名归并服务并推断副本数、逐项抽取镜像/环境/健康检查/端口/卷/网络/secrets、清洗历史标签后输出 YAML 或 JSON。理解 cmd/compose/generate.go 的命令层与 pkg/compose/generate.go 的实现层这两处源码,就能准确判断它在你的迁移流程中"能给出什么、缺什么需要人工补",是遗留 Docker 应用 Compose 化改造的实用起点。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00