docker.go 25 KB

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