-
Notifications
You must be signed in to change notification settings - Fork 21
Consolidate duplicate container detection into sys.DetectContainerID #3522
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
f2d35e6
ce35fd9
078e4fe
ba31964
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| package sys | ||
|
|
||
| import ( | ||
| "bufio" | ||
| "os" | ||
| "strings" | ||
|
|
||
|
|
@@ -9,35 +10,86 @@ import ( | |
|
|
||
| var logSys = logger.New("sys:container") | ||
|
|
||
| // containerIndicators lists the cgroup path substrings that indicate a container environment. | ||
| var containerIndicators = []string{"docker", "containerd", "kubepods", "lxc"} | ||
|
|
||
| // IsRunningInContainer detects if the current process is running inside a container. | ||
| func IsRunningInContainer() bool { | ||
| detected, _ := DetectContainerID() | ||
| return detected | ||
| } | ||
|
|
||
| // DetectContainerID detects if the current process is running inside a container | ||
| // and attempts to extract the container ID from cgroup entries. | ||
| // It returns (isContainer, containerID). The containerID may be empty even when | ||
| // a container is detected (e.g., via /.dockerenv or environment variable). | ||
| func DetectContainerID() (bool, string) { | ||
| logSys.Print("Detecting container environment") | ||
|
|
||
| // Method 1: Check for /.dockerenv file (Docker-specific) | ||
| if _, err := os.Stat("/.dockerenv"); err == nil { | ||
| logSys.Print("Container detected via /.dockerenv") | ||
| return true | ||
| // Still try to extract container ID from cgroup | ||
| if id := extractContainerIDFromCgroup(); id != "" { | ||
| return true, id | ||
| } | ||
| return true, "" | ||
| } | ||
|
|
||
| // Method 2: Check /proc/1/cgroup for container indicators | ||
| data, err := os.ReadFile("/proc/1/cgroup") | ||
| if err == nil { | ||
| content := string(data) | ||
| if strings.Contains(content, "docker") || | ||
| strings.Contains(content, "containerd") || | ||
| strings.Contains(content, "kubepods") || | ||
| strings.Contains(content, "lxc") { | ||
| logSys.Print("Container detected via /proc/1/cgroup") | ||
| return true | ||
| for _, indicator := range containerIndicators { | ||
| if strings.Contains(content, indicator) { | ||
| logSys.Print("Container detected via /proc/1/cgroup") | ||
| if id := extractContainerIDFromContent(content); id != "" { | ||
| return true, id | ||
| } | ||
| return true, "" | ||
| } | ||
|
||
| } | ||
| } | ||
|
|
||
| // Method 3: Check environment variable (set by Dockerfile) | ||
| if os.Getenv("RUNNING_IN_CONTAINER") == "true" { | ||
| logSys.Print("Container detected via RUNNING_IN_CONTAINER env var") | ||
| return true | ||
| return true, "" | ||
| } | ||
|
|
||
| logSys.Print("No container indicators found, running on host") | ||
| return false | ||
| return false, "" | ||
| } | ||
|
|
||
| // extractContainerIDFromCgroup reads /proc/1/cgroup and tries to extract a container ID. | ||
| func extractContainerIDFromCgroup() string { | ||
| data, err := os.ReadFile("/proc/1/cgroup") | ||
| if err != nil { | ||
| return "" | ||
| } | ||
| return extractContainerIDFromContent(string(data)) | ||
| } | ||
|
|
||
| // extractContainerIDFromContent parses cgroup content line-by-line and extracts a container ID. | ||
| // It looks for path segments following "docker" or "containerd" that are at least 12 characters long. | ||
| func extractContainerIDFromContent(content string) string { | ||
| scanner := bufio.NewScanner(strings.NewReader(content)) | ||
| for scanner.Scan() { | ||
| line := scanner.Text() | ||
| if strings.Contains(line, "docker") || strings.Contains(line, "containerd") { | ||
| parts := strings.Split(line, "/") | ||
| for i, part := range parts { | ||
| if (part == "docker" || part == "containerd") && i+1 < len(parts) { | ||
| containerID := parts[i+1] | ||
| if len(containerID) >= 12 { | ||
| return containerID | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| if err := scanner.Err(); err != nil { | ||
| logSys.Printf("Error scanning cgroup content: %v", err) | ||
| } | ||
| return "" | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test still uses the name TestDetectContainerized even though it now calls sys.DetectContainerID. Renaming the test to match the public API would improve clarity and makes failures easier to interpret when reading
go testoutput.