docker.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876
  1. package service
  2. import (
  3. "bytes"
  4. "context"
  5. "encoding/base64"
  6. "encoding/binary"
  7. json2 "encoding/json"
  8. "fmt"
  9. "reflect"
  10. "syscall"
  11. model2 "github.com/IceWhaleTech/CasaOS/service/model"
  12. types2 "github.com/IceWhaleTech/CasaOS/types"
  13. "github.com/containerd/containerd"
  14. "github.com/containerd/containerd/cio"
  15. "github.com/containerd/containerd/namespaces"
  16. "github.com/containerd/containerd/oci"
  17. "github.com/IceWhaleTech/CasaOS/model"
  18. "github.com/IceWhaleTech/CasaOS/pkg/docker"
  19. command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
  20. "github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper"
  21. "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
  22. loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
  23. //"github.com/containerd/containerd/oci"
  24. "io"
  25. "io/ioutil"
  26. "log"
  27. "os"
  28. "strconv"
  29. "strings"
  30. "time"
  31. "github.com/docker/docker/api/types"
  32. "github.com/docker/docker/api/types/container"
  33. "github.com/docker/docker/api/types/filters"
  34. "github.com/docker/docker/api/types/mount"
  35. "github.com/docker/docker/api/types/network"
  36. client2 "github.com/docker/docker/client"
  37. "github.com/docker/go-connections/nat"
  38. )
  39. type DockerService interface {
  40. DockerPullImage(imageName string, m model2.AppNotify) error
  41. IsExistImage(imageName string) bool
  42. DockerContainerCreate(imageName string, containerDbId string, m model.CustomizationPostData, net string) (containerId string, err error)
  43. DockerContainerStart(name string) error
  44. DockerContainerStats(name string) (string, error)
  45. DockerListByName(name string) (*types.Container, error)
  46. DockerListByImage(image, version string) (*types.Container, error)
  47. DockerContainerInfo(name string) (*types.ContainerJSON, error)
  48. DockerImageRemove(name string) error
  49. DockerContainerRemove(name string, update bool) error
  50. DockerContainerStop(id string) error
  51. DockerContainerUpdateName(name, id string) (err error)
  52. DockerContainerUpdate(m model.CustomizationPostData, id string) (err error)
  53. DockerContainerLog(name string) (string, error)
  54. DockerContainerCommit(name string)
  55. DockerNetworkModelList() []types.NetworkResource
  56. DockerImageInfo(image string)
  57. GetNetWorkNameByNetWorkID(id string) (string, error)
  58. ContainerExecShell(container_id string) string
  59. }
  60. type dockerService struct {
  61. rootDir string
  62. log loger2.OLog
  63. }
  64. func (ds *dockerService) ContainerExecShell(container_id string) string {
  65. cli, _ := client2.NewClientWithOpts(client2.FromEnv)
  66. exec, err := cli.ContainerExecCreate(context.Background(), container_id, types.ExecConfig{
  67. User: "1000:1000",
  68. Cmd: []string{"echo -e \"hellow\nworld\" >> /a.txt"},
  69. })
  70. if err != nil {
  71. os.Exit(5)
  72. }
  73. err = cli.ContainerExecStart(context.Background(), exec.ID, types.ExecStartCheck{})
  74. if err != nil {
  75. fmt.Println("exec script error ", err)
  76. }
  77. return exec.ID
  78. }
  79. //创建默认网络
  80. func DockerNetwork() {
  81. cli, _ := client2.NewClientWithOpts(client2.FromEnv)
  82. defer cli.Close()
  83. d, _ := cli.NetworkList(context.Background(), types.NetworkListOptions{})
  84. for _, resource := range d {
  85. if resource.Name == docker.NETWORKNAME {
  86. return
  87. }
  88. }
  89. cli.NetworkCreate(context.Background(), docker.NETWORKNAME, types.NetworkCreate{})
  90. }
  91. //根据网络id获取网络名
  92. func (ds *dockerService) GetNetWorkNameByNetWorkID(id string) (string, error) {
  93. cli, _ := client2.NewClientWithOpts(client2.FromEnv)
  94. defer cli.Close()
  95. filter := filters.NewArgs()
  96. filter.Add("id", id)
  97. d, err := cli.NetworkList(context.Background(), types.NetworkListOptions{Filters: filter})
  98. if err == nil && len(d) > 0 {
  99. return d[0].Name, nil
  100. }
  101. return "", err
  102. }
  103. //拉取镜像
  104. func DockerPull() {
  105. cli, _ := client2.NewClientWithOpts(client2.FromEnv)
  106. defer cli.Close()
  107. authConfig := types.AuthConfig{
  108. Username: "cn-north-4@M4OW0IULZ3U6PCQPBUZC",
  109. Password: "7390181a1565f90927bbd98038436b57d6ebc66a3828d7a11dfda42b9c19d91d",
  110. }
  111. encodedJSON, err := json2.Marshal(authConfig)
  112. fmt.Println(err)
  113. authStr := base64.URLEncoding.EncodeToString(encodedJSON)
  114. reader, err := cli.ImagePull(context.Background(), "swr.cn-north-4.myhuaweicloud.com/root/swr-demo-2048:latest", types.ImagePullOptions{RegistryAuth: authStr})
  115. buf := new(bytes.Buffer)
  116. buf.ReadFrom(reader)
  117. fmt.Println(buf.String())
  118. }
  119. //拉取镜像
  120. func DockerEx() {
  121. cli, _ := client2.NewClientWithOpts(client2.FromEnv)
  122. defer cli.Close()
  123. importResponse, err := cli.ImageImport(context.Background(), types.ImageImportSource{
  124. Source: strings.NewReader("source"),
  125. SourceName: "image_source",
  126. }, "repository_name:imported", types.ImageImportOptions{
  127. Tag: "imported",
  128. Message: "A message",
  129. Changes: []string{"change1", "change2"},
  130. })
  131. response, err := ioutil.ReadAll(importResponse)
  132. if err != nil {
  133. fmt.Println(err)
  134. }
  135. importResponse.Close()
  136. println(string(response))
  137. if string(response) != "response" {
  138. fmt.Printf("expected response to contain 'response', got %s", string(response))
  139. }
  140. }
  141. //func DockerContainerSize() {
  142. // cli, err := client2.NewClientWithOpts(client2.FromEnv)
  143. // //but := bytes.Buffer{}
  144. // d, err := cli.ContainerExecCreate(context.Background(), "c3adcef92bae648890941ac00e6c4024d7f2959c2e629f0b581d6a19d77b5eda")
  145. // fmt.Println(d)
  146. // st, _ := ioutil.ReadAll(d.Body)
  147. // fmt.Println(string(st))
  148. // if err != nil {
  149. // fmt.Print(err)
  150. // }
  151. //
  152. //}
  153. func (ds *dockerService) DockerImageInfo(image string) {
  154. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  155. //but := bytes.Buffer{}
  156. d, b, err := cli.ImageInspectWithRaw(context.Background(), image)
  157. st, _ := json2.Marshal(d.Config)
  158. fmt.Println(string(st))
  159. fmt.Println("换行")
  160. fmt.Println(string(b))
  161. if err != nil {
  162. fmt.Print(err)
  163. }
  164. }
  165. func MsqlExec(container string) error {
  166. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  167. ctx := context.Background()
  168. // 执行/bin/bash命令
  169. ir, err := cli.ContainerExecCreate(ctx, container, types.ExecConfig{
  170. AttachStdin: false,
  171. AttachStdout: true,
  172. AttachStderr: true,
  173. Cmd: []string{"date"},
  174. Tty: true,
  175. Env: []string{"aaa=ddd"},
  176. })
  177. err = cli.ContainerExecStart(ctx, ir.ID, types.ExecStartCheck{})
  178. fmt.Println(err)
  179. return err
  180. }
  181. func Exec(container, row, col string) (hr types.HijackedResponse, err error) {
  182. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  183. ctx := context.Background()
  184. // 执行/bin/bash命令
  185. ir, err := cli.ContainerExecCreate(ctx, container, types.ExecConfig{
  186. AttachStdin: true,
  187. AttachStdout: true,
  188. AttachStderr: true,
  189. Env: []string{"COLUMNS=" + col, "LINES=" + row},
  190. Cmd: []string{"/bin/bash"},
  191. Tty: true,
  192. })
  193. if err != nil {
  194. return
  195. }
  196. // 附加到上面创建的/bin/bash进程中
  197. hr, err = cli.ContainerExecAttach(ctx, ir.ID, types.ExecStartCheck{Detach: false, Tty: true})
  198. if err != nil {
  199. return
  200. }
  201. return
  202. }
  203. func DockerLog() {
  204. //cli, err := client2.NewClientWithOpts(client2.FromEnv)
  205. //ctx := context.Background()
  206. //ir, err := cli.ContainerLogs(ctx, "79c6fa382c330b9149e2d28d24f4d2c231cdb8cfc0710c2d268ccee13c5b24f8", types.ContainerLogsOptions{})
  207. //str, err := ioutil.ReadAll(ir)
  208. //fmt.Println(string(str))
  209. //fmt.Println(err)
  210. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  211. defer cancel()
  212. client, _ := client2.NewClientWithOpts(client2.FromEnv)
  213. reader, err := client.ContainerLogs(ctx, "79c6fa382c330b9149e2d28d24f4d2c231cdb8cfc0710c2d268ccee13c5b24f8", types.ContainerLogsOptions{})
  214. if err != nil {
  215. log.Fatal(err)
  216. }
  217. _, err = io.Copy(os.Stdout, reader)
  218. if err != nil && err != io.EOF {
  219. log.Fatal(err)
  220. }
  221. }
  222. func DockerLogs() {
  223. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  224. i, err := cli.ContainerLogs(context.Background(), "79c6fa382c330b9149e2d28d24f4d2c231cdb8cfc0710c2d268ccee13c5b24f8", types.ContainerLogsOptions{
  225. ShowStderr: true,
  226. ShowStdout: true,
  227. Timestamps: false,
  228. Follow: true,
  229. Tail: "40",
  230. })
  231. if err != nil {
  232. log.Fatal(err)
  233. }
  234. defer i.Close()
  235. hdr := make([]byte, 8)
  236. for {
  237. _, err := i.Read(hdr)
  238. if err != nil {
  239. log.Fatal(err)
  240. }
  241. var w io.Writer
  242. switch hdr[0] {
  243. case 1:
  244. w = os.Stdout
  245. default:
  246. w = os.Stderr
  247. }
  248. count := binary.BigEndian.Uint32(hdr[4:])
  249. dat := make([]byte, count)
  250. _, err = i.Read(dat)
  251. fmt.Fprint(w, string(dat))
  252. }
  253. }
  254. //正式内容
  255. //检查镜像是否存在
  256. func (ds *dockerService) IsExistImage(imageName string) bool {
  257. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  258. if err != nil {
  259. return false
  260. }
  261. defer cli.Close()
  262. filter := filters.NewArgs()
  263. filter.Add("reference", imageName)
  264. list, err := cli.ImageList(context.Background(), types.ImageListOptions{Filters: filter})
  265. if err == nil && len(list) > 0 {
  266. return true
  267. }
  268. return false
  269. }
  270. //安装镜像
  271. func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) error {
  272. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  273. if err != nil {
  274. return err
  275. }
  276. defer cli.Close()
  277. out, err := cli.ImagePull(context.Background(), imageName, types.ImagePullOptions{})
  278. if err != nil {
  279. return err
  280. }
  281. defer out.Close()
  282. if err != nil {
  283. return err
  284. }
  285. buf := make([]byte, 256)
  286. for {
  287. n, err := out.Read(buf)
  288. if err != nil {
  289. if err != io.EOF {
  290. fmt.Println("read error:", err)
  291. }
  292. break
  293. }
  294. if !reflect.DeepEqual(m, model2.AppNotify{}) {
  295. m.Type = types2.NOTIFY_TYPE_INSTALL_LOG
  296. m.State = 0
  297. m.Message = string(buf[:n])
  298. MyService.Notify().UpdateLog(m)
  299. }
  300. }
  301. return err
  302. }
  303. //param imageName 镜像名称
  304. //param containerDbId 数据库的id
  305. //param port 容器内部主端口
  306. //param mapPort 容器主端口映射到外部的端口
  307. //param tcp 容器其他tcp端口
  308. //param udp 容器其他udp端口
  309. func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId string, m model.CustomizationPostData, net string) (containerId string, err error) {
  310. if len(net) == 0 {
  311. net = "bridge"
  312. }
  313. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  314. if err != nil {
  315. return "", err
  316. }
  317. defer cli.Close()
  318. ports := make(nat.PortSet)
  319. portMaps := make(nat.PortMap)
  320. // ports[nat.Port(fmt.Sprint(m.PortMap)+"/tcp")] = struct{}{}
  321. // if net != "host" {
  322. // portMaps[nat.Port(fmt.Sprint(m.Port)+"/tcp")] = []nat.PortBinding{{HostIP: "", HostPort: m.PortMap}}
  323. // }
  324. //port := ""
  325. for _, portMap := range m.Ports {
  326. // if portMap.CommendPort == m.PortMap && portMap.Protocol == "tcp" || portMap.Protocol == "both" {
  327. // port = portMap.ContainerPort
  328. // }
  329. if portMap.Protocol == "tcp" {
  330. tContainer, _ := strconv.Atoi(portMap.ContainerPort)
  331. if tContainer > 0 {
  332. ports[nat.Port(portMap.ContainerPort+"/tcp")] = struct{}{}
  333. if net != "host" {
  334. portMaps[nat.Port(portMap.ContainerPort+"/tcp")] = []nat.PortBinding{{HostIP: "0.0.0.0", HostPort: portMap.CommendPort}}
  335. }
  336. }
  337. } else if portMap.Protocol == "both" {
  338. tContainer, _ := strconv.Atoi(portMap.ContainerPort)
  339. if tContainer > 0 {
  340. ports[nat.Port(portMap.ContainerPort+"/tcp")] = struct{}{}
  341. if net != "host" {
  342. portMaps[nat.Port(portMap.ContainerPort+"/tcp")] = []nat.PortBinding{{HostIP: "0.0.0.0", HostPort: portMap.CommendPort}}
  343. }
  344. }
  345. uContainer, _ := strconv.Atoi(portMap.ContainerPort)
  346. if uContainer > 0 {
  347. ports[nat.Port(portMap.ContainerPort+"/udp")] = struct{}{}
  348. if net != "host" {
  349. portMaps[nat.Port(portMap.ContainerPort+"/udp")] = []nat.PortBinding{{HostIP: "0.0.0.0", HostPort: portMap.CommendPort}}
  350. }
  351. }
  352. } else {
  353. uContainer, _ := strconv.Atoi(portMap.ContainerPort)
  354. if uContainer > 0 {
  355. ports[nat.Port(portMap.ContainerPort+"/udp")] = struct{}{}
  356. if net != "host" {
  357. portMaps[nat.Port(portMap.ContainerPort+"/udp")] = []nat.PortBinding{{HostIP: "0.0.0.0", HostPort: portMap.CommendPort}}
  358. }
  359. }
  360. }
  361. }
  362. var envArr []string
  363. for _, e := range m.Envs {
  364. if strings.HasPrefix(e.Value, "$") {
  365. envArr = append(envArr, e.Name+"="+env_helper.ReplaceDefaultENV(e.Value, MyService.System().GetTimeZone()))
  366. continue
  367. }
  368. if len(e.Value) > 0 {
  369. if e.Value == "port_map" {
  370. envArr = append(envArr, e.Name+"="+m.PortMap)
  371. continue
  372. }
  373. envArr = append(envArr, e.Name+"="+e.Value)
  374. }
  375. }
  376. res := container.Resources{}
  377. if m.CpuShares > 0 {
  378. res.CPUShares = m.CpuShares
  379. }
  380. if m.Memory > 0 {
  381. res.Memory = m.Memory << 20
  382. }
  383. for _, p := range m.Devices {
  384. if len(p.Path) > 0 {
  385. res.Devices = append(res.Devices, container.DeviceMapping{PathOnHost: p.Path, PathInContainer: p.ContainerPath})
  386. }
  387. }
  388. hostConfingBind := []string{}
  389. // volumes bind
  390. volumes := []mount.Mount{}
  391. for _, v := range m.Volumes {
  392. path := v.Path
  393. if len(path) == 0 {
  394. path = docker.GetDir(containerDbId, v.Path)
  395. if len(path) == 0 {
  396. continue
  397. }
  398. }
  399. path = strings.ReplaceAll(path, "$AppID", containerDbId)
  400. //reg1 := regexp.MustCompile(`([^<>/\\\|:""\*\?]+\.\w+$)`)
  401. //result1 := reg1.FindAllStringSubmatch(path, -1)
  402. //if len(result1) == 0 {
  403. err = file.IsNotExistMkDir(path)
  404. if err != nil {
  405. ds.log.Error("mkdir error", err)
  406. continue
  407. }
  408. //}
  409. // else {
  410. // err = file.IsNotExistCreateFile(path)
  411. // if err != nil {
  412. // ds.log.Error("mkdir error", err)
  413. // continue
  414. // }
  415. // }
  416. volumes = append(volumes, mount.Mount{
  417. Type: mount.TypeBind,
  418. Source: path,
  419. Target: v.ContainerPath,
  420. })
  421. hostConfingBind = append(hostConfingBind, v.Path+":"+v.ContainerPath)
  422. }
  423. rp := container.RestartPolicy{}
  424. if len(m.Restart) > 0 {
  425. rp.Name = m.Restart
  426. }
  427. // healthTest := []string{}
  428. // if len(port) > 0 {
  429. // healthTest = []string{"CMD-SHELL", "curl -f http://localhost:" + port + m.Index + " || exit 1"}
  430. // }
  431. // health := &container.HealthConfig{
  432. // Test: healthTest,
  433. // StartPeriod: 0,
  434. // Retries: 1000,
  435. // }
  436. // fmt.Print(health)
  437. config := &container.Config{
  438. Image: imageName,
  439. Labels: map[string]string{"origin": m.Origin, m.Origin: m.Origin},
  440. Env: envArr,
  441. // Healthcheck: health,
  442. }
  443. hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: container.NetworkMode(net)}
  444. //if net != "host" {
  445. config.ExposedPorts = ports
  446. hostConfig.PortBindings = portMaps
  447. //}
  448. containerDb, err := cli.ContainerCreate(context.Background(),
  449. config,
  450. hostConfig,
  451. &network.NetworkingConfig{EndpointsConfig: map[string]*network.EndpointSettings{net: {NetworkID: "", Aliases: []string{}}}},
  452. nil,
  453. containerDbId)
  454. if err != nil {
  455. return "", err
  456. }
  457. return containerDb.ID, err
  458. }
  459. //删除容器
  460. func (ds *dockerService) DockerContainerRemove(name string, update bool) error {
  461. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  462. if err != nil {
  463. return err
  464. }
  465. defer cli.Close()
  466. err = cli.ContainerRemove(context.Background(), name, types.ContainerRemoveOptions{})
  467. //路径处理
  468. if !update {
  469. path := docker.GetDir(name, "/config")
  470. if !file.CheckNotExist(path) {
  471. file.RMDir(path)
  472. }
  473. }
  474. if err != nil {
  475. return err
  476. }
  477. return err
  478. }
  479. //删除镜像
  480. func (ds *dockerService) DockerImageRemove(name string) error {
  481. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  482. if err != nil {
  483. return err
  484. }
  485. defer cli.Close()
  486. imageList, err := cli.ImageList(context.Background(), types.ImageListOptions{})
  487. imageId := ""
  488. Loop:
  489. for _, ig := range imageList {
  490. for _, i := range ig.RepoTags {
  491. if i == name {
  492. imageId = ig.ID
  493. break Loop
  494. }
  495. }
  496. }
  497. _, err = cli.ImageRemove(context.Background(), imageId, types.ImageRemoveOptions{})
  498. return err
  499. }
  500. func DockerImageRemove(name string) error {
  501. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  502. if err != nil {
  503. return err
  504. }
  505. defer cli.Close()
  506. imageList, err := cli.ImageList(context.Background(), types.ImageListOptions{})
  507. imageId := ""
  508. Loop:
  509. for _, ig := range imageList {
  510. fmt.Println(ig.RepoDigests)
  511. fmt.Println(ig.Containers)
  512. for _, i := range ig.RepoTags {
  513. if i == name {
  514. imageId = ig.ID
  515. break Loop
  516. }
  517. }
  518. }
  519. _, err = cli.ImageRemove(context.Background(), imageId, types.ImageRemoveOptions{})
  520. return err
  521. }
  522. //停止镜像
  523. func (ds *dockerService) DockerContainerStop(id string) error {
  524. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  525. if err != nil {
  526. return err
  527. }
  528. defer cli.Close()
  529. err = cli.ContainerStop(context.Background(), id, nil)
  530. return err
  531. }
  532. //启动容器
  533. func (ds *dockerService) DockerContainerStart(name string) error {
  534. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  535. if err != nil {
  536. return err
  537. }
  538. defer cli.Close()
  539. err = cli.ContainerStart(context.Background(), name, types.ContainerStartOptions{})
  540. return err
  541. }
  542. //查看日志
  543. func (ds *dockerService) DockerContainerLog(name string) (string, error) {
  544. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  545. if err != nil {
  546. return "", err
  547. }
  548. defer cli.Close()
  549. body, err := cli.ContainerLogs(context.Background(), name, types.ContainerLogsOptions{ShowStderr: true, ShowStdout: true})
  550. if err != nil {
  551. return "", err
  552. }
  553. defer body.Close()
  554. content, err := ioutil.ReadAll(body)
  555. if err != nil {
  556. return "", err
  557. }
  558. return string(content), nil
  559. }
  560. func DockerContainerStats1() error {
  561. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  562. if err != nil {
  563. return err
  564. }
  565. defer cli.Close()
  566. dss, err := cli.ContainerStats(context.Background(), "dockermysql", false)
  567. if err != nil {
  568. return err
  569. }
  570. defer dss.Body.Close()
  571. sts, err := ioutil.ReadAll(dss.Body)
  572. if err != nil {
  573. return err
  574. }
  575. fmt.Println(string(sts))
  576. return nil
  577. }
  578. //获取容器状态
  579. func (ds *dockerService) DockerContainerStats(name string) (string, error) {
  580. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  581. if err != nil {
  582. return "", err
  583. }
  584. defer cli.Close()
  585. dss, err := cli.ContainerStats(context.Background(), name, false)
  586. if err != nil {
  587. return "", err
  588. }
  589. defer dss.Body.Close()
  590. sts, err := ioutil.ReadAll(dss.Body)
  591. if err != nil {
  592. return "", err
  593. }
  594. return string(sts), nil
  595. }
  596. //备份容器
  597. func (ds *dockerService) DockerContainerCommit(name string) {
  598. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  599. if err != nil {
  600. fmt.Println(err)
  601. }
  602. defer cli.Close()
  603. d, err := cli.ContainerInspect(context.Background(), name)
  604. dss, err := cli.ContainerCommit(context.Background(), name, types.ContainerCommitOptions{Reference: "test", Config: d.Config})
  605. if err != nil {
  606. fmt.Println(err)
  607. }
  608. fmt.Println(dss)
  609. }
  610. func (ds *dockerService) DockerListByName(name string) (*types.Container, error) {
  611. cli, _ := client2.NewClientWithOpts(client2.FromEnv)
  612. defer cli.Close()
  613. filter := filters.NewArgs()
  614. filter.Add("name", name)
  615. containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{Filters: filter})
  616. if err != nil {
  617. return &types.Container{}, err
  618. }
  619. return &containers[0], nil
  620. }
  621. func (ds *dockerService) DockerListByImage(image, version string) (*types.Container, error) {
  622. cli, _ := client2.NewClientWithOpts(client2.FromEnv)
  623. defer cli.Close()
  624. filter := filters.NewArgs()
  625. filter.Add("ancestor", image+":"+version)
  626. containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{Filters: filter})
  627. if err != nil {
  628. return nil, err
  629. }
  630. if len(containers) == 0 {
  631. return nil, nil
  632. }
  633. return &containers[0], nil
  634. }
  635. //获取容器详情
  636. func (ds *dockerService) DockerContainerInfo(name string) (*types.ContainerJSON, error) {
  637. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  638. if err != nil {
  639. return &types.ContainerJSON{}, err
  640. }
  641. defer cli.Close()
  642. d, err := cli.ContainerInspect(context.Background(), name)
  643. if err != nil {
  644. return &types.ContainerJSON{}, err
  645. }
  646. return &d, nil
  647. }
  648. //更新容器
  649. //param shares cpu优先级
  650. //param containerDbId 数据库的id
  651. //param port 容器内部主端口
  652. //param mapPort 容器主端口映射到外部的端口
  653. //param tcp 容器其他tcp端口
  654. //param udp 容器其他udp端口
  655. func (ds *dockerService) DockerContainerUpdate(m model.CustomizationPostData, id string) (err error) {
  656. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  657. if err != nil {
  658. return err
  659. }
  660. defer cli.Close()
  661. //重启策略
  662. rp := container.RestartPolicy{
  663. Name: "",
  664. MaximumRetryCount: 0,
  665. }
  666. if len(m.Restart) > 0 {
  667. rp.Name = m.Restart
  668. }
  669. res := container.Resources{}
  670. if m.Memory > 0 {
  671. res.Memory = m.Memory * 1024 * 1024
  672. res.MemorySwap = -1
  673. }
  674. if m.CpuShares > 0 {
  675. res.CPUShares = m.CpuShares
  676. }
  677. for _, p := range m.Devices {
  678. res.Devices = append(res.Devices, container.DeviceMapping{PathOnHost: p.Path, PathInContainer: p.ContainerPath})
  679. }
  680. _, err = cli.ContainerUpdate(context.Background(), id, container.UpdateConfig{RestartPolicy: rp, Resources: res})
  681. if err != nil {
  682. return err
  683. }
  684. return
  685. }
  686. //更新容器名称
  687. //param name 容器名称
  688. //param id 老的容器名称
  689. func (ds *dockerService) DockerContainerUpdateName(name, id string) (err error) {
  690. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  691. if err != nil {
  692. return err
  693. }
  694. defer cli.Close()
  695. err = cli.ContainerRename(context.Background(), id, name)
  696. if err != nil {
  697. return err
  698. }
  699. return
  700. }
  701. //获取网络列表
  702. func (ds *dockerService) DockerNetworkModelList() []types.NetworkResource {
  703. cli, _ := client2.NewClientWithOpts(client2.FromEnv)
  704. defer cli.Close()
  705. networks, _ := cli.NetworkList(context.Background(), types.NetworkListOptions{})
  706. return networks
  707. }
  708. func NewDockerService(log loger2.OLog) DockerService {
  709. return &dockerService{rootDir: command2.ExecResultStr(`source ./shell/helper.sh ;GetDockerRootDir`), log: log}
  710. }
  711. // ---------------------------------------test------------------------------------
  712. //func ServiceCreate() {
  713. // cli, err := client2.NewClientWithOpts(client2.FromEnv)
  714. // r, err := cli.ServiceCreate(context.Background(), swarm.ServiceSpec{}, types.ServiceCreateOptions{})
  715. // if err != nil {
  716. // fmt.Println("error", err)
  717. // }
  718. //
  719. //
  720. //}
  721. func Containerd() {
  722. // create a new client connected to the default socket path for containerd
  723. cli, err := containerd.New("/run/containerd/containerd.sock")
  724. if err != nil {
  725. fmt.Println("111")
  726. fmt.Println(err)
  727. }
  728. defer cli.Close()
  729. // create a new context with an "example" namespace
  730. ctx := namespaces.WithNamespace(context.Background(), "default")
  731. // pull the redis image from DockerHub
  732. image, err := cli.Pull(ctx, "docker.io/library/busybox:latest", containerd.WithPullUnpack)
  733. if err != nil {
  734. fmt.Println("222")
  735. fmt.Println(err)
  736. }
  737. // create a container
  738. container, err := cli.NewContainer(
  739. ctx,
  740. "test1",
  741. containerd.WithImage(image),
  742. containerd.WithNewSnapshot("redis-server-snapshot1", image),
  743. containerd.WithNewSpec(oci.WithImageConfig(image)),
  744. )
  745. if err != nil {
  746. fmt.Println(err)
  747. }
  748. defer container.Delete(ctx, containerd.WithSnapshotCleanup)
  749. // create a task from the container
  750. task, err := container.NewTask(ctx, cio.NewCreator(cio.WithStdio))
  751. if err != nil {
  752. fmt.Println(err)
  753. }
  754. defer task.Delete(ctx)
  755. // make sure we wait before calling start
  756. exitStatusC, err := task.Wait(ctx)
  757. if err != nil {
  758. fmt.Println(err)
  759. }
  760. // call start on the task to execute the redis server
  761. if err = task.Start(ctx); err != nil {
  762. fmt.Println(err)
  763. }
  764. fmt.Println("执行完成等待")
  765. // sleep for a lil bit to see the logs
  766. time.Sleep(3 * time.Second)
  767. // kill the process and get the exit status
  768. if err = task.Kill(ctx, syscall.SIGTERM); err != nil {
  769. fmt.Println(err)
  770. }
  771. // wait for the process to fully exit and print out the exit status
  772. status := <-exitStatusC
  773. code, _, err := status.Result()
  774. if err != nil {
  775. fmt.Println(err)
  776. }
  777. fmt.Printf("redis-server exited with status: %d\n", code)
  778. }