Featured image of post Docker 容器启动命令还原:cucker / runlike 工具对比

Docker 容器启动命令还原:cucker / runlike 工具对比

容器跑久了找不到启动命令怎么办?cucker/get_command_4_run_container、runlike、runcommand 三个工具对比与使用

容器跑久了之后,谁、用什么参数起的经常说不清。docker inspect 能看到参数但格式反人类,没有一个工具能直接还原成 docker run 命令就是问题。

社区里有三个工具专门干这事:cucker/get_command_4_run_containerassaflavie/runlikejoinsunsoft/runcommand。这一篇把它们的使用、差异、坑点一次性说清楚。

阅读对象:需要批量迁移容器、查历史启动参数、自动化复现容器配置的运维 / 开发者 覆盖范围:三个工具的对比 + 实战演示 + 自定义 alias + 边界场景

一、问题:为什么"看启动参数"这么难

docker inspect 能看所有配置,但输出的 JSON 字段名和 docker run 参数不一一对应

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
$ docker inspect mysql01 | jq '.[0].Config.Env'
[
  "MYSQL_ROOT_PASSWORD=py123456",
  "PATH=/usr/local/sbin:/usr/local/bin:...",
  ...
]

$ docker inspect mysql01 | jq '.[0].HostConfig.PortBindings'
{
  "3306/tcp": [
    {
      "HostIp": "",
      "HostPort": "13306"
    }
  ]
}

要把这些反向工程docker run -d --name mysql01 -p 13306:3306 -e MYSQL_ROOT_PASSWORD=py123456 mysql光看 JSON 就要在脑子里做几层翻译。三个工具就是干这个的。

二、cucker/get_command_4_run_container

最老牌、用得最多的工具,Docker Hub 上被 pull 了 100w+ 次

2.1 拉取 + 跑

1
2
3
4
5
6
# 拉镜像
docker pull cucker/get_command_4_run_container:1.3

# 还原容器的启动命令
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  cucker/get_command_4_run_container:1.3 <container-name-or-id>

关键点

  • --rm——跑完就删容器
  • -v /var/run/docker.sock:/var/run/docker.sock——挂载 docker daemon 的 socket,让容器内的工具能跟宿主机的 daemon 通信

2.2 输出示例

1
2
3
4
5
6
7
8
9
$ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  cucker/get_command_4_run_container:1.3 mysql01

docker run -d \
 --name mysql01 \
 --env MYSQL_ROOT_PASSWORD=py123456 \
 -p 13306:3306/tcp \
 --restart=always \
 mysql

直接复制粘贴就能跑

2.3 配合 alias 用

1
2
3
4
5
# ~/.bashrc
alias get_run_command='docker run --rm -v /var/run/docker.sock:/var/run/docker.sock cucker/get_command_4_run_container:1.3'

# 用
get_run_command mysql01

三、assaflavie/runlike

另一个流行工具,和 cucker 类似但输出格式略有不同

3.1 用法

1
2
3
4
5
6
# 拉镜像
docker pull assaflavie/runlike

# 还原
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  assaflavie/runlike <container-name-or-id>

3.2 差异

