diff --git a/internal/context/context.go b/internal/context/context.go index 40817699..8327e911 100644 --- a/internal/context/context.go +++ b/internal/context/context.go @@ -218,7 +218,8 @@ func matchContainerID(regex, lines string) string { // https://www.kernel.org/doc/Documentation/filesystems/proc.txt section 3.5 re := regexp.MustCompilePOSIX("^[0-9]+ [0-9]+ [0-9]+:[0-9]+ /") if re.MatchString(lines) { - regex = fmt.Sprintf("containers/%v", regex) + // Anchor the id to a per-container file so it matches whether or not the path keeps a containers/ segment (#452). + regex = fmt.Sprintf("/%v/(hostname|hosts|resolv\\.conf)", regex) } re = regexp.MustCompilePOSIX(regex) diff --git a/internal/context/context_test.go b/internal/context/context_test.go index 4e8f8557..00b0c89f 100644 --- a/internal/context/context_test.go +++ b/internal/context/context_test.go @@ -128,6 +128,42 @@ func TestGetCurrentContainerIDMountInfo(t *testing.T) { assert.Equal(t, id, GetCurrentContainerID(filepaths...), "id mismatch on mountinfo") } +func TestGetCurrentContainerIDSeparateMount(t *testing.T) { + // Test specific to https://github.com/nginx-proxy/docker-gen/issues/452 where /var/lib/docker/containers + // is a separate mount, so per-container files appear as //hosts without a containers/ segment. + hostname := os.Getenv("HOSTNAME") + defer os.Setenv("HOSTNAME", hostname) + os.Setenv("HOSTNAME", "customhostname") + + id := ids[2] + overlay := "e1fab975d5ffd51474b11a964c82c3bfda1c0e82aec6845a1f12c8150bf61419" + + content := map[string]string{ + "cpuset": "/", + "cgroup": "0::/", + "mountinfo": fmt.Sprintf(`705 661 0:96 / / rw,relatime master:192 - overlay overlay rw,upperdir=/var/lib/docker/overlay2/%[2]v/diff,workdir=/var/lib/docker/overlay2/%[2]v/work,index=off +713 705 8:3 /%[1]v/resolv.conf /etc/resolv.conf rw,relatime - ext4 /dev/sda3 rw +714 705 8:3 /%[1]v/hostname /etc/hostname rw,relatime - ext4 /dev/sda3 rw +715 705 8:3 /%[1]v/hosts /etc/hosts rw,relatime - ext4 /dev/sda3 rw`, id, overlay), + } + + var filepaths []string + for _, key := range fileKeys { + file, err := os.CreateTemp("", key) + if err != nil { + t.Fatal(err) + } + defer os.Remove(file.Name()) + if _, err = file.WriteString(content[key]); err != nil { + t.Fatal(err) + } + filepaths = append(filepaths, file.Name()) + } + + // The id must come from the //hosts path field, not the overlay2 hex in the mount options. + assert.Equal(t, id, GetCurrentContainerID(filepaths...), "id mismatch on separate-mount mountinfo") +} + func TestGetCurrentContainerEmpty(t *testing.T) { assert.Equal(t, "", GetCurrentContainerID()) }