docker run 转 docker-compose,复盘拆出 12 个坑
需求听起来简单到不值一提输入一条docker run命令输出等价的docker-compose.yml。字符串进字符串出没有网络请求没有状态。我给自己排了 30 分钟。最后花了一整天。这篇文章把过程中拆出来的 12 个坑全部摊开——包括一个写这篇文章时复查代码才抓出来的真 bug第 7 坑60 进制那个。完整实现 300 行左右已开源成单文件工具文末有链接全部代码都能对着看。第一段流水线分词split( )活不过第一个测试用例最直觉的写法一行搞定var tokens cmd.split( );然后第一个真实命令就把它打穿了docker run -e MSGhello world \ --name web nginx两个问题引号里的空格不能切行尾的\续行符要当空格处理。正则也不好使——引号可以是单引号也可以是双引号还能出现在参数中间--envAb c。老老实实写状态机核心就 12 行function tokenize(cmd){ cmd String(cmd||).replace(/\\\r?\n/g, ).trim(); // 坑1先吃掉续行符 var out[], cur, qnull; for(var i0;icmd.length;i){ var ccmd[i]; if(q){ if(cq) qnull; else curc; } // 引号内只认配对引号 else if(c||c) qc; // 引号外进入引号态 else if(/\s/.test(c)){ if(cur){out.push(cur);cur;} } else curc; } if(cur) out.push(cur); return out; }一个q变量记住当前在哪种引号里出来的 token 已经自动脱掉引号。这是整个转换器的地基它错一个字符后面全错。第二段流水线参数解析docker 的 flag 有三副面孔同一个环境变量用户可能写成三种形态docker run -e Ab img # 短选项 空格 docker run --env Ab img # 长选项 空格 docker run --envAb img # 长选项 等号第三种最阴险--envAb里有两个只能切第一刀坑 2var keya, valnull, eqa.indexOf(); if(a.slice(0,2)-- eq0){ keya.slice(0,eq); vala.slice(eq1); }接着是坑 3-d后面不跟值-p后面必须跟一个值。你不查表就没法知道下一个 token 是「当前 flag 的值」还是「下一个 flag」。没有捷径把 docker run 的参数表抄成两个白名单var FLAG_ARG {-p:1,--publish:1,-v:1,--volume:1,-e:1,--env:1, --name:1,--restart:1,--network:1, /* ...30 个 */}; var FLAG_BOOL{-d:1,--detach:1,--rm:1,--privileged:1, -t:1,--tty:1,-i:1,--interactive:1, /* ... */};坑 4是分界线问题docker run -w /app node:20 npm start里npm start不是参数是容器启动命令。规则是遇到第一个不以-开头且不是某个 flag 的值的 token它就是镜像名镜像名之后的一切原样进command哪怕它长得像 flagif(o.image){ o.command.push(a); i; continue; } // 镜像名之后全是 command if(a[0]!-){ o.imagea; i; continue; } // 第一个裸 token镜像名docker run img --rm里的--rm是传给容器的参数不是 docker 的——这条规则保证了语义正确。语义翻译有些参数在 compose 世界里根本不存在坑 5-d和--rm没有对应物。compose 服务天生就是后台常驻的-d直接丢弃--rm的「退出即删」语义靠docker compose down实现也丢弃。丢弃是对的但要静默丢弃不能报错——用户的命令没有错。坑 6--network mynet要写两处。服务里声明加入网络顶层还得声明这个网络是外部已存在的漏掉第二处docker compose up直接报错services: web: networks: - mynet networks: # 这一段最容易忘 mynet: external: true坑 10资源限制有版本裂缝。--memory 512m在 compose v2 语法里是mem_limit在 v3 Swarm 里是deploy.resources.limits。本地开发场景docker compose up对mem_limit的支持最直接选它——但选择本身就是坑你得知道自己在哪条兼容线上。第三段流水线YAML 输出看起来最简单坑最深坑 7本文最值钱的一个YAML 1.1 的 60 进制陷阱。写这篇文章时我复查yq()引号函数突然意识到一个问题ports: - 53:53不带引号的53:53会被 YAML 1.1 解析器读成60 进制整数 323353×6053。你想映射 DNS 端口实际得到一个叫3233的东西。只要冒号两边都是 ≤59 的纯数字就会中招22:22SSH、25:25SMTP全在雷区。而我的yq()白名单里恰好放行了冒号——意味着端口全部裸奔。修复端口一律强制加引号其他字段维持白名单策略function yqq(s){ // 强制引号版专供 ports return String(s).replace(/\\/g,\\\\).replace(//g,\\) ; } list(ports, o.ports, true); // forcetrue → 走 yqq顺手加了回归断言让这个坑永远不会复活ok(yaml sexagesimal guard, A.toCompose(docker run -p 53:53 img).indexOf(- 53:53) 0);修复的 commit 已推送。这是「写文章」这件事直接改进了代码的一次实证——把实现讲给别人听的过程就是最严格的 code review。坑 8是引号的整体策略全部加引号最安全但产物很丑全部不加则Ab c、x!y这类值会炸。折中安全字符白名单字母数字._/:-放行其余加引号并转义反斜杠和双引号。坑 9用户没写--name时服务名从哪来从镜像名剥去 tag、去 registry 路径、洗掉 YAML 不认的字符全空则兜底appvar svc o.name || String(o.image).split(:)[0].split(/).pop() .replace(/[^A-Za-z0-9_-]/g,) || app; // registry.example.com/team/api-server:v2 → api-server收尾的两个工程决策坑 11未知参数怎么办docker run 的参数有上百个白名单不可能穷尽。原则是诚实优先认不出的参数收进unknown[]转换照常完成但在产物顶部用注释亮出来# 警告: 未识别参数 --some-exotic-flag services: ...用户拿到的是「95 分答案 明确告诉你哪 5 分要自己补」这比假装 100 分或直接罢工都有用。坑 12一个 HTML 文件怎么写测试这个工具是单文件应用一个 HTML 就是全部没有构建链那测试怎么跑答案是把纯函数层和 UI 层拆成两个script第一个只有纯函数末尾挂双导出if (typeof module ! undefined module.exports) { module.exports { tokenize, parseDockerRun, toCompose }; // Node 测试用 } if (typeof window ! undefined) { window.DockerForgePure { tokenize, parseDockerRun, toCompose }; // 浏览器用 }测试脚本用正则抠出第一个script的内容new Function在 Node 里直接执行——不装任何测试框架23 条断言毫秒级跑完。UI 层则用 jsdom 做冒烟测试。CI 里node _test.js node smoke.js两行搞定。写在最后一条命令的转换器麻雀虽小分词状态机、参数语法的三形态、两个世界的语义翻译、YAML 的历史包袱、防御性输出、零框架测试——每一层都有值得较真的细节。三个可以直接带走的结论1.凡是「把一种字符串变成另一种字符串」的需求都比看起来难难点永远在两种格式各自的边角语义里2.YAML 里的值拿不准就加引号尤其是ports这种冒号分隔的字段3.把实现写成文章是性价比最高的 code review——第 7 个坑就是这么抓出来的。工具已开源MIT单 HTML 文件双击即用数据不出本机- DockerForge 在线版DockerForge — 离线 docker run 转 docker-compose 转换器- 源码300 行含全部测试https://github.com/wangzifan396-wzf/DockerForge- 同系列 82 款单文件工具导航nano-tools · 单文件零依赖工具集

相关新闻

Anki Cloze填空高级技巧:从字段验证到嵌套逻辑的完整指南 [特殊字符]

Anki Cloze填空高级技巧:从字段验证到嵌套逻辑的完整指南 [特殊字符]

Anki Cloze填空高级技巧:从字段验证到嵌套逻辑的完整指南 🚀 【免费下载链接】anki Anki is a smart spaced repetition flashcard program 项目地址: https://gitcode.com/GitHub_Trending/an/anki Anki作为智能间隔重复记忆软件,其C…

2026/7/27 13:19:59 阅读更多 →
TradingView Charting Library企业级跨平台集成架构:高性能金融图表解决方案

TradingView Charting Library企业级跨平台集成架构:高性能金融图表解决方案

TradingView Charting Library企业级跨平台集成架构:高性能金融图表解决方案 【免费下载链接】charting-library-examples Examples of Charting Library integrations with other libraries, frameworks and data transports 项目地址: https://gitcode.com/gh_m…

2026/7/27 13:19:59 阅读更多 →
Stable Zero123终极指南:从单张图片快速生成高质量3D模型的完整教程

Stable Zero123终极指南:从单张图片快速生成高质量3D模型的完整教程

Stable Zero123终极指南:从单张图片快速生成高质量3D模型的完整教程 【免费下载链接】stable-zero123 项目地址: https://ai.gitcode.com/hf_mirrors/stabilityai/stable-zero123 Stable Zero123是一个革命性的AI模型,能够从单张图片生成高质量的…

2026/7/27 13:19:59 阅读更多 →

最新新闻

7 月模型服务质量月报:延迟、可用率和成本三线看板

7 月模型服务质量月报:延迟、可用率和成本三线看板

7 月模型服务质量月报:延迟、可用率和成本三线看板 一、为什么单独拉一份模型服务质量报告 后端服务的 SLA 管理已经很成熟了:四九可用率、P99 延迟、QPS 峰值,各有一套监控方案。但模型推理服务不同——它的服务质量维度不是简单的"请求…

2026/7/27 13:41:12 阅读更多 →
7 月收尾:云原生 AI 平台的半年里程碑与下半年路线

7 月收尾:云原生 AI 平台的半年里程碑与下半年路线

7 月收尾:云原生 AI 平台的半年里程碑与下半年路线 一、半年数据:从零到日均 480 万推理请求 一月的时候,这个平台还只是三个模型跑在几台 GPU 节点上的原型系统。到七月底,平台承载的在线模型 26 个,日均推理请求 4…

2026/7/27 13:41:12 阅读更多 →
Mirror框架下VR联机实战:抓取同步、伤害判定与瞬移移动实现

Mirror框架下VR联机实战:抓取同步、伤害判定与瞬移移动实现

1. 项目概述与核心挑战 上次我们聊了Mirror网络框架的基础搭建和简单的同步逻辑,算是把VR联机的“地基”给打好了。但真要把一个VR联机项目跑起来,尤其是想让多个玩家在虚拟空间里顺畅地互动,你会发现一堆“地基”之上的难题在等着你。比如&a…

2026/7/27 13:41:12 阅读更多 →
C++动态数据绑定与反射机制:基于yaml-cpp的配置管理实践

C++动态数据绑定与反射机制:基于yaml-cpp的配置管理实践

1. 项目概述:为什么我们需要动态数据绑定与反射? 在C的世界里,处理配置文件、序列化数据或者构建灵活的插件系统时,我们常常会碰到一个经典难题:如何将一段外部的、结构可能变化的文本数据(比如YAML、JSON&…

2026/7/27 13:41:12 阅读更多 →
Governed Agent架构:LLM与规则引擎结合的业务流程控制

Governed Agent架构:LLM与规则引擎结合的业务流程控制

1. 先搞清楚 Governed Agent 到底解决什么问题 如果你用过基于 LLM 的智能助手或自动化流程,大概率遇到过这种情况:模型有时候会“自由发挥”,给出不符合业务规则的回答,或者在代码生成、数据处理等需要精确输出的场景里&#xff…

2026/7/27 13:41:12 阅读更多 →
免费绕过iPhone激活锁的终极指南:5分钟解锁你的iOS设备

免费绕过iPhone激活锁的终极指南:5分钟解锁你的iOS设备

免费绕过iPhone激活锁的终极指南:5分钟解锁你的iOS设备 【免费下载链接】applera1n icloud bypass for ios 15-16 项目地址: https://gitcode.com/gh_mirrors/ap/applera1n 你是否曾面对着一台被激活锁困住的iPhone,感到束手无策?无论…

2026/7/27 13:40:12 阅读更多 →

日新闻

【JAVA毕设源码分享】基于SpringBoot的社区智能垃圾管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

【JAVA毕设源码分享】基于SpringBoot的社区智能垃圾管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/27 0:00:54 阅读更多 →
SPI实战指南:从时钟模式到寄存器配置,解决嵌入式通信难题

SPI实战指南:从时钟模式到寄存器配置,解决嵌入式通信难题

1. 项目概述:从寄存器手册到实战指南 如果你手头有一份类似德州仪器(TI)TMS320x240xA系列DSP的SPI模块技术手册,看着里面密密麻麻的寄存器位定义、时序图和公式,是不是感觉头大?这份资料虽然权威&#xff0…

2026/7/27 0:00:54 阅读更多 →
【JAVA毕设源码分享】基于springboot的水果购物管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

【JAVA毕设源码分享】基于springboot的水果购物管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/27 0:00:54 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/27 4:33:59 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/27 6:31:56 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/27 4:01:12 阅读更多 →

月新闻