diff --git a/v3/internal/crossagent/cross_agent_tests/docker_container_id/cases.json b/v3/internal/crossagent/cross_agent_tests/docker_container_id/cases.json index f1f9c0e61..4f9717792 100644 --- a/v3/internal/crossagent/cross_agent_tests/docker_container_id/cases.json +++ b/v3/internal/crossagent/cross_agent_tests/docker_container_id/cases.json @@ -1,4 +1,9 @@ [ + { + "filename": "mountinfo.txt", + "containerId": "ec807d5258c06c355c07e2acb700f9029d820afe5836d6a7e19764773dc790f5", + "expectedMetrics": null + }, { "filename": "docker-0.9.1.txt", "containerId": "f37a7e4d17017e7bf774656b19ca4360c6cdc4951c86700a464101d0d9ce97ee", diff --git a/v3/internal/crossagent/cross_agent_tests/docker_container_id/mountinfo.txt b/v3/internal/crossagent/cross_agent_tests/docker_container_id/mountinfo.txt new file mode 100644 index 000000000..cb1f3850a --- /dev/null +++ b/v3/internal/crossagent/cross_agent_tests/docker_container_id/mountinfo.txt @@ -0,0 +1,21 @@ +787 677 0:205 / / rw,relatime master:211 - overlay overlay rw,lowerdir=/var/lib/docker/overlay2/l/4LWPEJQQP4ZTPKM5BERIGWX63N:/var/lib/docker/overlay2/l/TFA7XS7THOIUG2XOSPD63ZTVCW:/var/lib/docker/overlay2/l/LU2GER2CKIEZEN3O3ZM7MMN7FE:/var/lib/docker/overlay2/l/C56BBR5IUNPYU7VFQYBD7B6TRV:/var/lib/docker/overlay2/l/3H5SWJGWS5HFV3EVBSXW3Z5EWP:/var/lib/docker/overlay2/l/FZSKODSSYVKREFDR7EOHUS4C52:/var/lib/docker/overlay2/l/X4HBP5ZZCMRNDQROSJCS3FPJXN:/var/lib/docker/overlay2/l/YXPJDSIAVYL3AQXJOMJKC2UBQ7:/var/lib/docker/overlay2/l/S3H6KC6FPHLB4YMN24TNILEUIG:/var/lib/docker/overlay2/l/Y3UADAXTZUWRMXPRAFLWZEHC4O,upperdir=/var/lib/docker/overlay2/88a9371f4db27c41c3013cea0af17d1a51d8a591a659dafe0ee4f4f5aa07ea34/diff,workdir=/var/lib/docker/overlay2/88a9371f4db27c41c3013cea0af17d1a51d8a591a659dafe0ee4f4f5aa07ea34/work +788 787 0:208 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw +789 787 0:209 / /dev rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755 +790 789 0:210 / /dev/pts rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=666 +791 787 0:211 / /sys ro,nosuid,nodev,noexec,relatime - sysfs sysfs ro +792 791 0:33 / /sys/fs/cgroup ro,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw +793 789 0:207 / /dev/mqueue rw,nosuid,nodev,noexec,relatime - mqueue mqueue rw +794 789 0:212 / /dev/shm rw,nosuid,nodev,noexec,relatime - tmpfs shm rw,size=65536k +795 787 254:1 /docker/containers/ec807d5258c06c355c07e2acb700f9029d820afe5836d6a7e19764773dc790f5/resolv.conf /etc/resolv.conf rw,relatime - ext4 /dev/vda1 rw +796 787 254:1 /docker/containers/ec807d5258c06c355c07e2acb700f9029d820afe5836d6a7e19764773dc790f5/hostname /etc/hostname rw,relatime - ext4 /dev/vda1 rw +797 787 254:1 /docker/containers/ec807d5258c06c355c07e2acb700f9029d820afe5836d6a7e19764773dc790f5/hosts /etc/hosts rw,relatime - ext4 /dev/vda1 rw +678 788 0:208 /bus /proc/bus ro,nosuid,nodev,noexec,relatime - proc proc rw +679 788 0:208 /fs /proc/fs ro,nosuid,nodev,noexec,relatime - proc proc rw +680 788 0:208 /irq /proc/irq ro,nosuid,nodev,noexec,relatime - proc proc rw +681 788 0:208 /sys /proc/sys ro,nosuid,nodev,noexec,relatime - proc proc rw +682 788 0:208 /sysrq-trigger /proc/sysrq-trigger ro,nosuid,nodev,noexec,relatime - proc proc rw +683 788 0:209 /null /proc/kcore rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755 +684 788 0:209 /null /proc/keys rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755 +685 788 0:209 /null /proc/timer_list rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755 +686 788 0:209 /null /proc/sched_debug rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755 +687 791 0:213 / /sys/firmware ro,relatime - tmpfs tmpfs ro \ No newline at end of file diff --git a/v3/internal/sysinfo/docker.go b/v3/internal/sysinfo/docker.go index 97deee896..d7499bb22 100644 --- a/v3/internal/sysinfo/docker.go +++ b/v3/internal/sysinfo/docker.go @@ -12,6 +12,7 @@ import ( "os" "regexp" "runtime" + "strings" ) var ( @@ -31,8 +32,18 @@ func DockerID() (string, error) { return "", err } defer f.Close() + id, err := parseDockerID(f) - return parseDockerID(f) + // Attempt mountinfo file lookup if DockerID not found in cgroup file + if err == ErrDockerNotFound { + f, err := os.Open("/proc/self/mountinfo") + if err != nil { + return "", err + } + defer f.Close() + return parseDockerIDMountInfo(f) + } + return id, err } var ( @@ -43,6 +54,27 @@ var ( dockerIDRegex = regexp.MustCompile(dockerIDRegexRaw) ) +func parseDockerIDMountInfo(r io.Reader) (string, error) { + // Each Line in the mountinfo file starts with a set of IDs before showing the path file we actually want + // 1. Mount ID + // 2. Parent ID + // 3. Major and minor device numbers + // 4. Path to ContainerID + + scanner := bufio.NewScanner(r) + for scanner.Scan() { + line := scanner.Text() + if strings.Contains(line, "/docker/containers/") { + id := dockerIDRegex.FindString(line) + if err := validateDockerID(id); err != nil { + return "", err + } + return id, nil + } + } + return "", ErrDockerNotFound +} + func parseDockerID(r io.Reader) (string, error) { // Each line in the cgroup file consists of three colon delimited fields. // 1. hierarchy ID - we don't care about this @@ -51,7 +83,6 @@ func parseDockerID(r io.Reader) (string, error) { // // Example // 5:cpuacct,cpu,cpuset:/daemons - var id string for scanner := bufio.NewScanner(r); scanner.Scan(); { @@ -77,7 +108,6 @@ func parseDockerID(r io.Reader) (string, error) { } return id, nil } - return "", ErrDockerNotFound } diff --git a/v3/internal/sysinfo/docker_test.go b/v3/internal/sysinfo/docker_test.go index 0bfd20af3..485383e9a 100644 --- a/v3/internal/sysinfo/docker_test.go +++ b/v3/internal/sysinfo/docker_test.go @@ -33,7 +33,11 @@ func TestDockerIDCrossAgent(t *testing.T) { got, _ := parseDockerID(bytes.NewReader(input)) if got != test.ID { - t.Errorf("%s != %s", got, test.ID) + mountInfoAttempt, _ := parseDockerIDMountInfo(bytes.NewReader(input)) + if mountInfoAttempt != test.ID { + t.Errorf("MountInfo Attempt: %s != %s", mountInfoAttempt, test.ID) + t.Errorf("Traditional Attempt: %s != %s", got, test.ID) + } } } }