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. "regexp"
  11. "syscall"
  12. model2 "github.com/IceWhaleTech/CasaOS/service/model"
  13. types2 "github.com/IceWhaleTech/CasaOS/types"
  14. "github.com/containerd/containerd"
  15. "github.com/containerd/containerd/cio"
  16. "github.com/containerd/containerd/namespaces"
  17. "github.com/containerd/containerd/oci"
  18. "github.com/IceWhaleTech/CasaOS/model"
  19. "github.com/IceWhaleTech/CasaOS/pkg/docker"
  20. command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
  21. "github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper"
  22. "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
  23. loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
  24. //"github.com/containerd/containerd/oci"
  25. "io"
  26. "io/ioutil"
  27. "log"
  28. "os"
  29. "strconv"
  30. "strings"
  31. "time"
  32. "github.com/docker/docker/api/types"
  33. "github.com/docker/docker/api/types/container"
  34. "github.com/docker/docker/api/types/filters"
  35. "github.com/docker/docker/api/types/mount"
  36. "github.com/docker/docker/api/types/network"
  37. client2 "github.com/docker/docker/client"
  38. "github.com/docker/go-connections/nat"
  39. )
  40. type DockerService interface {
  41. DockerPullImage(imageName string, m model2.AppNotify) error
  42. IsExistImage(imageName string) bool
  43. DockerContainerCreate(imageName string, containerDbId string, m model.CustomizationPostData, net string) (containerId string, err error)
  44. DockerContainerStart(name string) error
  45. DockerContainerStats(name string) (string, error)
  46. DockerListByName(name string) (*types.Container, error)
  47. DockerListByImage(image, version string) (*types.Container, error)
  48. DockerContainerInfo(name string) (*types.ContainerJSON, error)
  49. DockerImageRemove(name string) error
  50. DockerContainerRemove(name string, update bool) error
  51. DockerContainerStop(id string) error
  52. DockerContainerUpdateName(name, id string) (err error)
  53. DockerContainerUpdate(m model.CustomizationPostData, id string) (err error)
  54. DockerContainerLog(name string) (string, error)
  55. DockerContainerCommit(name string)
  56. DockerNetworkModelList() []types.NetworkResource
  57. DockerImageInfo(image string)
  58. GetNetWorkNameByNetWorkID(id string) (string, error)
  59. ContainerExecShell(container_id string) string
  60. }
  61. type dockerService struct {
  62. rootDir string
  63. log loger2.OLog
  64. }
  65. func (ds *dockerService) ContainerExecShell(container_id string) string {
  66. cli, _ := client2.NewClientWithOpts(client2.FromEnv)
  67. exec, err := cli.ContainerExecCreate(context.Background(), container_id, types.ExecConfig{
  68. User: "1000:1000",
  69. Cmd: []string{"echo -e \"hellow\nworld\" >> /a.txt"},
  70. })
  71. if err != nil {
  72. os.Exit(5)
  73. }
  74. err = cli.ContainerExecStart(context.Background(), exec.ID, types.ExecStartCheck{})
  75. if err != nil {
  76. fmt.Println("exec script error ", err)
  77. }
  78. return exec.ID
  79. }
  80. //创建默认网络
  81. func DockerNetwork() {
  82. cli, _ := client2.NewClientWithOpts(client2.FromEnv)
  83. defer cli.Close()
  84. d, _ := cli.NetworkList(context.Background(), types.NetworkListOptions{})
  85. for _, resource := range d {
  86. if resource.Name == docker.NETWORKNAME {
  87. return
  88. }
  89. }
  90. cli.NetworkCreate(context.Background(), docker.NETWORKNAME, types.NetworkCreate{})
  91. }
  92. //根据网络id获取网络名
  93. func (ds *dockerService) GetNetWorkNameByNetWorkID(id string) (string, error) {
  94. cli, _ := client2.NewClientWithOpts(client2.FromEnv)
  95. defer cli.Close()
  96. filter := filters.NewArgs()
  97. filter.Add("id", id)
  98. d, err := cli.NetworkList(context.Background(), types.NetworkListOptions{filter})
  99. if err == nil && len(d) > 0 {
  100. return d[0].Name, nil
  101. }
  102. return "", err
  103. }
  104. //拉取镜像
  105. func DockerPull() {
  106. cli, _ := client2.NewClientWithOpts(client2.FromEnv)
  107. defer cli.Close()
  108. authConfig := types.AuthConfig{
  109. Username: "cn-north-4@M4OW0IULZ3U6PCQPBUZC",
  110. Password: "7390181a1565f90927bbd98038436b57d6ebc66a3828d7a11dfda42b9c19d91d",
  111. }
  112. encodedJSON, err := json2.Marshal(authConfig)
  113. fmt.Println(err)
  114. authStr := base64.URLEncoding.EncodeToString(encodedJSON)
  115. reader, err := cli.ImagePull(context.Background(), "swr.cn-north-4.myhuaweicloud.com/root/swr-demo-2048:latest", types.ImagePullOptions{RegistryAuth: authStr})
  116. buf := new(bytes.Buffer)
  117. buf.ReadFrom(reader)
  118. fmt.Println(buf.String())
  119. }
  120. //拉取镜像
  121. func DockerEx() {
  122. cli, _ := client2.NewClientWithOpts(client2.FromEnv)
  123. defer cli.Close()
  124. importResponse, err := cli.ImageImport(context.Background(), types.ImageImportSource{
  125. Source: strings.NewReader("source"),
  126. SourceName: "image_source",
  127. }, "repository_name:imported", types.ImageImportOptions{
  128. Tag: "imported",
  129. Message: "A message",
  130. Changes: []string{"change1", "change2"},
  131. })
  132. response, err := ioutil.ReadAll(importResponse)
  133. if err != nil {
  134. fmt.Println(err)
  135. }
  136. importResponse.Close()
  137. println(string(response))
  138. if string(response) != "response" {
  139. fmt.Println("expected response to contain 'response', got %s", string(response))
  140. }
  141. }
  142. //func DockerContainerSize() {
  143. // cli, err := client2.NewClientWithOpts(client2.FromEnv)
  144. // //but := bytes.Buffer{}
  145. // d, err := cli.ContainerExecCreate(context.Background(), "c3adcef92bae648890941ac00e6c4024d7f2959c2e629f0b581d6a19d77b5eda")
  146. // fmt.Println(d)
  147. // st, _ := ioutil.ReadAll(d.Body)
  148. // fmt.Println(string(st))
  149. // if err != nil {
  150. // fmt.Print(err)
  151. // }
  152. //
  153. //}
  154. func (ds *dockerService) DockerImageInfo(image string) {
  155. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  156. //but := bytes.Buffer{}
  157. d, b, err := cli.ImageInspectWithRaw(context.Background(), image)
  158. st, _ := json2.Marshal(d.Config)
  159. fmt.Println(string(st))
  160. fmt.Println("换行")
  161. fmt.Println(string(b))
  162. if err != nil {
  163. fmt.Print(err)
  164. }
  165. }
  166. func MsqlExec(container string) error {
  167. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  168. ctx := context.Background()
  169. // 执行/bin/bash命令
  170. ir, err := cli.ContainerExecCreate(ctx, container, types.ExecConfig{
  171. AttachStdin: false,
  172. AttachStdout: true,
  173. AttachStderr: true,
  174. Cmd: []string{"date"},
  175. Tty: true,
  176. Env: []string{"aaa=ddd"},
  177. })
  178. err = cli.ContainerExecStart(ctx, ir.ID, types.ExecStartCheck{})
  179. fmt.Println(err)
  180. return err
  181. }
  182. func Exec(container, row, col string) (hr types.HijackedResponse, err error) {
  183. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  184. ctx := context.Background()
  185. // 执行/bin/bash命令
  186. ir, err := cli.ContainerExecCreate(ctx, container, types.ExecConfig{
  187. AttachStdin: true,
  188. AttachStdout: true,
  189. AttachStderr: true,
  190. Env: []string{"COLUMNS=" + col, "LINES=" + row},
  191. Cmd: []string{"/bin/bash"},
  192. Tty: true,
  193. })
  194. if err != nil {
  195. return
  196. }
  197. // 附加到上面创建的/bin/bash进程中
  198. hr, err = cli.ContainerExecAttach(ctx, ir.ID, types.ExecStartCheck{Detach: false, Tty: true})
  199. if err != nil {
  200. return
  201. }
  202. return
  203. }
  204. func DockerLog() {
  205. //cli, err := client2.NewClientWithOpts(client2.FromEnv)
  206. //ctx := context.Background()
  207. //ir, err := cli.ContainerLogs(ctx, "79c6fa382c330b9149e2d28d24f4d2c231cdb8cfc0710c2d268ccee13c5b24f8", types.ContainerLogsOptions{})
  208. //str, err := ioutil.ReadAll(ir)
  209. //fmt.Println(string(str))
  210. //fmt.Println(err)
  211. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  212. defer cancel()
  213. client, _ := client2.NewClientWithOpts(client2.FromEnv)
  214. reader, err := client.ContainerLogs(ctx, "79c6fa382c330b9149e2d28d24f4d2c231cdb8cfc0710c2d268ccee13c5b24f8", types.ContainerLogsOptions{})
  215. if err != nil {
  216. log.Fatal(err)
  217. }
  218. _, err = io.Copy(os.Stdout, reader)
  219. if err != nil && err != io.EOF {
  220. log.Fatal(err)
  221. }
  222. }
  223. func DockerLogs() {
  224. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  225. i, err := cli.ContainerLogs(context.Background(), "79c6fa382c330b9149e2d28d24f4d2c231cdb8cfc0710c2d268ccee13c5b24f8", types.ContainerLogsOptions{
  226. ShowStderr: true,
  227. ShowStdout: true,
  228. Timestamps: false,
  229. Follow: true,
  230. Tail: "40",
  231. })
  232. if err != nil {
  233. log.Fatal(err)
  234. }
  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. defer i.Close()
  254. }
  255. //正式内容
  256. //检查镜像是否存在
  257. func (ds *dockerService) IsExistImage(imageName string) bool {
  258. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  259. if err != nil {
  260. return false
  261. }
  262. defer cli.Close()
  263. filter := filters.NewArgs()
  264. filter.Add("reference", imageName)
  265. list, err := cli.ImageList(context.Background(), types.ImageListOptions{Filters: filter})
  266. if err == nil && len(list) > 0 {
  267. return true
  268. }
  269. return false
  270. }
  271. //安装镜像
  272. func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) error {
  273. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  274. if err != nil {
  275. return err
  276. }
  277. defer cli.Close()
  278. out, err := cli.ImagePull(context.Background(), imageName, types.ImagePullOptions{})
  279. if err != nil {
  280. return err
  281. }
  282. defer out.Close()
  283. if err != nil {
  284. return err
  285. }
  286. buf := make([]byte, 256)
  287. for {
  288. n, err := out.Read(buf)
  289. if err != nil {
  290. if err != io.EOF {
  291. fmt.Println("read error:", err)
  292. }
  293. break
  294. }
  295. if !reflect.DeepEqual(m, model2.AppNotify{}) {
  296. m.Type = types2.NOTIFY_TYPE_INSTALL_LOG
  297. m.State = 0
  298. m.Message = string(buf[:n])
  299. MyService.Notify().UpdateLog(m)
  300. }
  301. }
  302. return err
  303. }
  304. //param imageName 镜像名称
  305. //param containerDbId 数据库的id
  306. //param port 容器内部主端口
  307. //param mapPort 容器主端口映射到外部的端口
  308. //param tcp 容器其他tcp端口
  309. //param udp 容器其他udp端口
  310. func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId string, m model.CustomizationPostData, net string) (containerId string, err error) {
  311. if len(net) == 0 {
  312. net = "bridge"
  313. }
  314. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  315. if err != nil {
  316. return "", err
  317. }
  318. defer cli.Close()
  319. ports := make(nat.PortSet)
  320. portMaps := make(nat.PortMap)
  321. // ports[nat.Port(fmt.Sprint(m.PortMap)+"/tcp")] = struct{}{}
  322. // if net != "host" {
  323. // portMaps[nat.Port(fmt.Sprint(m.Port)+"/tcp")] = []nat.PortBinding{{HostIP: "", HostPort: m.PortMap}}
  324. // }
  325. port := ""
  326. for _, portMap := range m.Ports {
  327. if portMap.CommendPort == m.PortMap && portMap.Protocol == "tcp" || portMap.Protocol == "both" {
  328. port = portMap.ContainerPort
  329. }
  330. if portMap.Protocol == "tcp" {
  331. tContainer, _ := strconv.Atoi(portMap.ContainerPort)
  332. if tContainer > 0 {
  333. ports[nat.Port(portMap.ContainerPort+"/tcp")] = struct{}{}
  334. if net != "host" {
  335. portMaps[nat.Port(portMap.ContainerPort+"/tcp")] = []nat.PortBinding{{HostIP: "0.0.0.0", HostPort: portMap.CommendPort}}
  336. }
  337. }
  338. } else if portMap.Protocol == "both" {
  339. tContainer, _ := strconv.Atoi(portMap.ContainerPort)
  340. if tContainer > 0 {
  341. ports[nat.Port(portMap.ContainerPort+"/tcp")] = struct{}{}
  342. if net != "host" {
  343. portMaps[nat.Port(portMap.ContainerPort+"/tcp")] = []nat.PortBinding{{HostIP: "0.0.0.0", HostPort: portMap.CommendPort}}
  344. }
  345. }
  346. uContainer, _ := strconv.Atoi(portMap.ContainerPort)
  347. if uContainer > 0 {
  348. ports[nat.Port(portMap.ContainerPort+"/udp")] = struct{}{}
  349. if net != "host" {
  350. portMaps[nat.Port(portMap.ContainerPort+"/udp")] = []nat.PortBinding{{HostIP: "0.0.0.0", HostPort: portMap.CommendPort}}
  351. }
  352. }
  353. } else {
  354. uContainer, _ := strconv.Atoi(portMap.ContainerPort)
  355. if uContainer > 0 {
  356. ports[nat.Port(portMap.ContainerPort+"/udp")] = struct{}{}
  357. if net != "host" {
  358. portMaps[nat.Port(portMap.ContainerPort+"/udp")] = []nat.PortBinding{{HostIP: "0.0.0.0", HostPort: portMap.CommendPort}}
  359. }
  360. }
  361. }
  362. }
  363. var envArr []string
  364. for _, e := range m.Envs {
  365. if strings.HasPrefix(e.Value, "$") {
  366. envArr = append(envArr, e.Name+"="+env_helper.ReplaceDefaultENV(e.Value))
  367. continue
  368. }
  369. if len(e.Value) > 0 {
  370. if e.Value == "port_map" {
  371. envArr = append(envArr, e.Name+"="+m.PortMap)
  372. continue
  373. }
  374. envArr = append(envArr, e.Name+"="+e.Value)
  375. }
  376. }
  377. res := container.Resources{}
  378. if m.CpuShares > 0 {
  379. res.CPUShares = m.CpuShares
  380. }
  381. if m.Memory > 0 {
  382. res.Memory = m.Memory << 20
  383. }
  384. for _, p := range m.Devices {
  385. if len(p.Path) > 0 {
  386. res.Devices = append(res.Devices, container.DeviceMapping{PathOnHost: p.Path, PathInContainer: p.ContainerPath})
  387. }
  388. }
  389. hostConfingBind := []string{}
  390. // volumes bind
  391. volumes := []mount.Mount{}
  392. for _, v := range m.Volumes {
  393. path := v.Path
  394. if len(path) == 0 {
  395. path = docker.GetDir(containerDbId, v.ContainerPath)
  396. if len(path) == 0 {
  397. continue
  398. }
  399. }
  400. path = strings.ReplaceAll(path, "$AppID", containerDbId)
  401. reg1 := regexp.MustCompile(`([^<>/\\\|:""\*\?]+\.\w+$)`)
  402. result1 := reg1.FindAllStringSubmatch(path, -1)
  403. if len(result1) == 0 {
  404. err = file.IsNotExistMkDir(path)
  405. if err != nil {
  406. ds.log.Error("mkdir error", err)
  407. continue
  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 NewDcokerService(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. }