维度cuckerrunlike
输出格式docker run -d \\\n --name xxx \\\n ...docker run -d --name xxx ...(一行)
命名短名(mysql01FQDN(/mysql01,带斜杠)
网络--network=bridge--network=bridge
多网络部分支持支持更全
维护偶尔更新较活跃

四、joinsunsoft/runcommand

第三个工具,相对小众,但支持输出 docker-compose 格式

1
2
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  joinsunsoft/runcommand loki

特色:能输出 YAML 格式的 docker-compose 配置。

五、批量还原所有容器

1
2
3
4
5
6
# 所有运行中容器
for CONTAINER in $(docker ps --format '{{.Names}}'); do
  echo "=== $CONTAINER ==="
  docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
    cucker/get_command_4_run_container:1.3 $CONTAINER
done

典型场景:接手一个"无文档"的 Docker 主机,用这个脚本快速还原整个部署

六、还原 Docker Compose 配置

cucker 输出的是 docker run 单条命令。如果容器是用 docker-compose up 启动的,实际配置在 docker-compose.yml——还原不回来。

变通方案

1
2
3
4
5
6
7
# 1. 看容器实际配置
docker inspect <container> > /tmp/container.json

# 2. 用 jq 提取关键字段
docker inspect <container> | jq '.[0].Config.Env'
docker inspect <container> | jq '.[0].HostConfig.PortBindings'
docker inspect <container> | jq '.[0].Mounts'

或者用社区脚本 rekcod

1
2
3
# 把任意容器还原成 docker-compose.yml
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  nexdrew/rekcod <container>

七、常见坑

7.1 permission denied 挂载 socket

1
2
$ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock cucker/get_command_4_run_container:1.3 mysql
docker: error during connect: ... permission denied

解决

  • Linux:当前用户在 docker 用户组里,或者用 sudo
  • Mac/Windows (Docker Desktop):socket 路径在 VM 里,默认配置应该 OK
1
2
3
# Linux 上加 docker 组
sudo usermod -aG docker $USER
newgrp docker

7.2 还原出来的命令跑不起来

Why

  • 镜像已被删除(docker rmi 过)
  • 网络 / 卷不存在
  • 端口冲突

cucker / runlike 只还原配置,不还原前置依赖先验证镜像还在

1
2
$ docker images | grep mysql
mysql   latest   7d0a4dc9b...   2 weeks ago   546MB

7.3 容器里有 bind mount 到宿主机路径

cucker 还原的命令会保留 -v /host/path:/container/path,但如果目标宿主机上 /host/path 不存在,启动会失败。

配合 creates 标记

1
2
3
4
5
# 在还原的命令前先确保路径
mkdir -p /host/path

# 再跑还原的命令
docker run -d --name xxx -v /host/path:/container/path ...

7.4 docker run 输出和 docker-compose.yml 不一样

实例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 实际启动:docker-compose.yml
version: "3"
services:
  nginx:
    image: nginx:1.19
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html
    restart: always

# cucker 还原
docker run -d --name nginx -p 8080:80 \
  -v /root/project/html:/usr/share/nginx/html \
  --restart=always nginx:1.19

Why 不一样

  • compose 会自动加 --name <project>_<service>_<index>(如 project_nginx_1
  • compose 自动加 com.docker.compose.* 标签
  • bind mount 的相对路径变成绝对路径

生产建议别用 cucker 还原 compose 启动的容器——直接读 compose 文件最准。

八、工具对比

维度cuckerrunlikeruncommandrekcod
输出格式docker rundocker rundocker rundocker-compose
镜像大小~30MB~20MB~25MB~30MB
多网络支持部分
维护活跃偶尔活跃少更新活跃
推荐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

九、最佳实践

  1. 核心生产环境写好 docker-compose.yml + Git 版本管理——别依赖"事后还原"
  2. 应急查命令cucker / runlike 一键还原
  3. 批量盘点:用 for 循环扫所有容器,输出成文档
  4. 不要把"还原命令"作为"日常运维工具"——SSoT 应该是 compose 文件 / K8s manifest

十、要点回顾

  1. cucker / runlike / runcommand / rekcod 是社区主流的"反查启动命令"工具
  2. 必须挂载 /var/run/docker.sock——容器内的工具才能跟 daemon 通信
  3. 还原的命令可能不能直接跑——镜像删除 / 路径不存在 / 端口冲突都常见
  4. compose 启动的容器还原出来是 docker run 格式——不是 compose
  5. 生产 SSoT 应该是 compose / K8s manifest——还原工具只应急

十一、小结

“还原启动命令"是接手历史部署、自动化盘点、应急迁移的利器。但最佳实践仍然是把启动配置写在文件里——docker-compose.yml / K8s manifest,让 Git 成为 SSoT

下一步:理解了"还原单条启动命令”,下一步是"还原整套部署"——rekcod 风格的 docker-compose 还原、Helm chart 模板化、Kustomize 跨环境覆盖——把"凭记忆启动"变成"声明式部署"。

参考资料

使用 Hugo 构建
主题 StackJimmy 设计