detached 6b4468e

feat: Enhance Gordon container auto-detection in proxy routing

- Add `detectGordonContainer()` method to automatically find Gordon container
- Support multiple detection strategies: hostname, container processes, and container names
- Improve container routing by dynamically identifying the correct container
- Add debug logging for container detection process
- Remove hardcoded "gordon-server" container ID
- Enhance flexibility for different container runtime environments
commit
6b4468ef1be619136bfc247c46a10ea5f22d9e08
author
bamen · · 2025-03-10 14:00 UTC
parent
de0c4ec
signature
unsigned
2 files · +93 -5
M internal/proxy/routes.go +1 -1
@@ -152,7 +152,7 @@ func (p *Proxy) configureRoutes() {
152152 if err != nil {
153153 // Connection failed, check if container exists but has a new IP
154154 containerID := route.ContainerID
155- if containerID != "" && containerID != "gordon-server" {
155+ if containerID != "" {
156156 // Try to get container info and check if it has a different IP
157157 containerInfo, err := docker.GetContainerInfo(containerID)
158158 if err == nil && containerInfo.NetworkSettings != nil {
@@ -152,7 +152,7 @@ func (p *Proxy) configureRoutes() {
152 if err != nil {152 if err != nil {
153 // Connection failed, check if container exists but has a new IP153 // Connection failed, check if container exists but has a new IP
154 containerID := route.ContainerID154 containerID := route.ContainerID
155- if containerID != "" && containerID != "gordon-server" {155+ if containerID != "" {
156 // Try to get container info and check if it has a different IP156 // Try to get container info and check if it has a different IP
157 containerInfo, err := docker.GetContainerInfo(containerID)157 containerInfo, err := docker.GetContainerInfo(containerID)
158 if err == nil && containerInfo.NetworkSettings != nil {158 if err == nil && containerInfo.NetworkSettings != nil {
M internal/proxy/server.go +92 -4
@@ -6,6 +6,7 @@ import (
66 "fmt"
77 "net/http"
88 "os"
9+ "strings"
910 "time"
1011
1112 "github.com/bnema/gordon/pkg/docker"
@@ -95,17 +96,21 @@ func (p *Proxy) Start() error {
9596 p.mu.Lock()
9697 // Only add if it doesn't already exist
9798 if _, exists := p.routes[adminDomain]; !exists {
99+ // Auto-detect the Gordon container name
100+ containerName := p.detectGordonContainer()
101+
98102 p.routes[adminDomain] = &ProxyRouteInfo{
99103 Domain: adminDomain,
100104 ContainerIP: containerIP,
101105 ContainerPort: p.app.GetConfig().Http.Port,
102- ContainerID: "gordon-server",
103- Protocol: "http", // Gordon server uses HTTP internally
106+ ContainerID: containerName, // Use auto-detected container name
107+ Protocol: "http", // Gordon server uses HTTP internally
104108 Path: "/",
105109 Active: true,
106110 }
107111 log.Info("Added special route for admin domain",
108112 "domain", adminDomain,
113+ "container", containerName,
109114 "target", fmt.Sprintf("http://%s:%s", containerIP, p.app.GetConfig().Http.Port))
110115 }
111116
@@ -113,12 +118,15 @@ func (p *Proxy) Start() error {
113118 rootDomain := p.app.GetConfig().Http.Domain
114119 if rootDomain != "" && rootDomain != adminDomain {
115120 if _, exists := p.routes[rootDomain]; !exists {
121+ // Use the same auto-detected container name
122+ containerName := p.detectGordonContainer()
123+
116124 p.routes[rootDomain] = &ProxyRouteInfo{
117125 Domain: rootDomain,
118126 ContainerIP: containerIP,
119127 ContainerPort: p.app.GetConfig().Http.Port,
120- ContainerID: "gordon-server",
121- Protocol: "http", // Gordon server uses HTTP internally
128+ ContainerID: containerName, // Use auto-detected container name
129+ Protocol: "http", // Gordon server uses HTTP internally
122130 Path: "/",
123131 Active: true,
124132 }
@@ -389,3 +397,83 @@ func (p *Proxy) checkExternalPortAccess() {
389397 log.Info("External HTTPS port 443 is accessible")
390398 }
391399 }
400+
401+// detectGordonContainer attempts to find the Gordon container automatically
402+func (p *Proxy) detectGordonContainer() string {
403+ // Check if we're running inside a container
404+ if docker.IsRunningInContainer() {
405+ log.Debug("Detected we're running in a container")
406+
407+ // Get our hostname which should be the container ID in Docker/Podman
408+ hostname := os.Getenv("HOSTNAME")
409+ if hostname != "" {
410+ // Check if there's a container with this hostname
411+ containers, err := docker.ListRunningContainers()
412+ if err == nil {
413+ for _, container := range containers {
414+ // Check if this container is us by comparing hostname with container ID
415+ if strings.HasPrefix(hostname, container.ID) {
416+ // This is our container
417+ containerName := strings.TrimLeft(container.Names[0], "/")
418+ log.Debug("Auto-detected Gordon container name from hostname", "container_name", containerName)
419+ return containerName
420+ }
421+ }
422+ } else {
423+ log.Debug("Could not list containers when checking hostname", "error", err)
424+ }
425+ }
426+ }
427+
428+ // Try to find Gordon by examining container processes
429+ containers, err := docker.ListRunningContainers()
430+ if err == nil {
431+ for _, container := range containers {
432+ containerID := container.ID
433+
434+ // Check container processes for Gordon
435+ containerLogs, err := docker.GetContainerLogs(containerID)
436+ if err == nil && (strings.Contains(containerLogs, "/gordon") || strings.Contains(containerLogs, "serve")) {
437+ containerName := strings.TrimLeft(container.Names[0], "/")
438+ log.Debug("Auto-detected Gordon container by process", "container_name", containerName)
439+ return containerName
440+ } else if err != nil {
441+ log.Debug("Could not get container logs", "container_id", containerID, "error", err)
442+ }
443+
444+ // Check container command for Gordon
445+ if len(container.Command) > 0 && strings.Contains(container.Command, "gordon") {
446+ containerName := strings.TrimLeft(container.Names[0], "/")
447+ log.Debug("Auto-detected Gordon container by command", "container_name", containerName)
448+ return containerName
449+ }
450+ }
451+ } else {
452+ log.Debug("Could not list containers when checking processes", "error", err)
453+ }
454+
455+ // If we couldn't detect from processes, try to find a container with gordon in the name or image
456+ if err == nil {
457+ for _, container := range containers {
458+ // Check container names for "gordon"
459+ for _, name := range container.Names {
460+ if strings.Contains(strings.ToLower(name), "gordon") {
461+ containerName := strings.TrimLeft(name, "/")
462+ log.Debug("Auto-detected Gordon container by name", "container_name", containerName)
463+ return containerName
464+ }
465+ }
466+
467+ // Check image name for "gordon"
468+ if strings.Contains(strings.ToLower(container.Image), "gordon") {
469+ containerName := strings.TrimLeft(container.Names[0], "/")
470+ log.Debug("Auto-detected Gordon container by image", "container_name", containerName, "image", container.Image)
471+ return containerName
472+ }
473+ }
474+ }
475+
476+ // If all else fails, default to "gordon"
477+ log.Debug("Could not auto-detect Gordon container, using default name", "container_name", "gordon")
478+ return "gordon"
479+}
@@ -6,6 +6,7 @@ import (
6 "fmt"6 "fmt"
7 "net/http"7 "net/http"
8 "os"8 "os"
9+ "strings"
9 "time"10 "time"
10 11
11 "github.com/bnema/gordon/pkg/docker"12 "github.com/bnema/gordon/pkg/docker"
@@ -95,17 +96,21 @@ func (p *Proxy) Start() error {
95 p.mu.Lock()96 p.mu.Lock()
96 // Only add if it doesn't already exist97 // Only add if it doesn't already exist
97 if _, exists := p.routes[adminDomain]; !exists {98 if _, exists := p.routes[adminDomain]; !exists {
99+ // Auto-detect the Gordon container name
100+ containerName := p.detectGordonContainer()
101+
98 p.routes[adminDomain] = &ProxyRouteInfo{102 p.routes[adminDomain] = &ProxyRouteInfo{
99 Domain: adminDomain,103 Domain: adminDomain,
100 ContainerIP: containerIP,104 ContainerIP: containerIP,
101 ContainerPort: p.app.GetConfig().Http.Port,105 ContainerPort: p.app.GetConfig().Http.Port,
102- ContainerID: "gordon-server",106+ ContainerID: containerName, // Use auto-detected container name
103- Protocol: "http", // Gordon server uses HTTP internally107+ Protocol: "http", // Gordon server uses HTTP internally
104 Path: "/",108 Path: "/",
105 Active: true,109 Active: true,
106 }110 }
107 log.Info("Added special route for admin domain",111 log.Info("Added special route for admin domain",
108 "domain", adminDomain,112 "domain", adminDomain,
113+ "container", containerName,
109 "target", fmt.Sprintf("http://%s:%s", containerIP, p.app.GetConfig().Http.Port))114 "target", fmt.Sprintf("http://%s:%s", containerIP, p.app.GetConfig().Http.Port))
110 }115 }
111 116
@@ -113,12 +118,15 @@ func (p *Proxy) Start() error {
113 rootDomain := p.app.GetConfig().Http.Domain118 rootDomain := p.app.GetConfig().Http.Domain
114 if rootDomain != "" && rootDomain != adminDomain {119 if rootDomain != "" && rootDomain != adminDomain {
115 if _, exists := p.routes[rootDomain]; !exists {120 if _, exists := p.routes[rootDomain]; !exists {
121+ // Use the same auto-detected container name
122+ containerName := p.detectGordonContainer()
123+
116 p.routes[rootDomain] = &ProxyRouteInfo{124 p.routes[rootDomain] = &ProxyRouteInfo{
117 Domain: rootDomain,125 Domain: rootDomain,
118 ContainerIP: containerIP,126 ContainerIP: containerIP,
119 ContainerPort: p.app.GetConfig().Http.Port,127 ContainerPort: p.app.GetConfig().Http.Port,
120- ContainerID: "gordon-server",128+ ContainerID: containerName, // Use auto-detected container name
121- Protocol: "http", // Gordon server uses HTTP internally129+ Protocol: "http", // Gordon server uses HTTP internally
122 Path: "/",130 Path: "/",
123 Active: true,131 Active: true,
124 }132 }
@@ -389,3 +397,83 @@ func (p *Proxy) checkExternalPortAccess() {
389 log.Info("External HTTPS port 443 is accessible")397 log.Info("External HTTPS port 443 is accessible")
390 }398 }
391 }399 }
400+
401+// detectGordonContainer attempts to find the Gordon container automatically
402+func (p *Proxy) detectGordonContainer() string {
403+ // Check if we're running inside a container
404+ if docker.IsRunningInContainer() {
405+ log.Debug("Detected we're running in a container")
406+
407+ // Get our hostname which should be the container ID in Docker/Podman
408+ hostname := os.Getenv("HOSTNAME")
409+ if hostname != "" {
410+ // Check if there's a container with this hostname
411+ containers, err := docker.ListRunningContainers()
412+ if err == nil {
413+ for _, container := range containers {
414+ // Check if this container is us by comparing hostname with container ID
415+ if strings.HasPrefix(hostname, container.ID) {
416+ // This is our container
417+ containerName := strings.TrimLeft(container.Names[0], "/")
418+ log.Debug("Auto-detected Gordon container name from hostname", "container_name", containerName)
419+ return containerName
420+ }
421+ }
422+ } else {
423+ log.Debug("Could not list containers when checking hostname", "error", err)
424+ }
425+ }
426+ }
427+
428+ // Try to find Gordon by examining container processes
429+ containers, err := docker.ListRunningContainers()
430+ if err == nil {
431+ for _, container := range containers {
432+ containerID := container.ID
433+
434+ // Check container processes for Gordon
435+ containerLogs, err := docker.GetContainerLogs(containerID)
436+ if err == nil && (strings.Contains(containerLogs, "/gordon") || strings.Contains(containerLogs, "serve")) {
437+ containerName := strings.TrimLeft(container.Names[0], "/")
438+ log.Debug("Auto-detected Gordon container by process", "container_name", containerName)
439+ return containerName
440+ } else if err != nil {
441+ log.Debug("Could not get container logs", "container_id", containerID, "error", err)
442+ }
443+
444+ // Check container command for Gordon
445+ if len(container.Command) > 0 && strings.Contains(container.Command, "gordon") {
446+ containerName := strings.TrimLeft(container.Names[0], "/")
447+ log.Debug("Auto-detected Gordon container by command", "container_name", containerName)
448+ return containerName
449+ }
450+ }
451+ } else {
452+ log.Debug("Could not list containers when checking processes", "error", err)
453+ }
454+
455+ // If we couldn't detect from processes, try to find a container with gordon in the name or image
456+ if err == nil {
457+ for _, container := range containers {
458+ // Check container names for "gordon"
459+ for _, name := range container.Names {
460+ if strings.Contains(strings.ToLower(name), "gordon") {
461+ containerName := strings.TrimLeft(name, "/")
462+ log.Debug("Auto-detected Gordon container by name", "container_name", containerName)
463+ return containerName
464+ }
465+ }
466+
467+ // Check image name for "gordon"
468+ if strings.Contains(strings.ToLower(container.Image), "gordon") {
469+ containerName := strings.TrimLeft(container.Names[0], "/")
470+ log.Debug("Auto-detected Gordon container by image", "container_name", containerName, "image", container.Image)
471+ return containerName
472+ }
473+ }
474+ }
475+
476+ // If all else fails, default to "gordon"
477+ log.Debug("Could not auto-detect Gordon container, using default name", "container_name", "gordon")
478+ return "gordon"
479+}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close