docker.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874
  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) 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 = "oasis"
  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) 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. path := docker.GetDir(name, "/config")
  469. if !file.CheckNotExist(path) {
  470. file.RMDir(path)
  471. }
  472. if err != nil {
  473. return err
  474. }
  475. return err
  476. }
  477. //删除镜像
  478. func (ds *dockerService) DockerImageRemove(name string) error {
  479. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  480. if err != nil {
  481. return err
  482. }
  483. defer cli.Close()
  484. imageList, err := cli.ImageList(context.Background(), types.ImageListOptions{})
  485. imageId := ""
  486. Loop:
  487. for _, ig := range imageList {
  488. for _, i := range ig.RepoTags {
  489. if i == name {
  490. imageId = ig.ID
  491. break Loop
  492. }
  493. }
  494. }
  495. _, err = cli.ImageRemove(context.Background(), imageId, types.ImageRemoveOptions{})
  496. return err
  497. }
  498. func DockerImageRemove(name string) error {
  499. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  500. if err != nil {
  501. return err
  502. }
  503. defer cli.Close()
  504. imageList, err := cli.ImageList(context.Background(), types.ImageListOptions{})
  505. imageId := ""
  506. Loop:
  507. for _, ig := range imageList {
  508. fmt.Println(ig.RepoDigests)
  509. fmt.Println(ig.Containers)
  510. for _, i := range ig.RepoTags {
  511. if i == name {
  512. imageId = ig.ID
  513. break Loop
  514. }
  515. }
  516. }
  517. _, err = cli.ImageRemove(context.Background(), imageId, types.ImageRemoveOptions{})
  518. return err
  519. }
  520. //停止镜像
  521. func (ds *dockerService) DockerContainerStop(id string) error {
  522. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  523. if err != nil {
  524. return err
  525. }
  526. defer cli.Close()
  527. err = cli.ContainerStop(context.Background(), id, nil)
  528. return err
  529. }
  530. //启动容器
  531. func (ds *dockerService) DockerContainerStart(name string) error {
  532. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  533. if err != nil {
  534. return err
  535. }
  536. defer cli.Close()
  537. err = cli.ContainerStart(context.Background(), name, types.ContainerStartOptions{})
  538. return err
  539. }
  540. //查看日志
  541. func (ds *dockerService) DockerContainerLog(name string) (string, error) {
  542. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  543. if err != nil {
  544. return "", err
  545. }
  546. defer cli.Close()
  547. body, err := cli.ContainerLogs(context.Background(), name, types.ContainerLogsOptions{ShowStderr: true, ShowStdout: true})
  548. if err != nil {
  549. return "", err
  550. }
  551. defer body.Close()
  552. content, err := ioutil.ReadAll(body)
  553. if err != nil {
  554. return "", err
  555. }
  556. return string(content), nil
  557. }
  558. func DockerContainerStats1() error {
  559. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  560. if err != nil {
  561. return err
  562. }
  563. defer cli.Close()
  564. dss, err := cli.ContainerStats(context.Background(), "dockermysql", false)
  565. if err != nil {
  566. return err
  567. }
  568. defer dss.Body.Close()
  569. sts, err := ioutil.ReadAll(dss.Body)
  570. if err != nil {
  571. return err
  572. }
  573. fmt.Println(string(sts))
  574. return nil
  575. }
  576. //获取容器状态
  577. func (ds *dockerService) DockerContainerStats(name string) (string, error) {
  578. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  579. if err != nil {
  580. return "", err
  581. }
  582. defer cli.Close()
  583. dss, err := cli.ContainerStats(context.Background(), name, false)
  584. if err != nil {
  585. return "", err
  586. }
  587. defer dss.Body.Close()
  588. sts, err := ioutil.ReadAll(dss.Body)
  589. if err != nil {
  590. return "", err
  591. }
  592. return string(sts), nil
  593. }
  594. //备份容器
  595. func (ds *dockerService) DockerContainerCommit(name string) {
  596. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  597. if err != nil {
  598. fmt.Println(err)
  599. }
  600. defer cli.Close()
  601. d, err := cli.ContainerInspect(context.Background(), name)
  602. dss, err := cli.ContainerCommit(context.Background(), name, types.ContainerCommitOptions{Reference: "test", Config: d.Config})
  603. if err != nil {
  604. fmt.Println(err)
  605. }
  606. fmt.Println(dss)
  607. }
  608. func (ds *dockerService) DockerListByName(name string) (*types.Container, error) {
  609. cli, _ := client2.NewClientWithOpts(client2.FromEnv)
  610. defer cli.Close()
  611. filter := filters.NewArgs()
  612. filter.Add("name", name)
  613. containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{Filters: filter})
  614. if err != nil {
  615. return &types.Container{}, err
  616. }
  617. return &containers[0], nil
  618. }
  619. func (ds *dockerService) DockerListByImage(image, version string) (*types.Container, error) {
  620. cli, _ := client2.NewClientWithOpts(client2.FromEnv)
  621. defer cli.Close()
  622. filter := filters.NewArgs()
  623. filter.Add("ancestor", image+":"+version)
  624. containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{Filters: filter})
  625. if err != nil {
  626. return nil, err
  627. }
  628. if len(containers) == 0 {
  629. return nil, nil
  630. }
  631. return &containers[0], nil
  632. }
  633. //获取容器详情
  634. func (ds *dockerService) DockerContainerInfo(name string) (*types.ContainerJSON, error) {
  635. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  636. if err != nil {
  637. return &types.ContainerJSON{}, err
  638. }
  639. defer cli.Close()
  640. d, err := cli.ContainerInspect(context.Background(), name)
  641. if err != nil {
  642. return &types.ContainerJSON{}, err
  643. }
  644. return &d, nil
  645. }
  646. //更新容器
  647. //param shares cpu优先级
  648. //param containerDbId 数据库的id
  649. //param port 容器内部主端口
  650. //param mapPort 容器主端口映射到外部的端口
  651. //param tcp 容器其他tcp端口
  652. //param udp 容器其他udp端口
  653. func (ds *dockerService) DockerContainerUpdate(m model.CustomizationPostData, id string) (err error) {
  654. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  655. if err != nil {
  656. return err
  657. }
  658. defer cli.Close()
  659. //重启策略
  660. rp := container.RestartPolicy{
  661. Name: "",
  662. MaximumRetryCount: 0,
  663. }
  664. if len(m.Restart) > 0 {
  665. rp.Name = m.Restart
  666. }
  667. res := container.Resources{}
  668. if m.Memory > 0 {
  669. res.Memory = m.Memory * 1024 * 1024
  670. res.MemorySwap = -1
  671. }
  672. if m.CpuShares > 0 {
  673. res.CPUShares = m.CpuShares
  674. }
  675. for _, p := range m.Devices {
  676. res.Devices = append(res.Devices, container.DeviceMapping{PathOnHost: p.Path, PathInContainer: p.ContainerPath})
  677. }
  678. _, err = cli.ContainerUpdate(context.Background(), id, container.UpdateConfig{RestartPolicy: rp, Resources: res})
  679. if err != nil {
  680. return err
  681. }
  682. return
  683. }
  684. //更新容器名称
  685. //param name 容器名称
  686. //param id 老的容器名称
  687. func (ds *dockerService) DockerContainerUpdateName(name, id string) (err error) {
  688. cli, err := client2.NewClientWithOpts(client2.FromEnv)
  689. if err != nil {
  690. return err
  691. }
  692. defer cli.Close()
  693. err = cli.ContainerRename(context.Background(), id, name)
  694. if err != nil {
  695. return err
  696. }
  697. return
  698. }
  699. //获取网络列表
  700. func (ds *dockerService) DockerNetworkModelList() []types.NetworkResource {
  701. cli, _ := client2.NewClientWithOpts(client2.FromEnv)
  702. defer cli.Close()
  703. networks, _ := cli.NetworkList(context.Background(), types.NetworkListOptions{})
  704. return networks
  705. }
  706. func NewDcokerService(log loger2.OLog) DockerService {
  707. return &dockerService{rootDir: command2.ExecResultStr(`source ./shell/helper.sh ;GetDockerRootDir`), log: log}
  708. }
  709. // ---------------------------------------test------------------------------------
  710. //func ServiceCreate() {
  711. // cli, err := client2.NewClientWithOpts(client2.FromEnv)
  712. // r, err := cli.ServiceCreate(context.Background(), swarm.ServiceSpec{}, types.ServiceCreateOptions{})
  713. // if err != nil {
  714. // fmt.Println("error", err)
  715. // }
  716. //
  717. //
  718. //}
  719. func Containerd() {
  720. // create a new client connected to the default socket path for containerd
  721. cli, err := containerd.New("/run/containerd/containerd.sock")
  722. if err != nil {
  723. fmt.Println("111")
  724. fmt.Println(err)
  725. }
  726. defer cli.Close()
  727. // create a new context with an "example" namespace
  728. ctx := namespaces.WithNamespace(context.Background(), "default")
  729. // pull the redis image from DockerHub
  730. image, err := cli.Pull(ctx, "docker.io/library/busybox:latest", containerd.WithPullUnpack)
  731. if err != nil {
  732. fmt.Println("222")
  733. fmt.Println(err)
  734. }
  735. // create a container
  736. container, err := cli.NewContainer(
  737. ctx,
  738. "test1",
  739. containerd.WithImage(image),
  740. containerd.WithNewSnapshot("redis-server-snapshot1", image),
  741. containerd.WithNewSpec(oci.WithImageConfig(image)),
  742. )
  743. if err != nil {
  744. fmt.Println(err)
  745. }
  746. defer container.Delete(ctx, containerd.WithSnapshotCleanup)
  747. // create a task from the container
  748. task, err := container.NewTask(ctx, cio.NewCreator(cio.WithStdio))
  749. if err != nil {
  750. fmt.Println(err)
  751. }
  752. defer task.Delete(ctx)
  753. // make sure we wait before calling start
  754. exitStatusC, err := task.Wait(ctx)
  755. if err != nil {
  756. fmt.Println(err)
  757. }
  758. // call start on the task to execute the redis server
  759. if err = task.Start(ctx); err != nil {
  760. fmt.Println(err)
  761. }
  762. fmt.Println("执行完成等待")
  763. // sleep for a lil bit to see the logs
  764. time.Sleep(3 * time.Second)
  765. // kill the process and get the exit status
  766. if err = task.Kill(ctx, syscall.SIGTERM); err != nil {
  767. fmt.Println(err)
  768. }
  769. // wait for the process to fully exit and print out the exit status
  770. status := <-exitStatusC
  771. code, _, err := status.Result()
  772. if err != nil {
  773. fmt.Println(err)
  774. }
  775. fmt.Printf("redis-server exited with status: %d\n", code)
  776. }