docker.go 24 KB

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