dockerd.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. package containers
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "path"
  7. "strings"
  8. "time"
  9. "github.com/coroot/coroot-node-agent/common"
  10. "github.com/coroot/coroot-node-agent/proc"
  11. "github.com/coroot/logparser"
  12. "github.com/docker/docker/client"
  13. "github.com/vishvananda/netns"
  14. "inet.af/netaddr"
  15. )
  16. const dockerdTimeout = 30 * time.Second
  17. var (
  18. dockerdClient *client.Client
  19. )
  20. func DockerdInit() error {
  21. c, err := client.NewClientWithOpts(
  22. client.WithHost("unix://" + proc.HostPath("/run/docker.sock")),
  23. )
  24. if err != nil {
  25. return err
  26. }
  27. ctx, cancelFn := context.WithTimeout(context.Background(), dockerdTimeout)
  28. defer cancelFn()
  29. if _, err := c.Ping(ctx); err != nil {
  30. return err
  31. }
  32. c.NegotiateAPIVersion(ctx)
  33. dockerdClient = c
  34. return nil
  35. }
  36. func DockerdInspect(containerID string) (*ContainerMetadata, error) {
  37. if dockerdClient == nil {
  38. return nil, fmt.Errorf("dockerd client not initialized")
  39. }
  40. ctx, cancel := context.WithTimeout(context.Background(), dockerdTimeout)
  41. defer cancel()
  42. c, err := dockerdClient.ContainerInspect(ctx, containerID)
  43. if err != nil {
  44. return nil, err
  45. }
  46. res := &ContainerMetadata{
  47. name: strings.TrimPrefix(c.Name, "/"),
  48. labels: c.Config.Labels,
  49. image: c.Config.Image,
  50. volumes: map[string]string{},
  51. hostListens: map[string][]netaddr.IPPort{},
  52. networks: map[string]ContainerNetwork{},
  53. env: map[string]string{},
  54. }
  55. for _, m := range c.Mounts {
  56. res.volumes[m.Destination] = common.ParseKubernetesVolumeSource(m.Source)
  57. }
  58. if c.LogPath != "" && c.HostConfig.LogConfig.Type == "json-file" {
  59. res.logPath = c.LogPath
  60. res.logDecoder = logparser.DockerJsonDecoder{}
  61. }
  62. if c.NetworkSettings != nil {
  63. addrs := map[netaddr.IPPort]struct{}{}
  64. for port, bindings := range c.NetworkSettings.Ports {
  65. if port.Proto() != "tcp" {
  66. continue
  67. }
  68. for _, b := range bindings {
  69. if ipp, err := netaddr.ParseIPPort(b.HostIP + ":" + b.HostPort); err == nil {
  70. addrs[ipp] = struct{}{}
  71. }
  72. }
  73. }
  74. if len(addrs) > 0 {
  75. s := make([]netaddr.IPPort, 0, len(addrs))
  76. for addr := range addrs {
  77. if common.PortFilter.ShouldBeSkipped(addr.Port()) {
  78. continue
  79. }
  80. s = append(s, addr)
  81. }
  82. res.hostListens["dockerd"] = s
  83. }
  84. for name, network := range c.NetworkSettings.Networks {
  85. res.networks[name] = ContainerNetwork{
  86. NetworkID: network.NetworkID,
  87. }
  88. }
  89. }
  90. if c.Config != nil {
  91. for _, value := range c.Config.Env {
  92. idx := strings.Index(value, "=")
  93. if idx < 0 {
  94. continue
  95. }
  96. k := value[:idx]
  97. v := value[idx+1:]
  98. res.env[k] = v
  99. }
  100. }
  101. return res, nil
  102. }
  103. func FindNetworkLoadBalancerNs(networkId string) netns.NsHandle {
  104. basePath := "/run/docker/netns"
  105. files, err := os.ReadDir(proc.HostPath(basePath))
  106. if err != nil {
  107. return -1
  108. }
  109. for _, f := range files {
  110. if !f.Type().IsRegular() || !strings.HasPrefix(f.Name(), "lb_") {
  111. continue
  112. }
  113. idPrefix := strings.Split(f.Name(), "_")[1]
  114. if strings.HasPrefix(networkId, idPrefix) {
  115. ns, _ := netns.GetFromPath(proc.HostPath(path.Join(basePath, f.Name())))
  116. return ns
  117. }
  118. }
  119. return -1
  120. }