package main import ( "encoding/json" "fmt" "os/exec" "strings" ) // 从 demo.json 中需要提取的字段: type ContainerInfo struct { Name string `json:"Name"` Config struct { Hostname string `json:"Hostname"` Image string `json:"Image"` Cmd []string `json:"Cmd"` Labels map[string]string `json:"Labels"` } `json:"Config"` Args []string `json:"Args"` HostConfig struct { NetworkMode string `json:"NetworkMode"` RestartPolicy struct { Name string `json:"Name"` } `json:"RestartPolicy"` Runtime string `json:"Runtime"` } `json:"HostConfig"` Mounts []struct { Type string Source string Destination string Mode string } `json:"Mounts"` } // 解析 JSON 文件并返回 ContainerInfo func parseJSONString(data map[string]any) (ContainerInfo, error) { var c ContainerInfo // 1. 顶层简单字段 if v, ok := data["Name"].(string); ok { c.Name = v[1:] // 去掉前导斜杠 } if v, ok := data["Args"].([]any); ok { c.Args = make([]string, len(v)) for i, a := range v { c.Args[i], _ = a.(string) } } // 2. Config 子对象 if cfg, ok := data["Config"].(map[string]any); ok { if v, ok := cfg["Hostname"].(string); ok { c.Config.Hostname = v } if v, ok := cfg["Image"].(string); ok { c.Config.Image = v } if arr, ok := cfg["Cmd"].([]any); ok { c.Config.Cmd = make([]string, len(arr)) for i, v := range arr { c.Config.Cmd[i], _ = v.(string) } } if labels, ok := cfg["Labels"].(map[string]any); ok { c.Config.Labels = make(map[string]string, len(labels)) for k, v := range labels { c.Config.Labels[k], _ = v.(string) } } } // 3. HostConfig 子对象 if hc, ok := data["HostConfig"].(map[string]any); ok { if v, ok := hc["NetworkMode"].(string); ok { c.HostConfig.NetworkMode = v } if v, ok := hc["Runtime"].(string); ok { c.HostConfig.Runtime = v } if rp, ok := hc["RestartPolicy"].(map[string]any); ok { if v, ok := rp["Name"].(string); ok { c.HostConfig.RestartPolicy.Name = v } } } // 4. Mounts 数组 if mounts, ok := data["Mounts"].([]any); ok { for _, m := range mounts { mm, _ := m.(map[string]any) var mount struct { Type, Source, Destination, Mode string } mount.Type, _ = mm["Type"].(string) mount.Source, _ = mm["Source"].(string) mount.Destination, _ = mm["Destination"].(string) mount.Mode, _ = mm["Mode"].(string) c.Mounts = append(c.Mounts, mount) } } return c, nil } // 构建 docker run 命令 func buildDockerRunCommand(container ContainerInfo) string { var cmd strings.Builder // 基础命令 cmd.WriteString("docker run") // 容器名称 if container.Name != "" { name := strings.TrimPrefix(container.Name, "/") cmd.WriteString(fmt.Sprintf(" --name=%s", name)) } // 主机名 if container.Config.Hostname != "" { cmd.WriteString(fmt.Sprintf(" --hostname=%s", container.Config.Hostname)) } // 卷挂载 for _, mount := range container.Mounts { if mount.Type == "bind" { cmd.WriteString(fmt.Sprintf(" --volume %s:%s", mount.Source, mount.Destination)) } } // 网络模式 if container.HostConfig.NetworkMode != "" { cmd.WriteString(fmt.Sprintf(" --network=%s", container.HostConfig.NetworkMode)) } // 重启策略 if container.HostConfig.RestartPolicy.Name != "" { cmd.WriteString(fmt.Sprintf(" --restart=%s", container.HostConfig.RestartPolicy.Name)) } // 标签 for key, value := range container.Config.Labels { cmd.WriteString(fmt.Sprintf(" --label='%s=%s'", key, value)) } // 运行时 if container.HostConfig.Runtime != "" { cmd.WriteString(fmt.Sprintf(" --runtime=%s", container.HostConfig.Runtime)) } // 镜像 if container.Config.Image != "" { cmd.WriteString(fmt.Sprintf(" %s", container.Config.Image)) } // 命令参数 if len(container.Args) > 0 { cmd.WriteString(fmt.Sprintf(" %s", strings.Join(container.Args, " "))) } else if len(container.Config.Cmd) > 0 { cmd.WriteString(fmt.Sprintf(" %s", strings.Join(container.Config.Cmd, " "))) } return cmd.String() } func getContainerCommand(containerName string) (string, error) { data_js, err := execInspectCommand(containerName) if err != nil { return "", err } ctInfo, err := parseJSONString(data_js[0]) if err != nil { return "", err } return buildDockerRunCommand(ctInfo), nil } // 执行shell命令 func execInspectCommand(name string) ([]map[string]interface{}, error) { cmd := exec.Command("docker", "inspect", name) out, err := cmd.CombinedOutput() if err != nil { return nil, fmt.Errorf("执行命令失败: %v", err) } // docker inspect 返回的是 []map[string]interface{} var result []map[string]interface{} if err := json.Unmarshal(out, &result); err != nil { return nil, fmt.Errorf("解析 JSON 失败: %w", err) } if len(result) == 0 { return nil, fmt.Errorf("未找到容器/镜像: %s", name) } return result, nil }