feat: Enhance container creation and proxy routing with improved IP and network handling
- Add container IP detection with fallback mechanisms - Implement automatic proxy route creation after container deployment - Improve container startup process with error handling and cleanup - Add hostname configuration during container creation - Enhance logging for container and proxy route operations - Refactor container deployment to support more robust network integration
- commit
- fd26325a939c2dbbb14482eb47cc2aa46bcfc970
- author
- bamen · · 2025-03-09 16:31 UTC
- parent
- 98f346b
- signature
- unsigned
4 files · +89 -19
M internal/httpserve/handlers/container_crud.go +45 -11
| @@ -2,14 +2,15 @@ package handlers | |||
| 2 | 2 | ||
| 3 | 3 | import ( | |
| 4 | 4 | "fmt" | |
| 5 | - | "log" | |
| 6 | 5 | "net/http" | |
| 6 | + | "strings" | |
| 7 | 7 | ||
| 8 | 8 | "github.com/bnema/gordon/internal/server" | |
| 9 | 9 | "github.com/bnema/gordon/internal/templating/cmdparams" | |
| 10 | 10 | "github.com/bnema/gordon/internal/templating/render" | |
| 11 | 11 | "github.com/bnema/gordon/pkg/docker" | |
| 12 | 12 | "github.com/bnema/gordon/pkg/sanitize" | |
| 13 | + | "github.com/charmbracelet/log" | |
| 13 | 14 | "github.com/labstack/echo/v4" | |
| 14 | 15 | ) | |
| 15 | 16 | ||
| @@ -17,7 +18,7 @@ import ( | |||
| 17 | 18 | func FromShortIDToImageID(ShortID string) (string, error) { | |
| 18 | 19 | imageID, exists := safelyInteractWithIDMap(Fetch, ShortID) | |
| 19 | 20 | if !exists { | |
| 20 | - | log.Printf("No mapping found for short ID: %s", ShortID) | |
| 21 | + | log.Debug("No mapping found for short ID: %s", ShortID) | |
| 21 | 22 | return "", fmt.Errorf("image ID not found") | |
| 22 | 23 | } | |
| 23 | 24 | return imageID, nil | |
| @@ -25,18 +26,18 @@ func FromShortIDToImageID(ShortID string) (string, error) { | |||
| 25 | 26 | ||
| 26 | 27 | // CreateContainerRoute is the route for creating a new container | |
| 27 | 28 | func CreateContainerGET(c echo.Context, a *server.App) error { | |
| 28 | - | log.Printf("Full request URL: %s", c.Request().URL.String()) | |
| 29 | + | log.Debug("Full request URL: %s", c.Request().URL.String()) | |
| 29 | 30 | // Retrieve the ShortID of the image from the URL | |
| 30 | 31 | shortID := c.Param("ID") | |
| 31 | - | log.Printf("Received ShortID: %s", shortID) | |
| 32 | + | log.Debug("Received ShortID: %s", shortID) | |
| 32 | 33 | ||
| 33 | 34 | fullID, exists := safelyInteractWithIDMap(Fetch, shortID) | |
| 34 | 35 | if !exists { | |
| 35 | - | log.Printf("No mapping found for short ID: %s", shortID) | |
| 36 | + | log.Debug("No mapping found for short ID: %s", shortID) | |
| 36 | 37 | return c.String(http.StatusNotFound, "Image ID not found") | |
| 37 | 38 | } | |
| 38 | 39 | ||
| 39 | - | log.Printf("Found mapping: %s -> %s", shortID, fullID) | |
| 40 | + | log.Debug("Found mapping: %s -> %s", shortID, fullID) | |
| 40 | 41 | ||
| 41 | 42 | // Get the image info | |
| 42 | 43 | imageInfo, err := docker.GetImageInfo(fullID) | |
| @@ -78,15 +79,15 @@ func CreateContainerGET(c echo.Context, a *server.App) error { | |||
| 78 | 79 | func CreateContainerFullGET(c echo.Context, a *server.App) error { | |
| 79 | 80 | // Retrieve the ShortID of the image from the URL | |
| 80 | 81 | shortID := c.Param("ID") | |
| 81 | - | log.Printf("Received ShortID: %s", shortID) | |
| 82 | + | log.Debug("Received ShortID: %s", shortID) | |
| 82 | 83 | ||
| 83 | 84 | fullID, exists := safelyInteractWithIDMap(Fetch, shortID) | |
| 84 | 85 | if !exists { | |
| 85 | - | log.Printf("No mapping found for short ID: %s", shortID) | |
| 86 | + | log.Debug("No mapping found for short ID: %s", shortID) | |
| 86 | 87 | return c.String(http.StatusNotFound, "Image ID not found") | |
| 87 | 88 | } | |
| 88 | 89 | ||
| 89 | - | log.Printf("Found mapping: %s -> %s", shortID, fullID) | |
| 90 | + | log.Debug("Found mapping: %s -> %s", shortID, fullID) | |
| 90 | 91 | ||
| 91 | 92 | // Get the image info | |
| 92 | 93 | imageInfo, err := docker.GetImageInfo(fullID) | |
| @@ -116,7 +117,7 @@ func CreateContainerFullGET(c echo.Context, a *server.App) error { | |||
| 116 | 117 | ||
| 117 | 118 | renderedHTML, err := rendererData.Render(data, a) | |
| 118 | 119 | if err != nil { | |
| 119 | - | log.Printf("Error rendering template: %v", err) | |
| 120 | + | log.Debug("Error rendering template: %v", err) | |
| 120 | 121 | return sendError(c, err) | |
| 121 | 122 | } | |
| 122 | 123 | ||
| @@ -166,10 +167,43 @@ func CreateContainerPOST(c echo.Context, a *server.App) error { | |||
| 166 | 167 | } | |
| 167 | 168 | ||
| 168 | 169 | // Create the container | |
| 169 | - | _, err = docker.CreateContainer(cmdParams) | |
| 170 | + | containerID, err := docker.CreateContainer(cmdParams) | |
| 170 | 171 | if err != nil { | |
| 171 | 172 | return sendError(c, err) | |
| 172 | 173 | } | |
| 173 | 174 | ||
| 175 | + | // Start the container | |
| 176 | + | err = docker.StartContainer(containerID) | |
| 177 | + | if err != nil { | |
| 178 | + | // If start fails, try to cleanup the container | |
| 179 | + | log.Warn("Failed to start container", "error", err) | |
| 180 | + | _ = docker.RemoveContainer(containerID) | |
| 181 | + | return sendError(c, fmt.Errorf("failed to start container: %w", err)) | |
| 182 | + | } | |
| 183 | + | ||
| 184 | + | // Get the container name for logging and as fallback | |
| 185 | + | containerName, err := docker.GetContainerName(containerID) | |
| 186 | + | if err != nil { | |
| 187 | + | log.Warn("Failed to get container name", "error", err) | |
| 188 | + | } else { | |
| 189 | + | containerName = strings.TrimPrefix(containerName, "/") | |
| 190 | + | } | |
| 191 | + | ||
| 192 | + | // Get container IP | |
| 193 | + | containerIP := GetContainerIP(a, containerID, containerName) | |
| 194 | + | ||
| 195 | + | // Construct target domain from form inputs | |
| 196 | + | targetDomain := fmt.Sprintf("%s://%s.%s", | |
| 197 | + | sanitizedInputs["container_protocol"], | |
| 198 | + | sanitizedInputs["container_subdomain"], | |
| 199 | + | sanitizedInputs["container_domain"]) | |
| 200 | + | ||
| 201 | + | // Add proxy route for the new container | |
| 202 | + | err = AddProxyRoute(a, containerID, containerIP, sanitizedInputs["proxy_port"], targetDomain) | |
| 203 | + | if err != nil { | |
| 204 | + | log.Error("Failed to add proxy route", "error", err) | |
| 205 | + | // Continue anyway, don't fail the whole operation | |
| 206 | + | } | |
| 207 | + | ||
| 174 | 208 | return c.HTML(http.StatusOK, ActionSuccess(a)) | |
| 175 | 209 | } | |
| @@ -2,14 +2,15 @@ package handlers | |||||
| 2 | 2 | ||||
| 3 | import ( | 3 | import ( | ||
| 4 | "fmt" | 4 | "fmt" | ||
| 5 | - | "log" | |||
| 6 | "net/http" | 5 | "net/http" | ||
| 6 | + | "strings" | |||
| 7 | 7 | ||||
| 8 | "github.com/bnema/gordon/internal/server" | 8 | "github.com/bnema/gordon/internal/server" | ||
| 9 | "github.com/bnema/gordon/internal/templating/cmdparams" | 9 | "github.com/bnema/gordon/internal/templating/cmdparams" | ||
| 10 | "github.com/bnema/gordon/internal/templating/render" | 10 | "github.com/bnema/gordon/internal/templating/render" | ||
| 11 | "github.com/bnema/gordon/pkg/docker" | 11 | "github.com/bnema/gordon/pkg/docker" | ||
| 12 | "github.com/bnema/gordon/pkg/sanitize" | 12 | "github.com/bnema/gordon/pkg/sanitize" | ||
| 13 | + | "github.com/charmbracelet/log" | |||
| 13 | "github.com/labstack/echo/v4" | 14 | "github.com/labstack/echo/v4" | ||
| 14 | ) | 15 | ) | ||
| 15 | 16 | ||||
| @@ -17,7 +18,7 @@ import ( | |||||
| 17 | func FromShortIDToImageID(ShortID string) (string, error) { | 18 | func FromShortIDToImageID(ShortID string) (string, error) { | ||
| 18 | imageID, exists := safelyInteractWithIDMap(Fetch, ShortID) | 19 | imageID, exists := safelyInteractWithIDMap(Fetch, ShortID) | ||
| 19 | if !exists { | 20 | if !exists { | ||
| 20 | - | log.Printf("No mapping found for short ID: %s", ShortID) | 21 | + | log.Debug("No mapping found for short ID: %s", ShortID) |
| 21 | return "", fmt.Errorf("image ID not found") | 22 | return "", fmt.Errorf("image ID not found") | ||
| 22 | } | 23 | } | ||
| 23 | return imageID, nil | 24 | return imageID, nil | ||
| @@ -25,18 +26,18 @@ func FromShortIDToImageID(ShortID string) (string, error) { | |||||
| 25 | 26 | ||||
| 26 | // CreateContainerRoute is the route for creating a new container | 27 | // CreateContainerRoute is the route for creating a new container | ||
| 27 | func CreateContainerGET(c echo.Context, a *server.App) error { | 28 | func CreateContainerGET(c echo.Context, a *server.App) error { | ||
| 28 | - | log.Printf("Full request URL: %s", c.Request().URL.String()) | 29 | + | log.Debug("Full request URL: %s", c.Request().URL.String()) |
| 29 | // Retrieve the ShortID of the image from the URL | 30 | // Retrieve the ShortID of the image from the URL | ||
| 30 | shortID := c.Param("ID") | 31 | shortID := c.Param("ID") | ||
| 31 | - | log.Printf("Received ShortID: %s", shortID) | 32 | + | log.Debug("Received ShortID: %s", shortID) |
| 32 | 33 | ||||
| 33 | fullID, exists := safelyInteractWithIDMap(Fetch, shortID) | 34 | fullID, exists := safelyInteractWithIDMap(Fetch, shortID) | ||
| 34 | if !exists { | 35 | if !exists { | ||
| 35 | - | log.Printf("No mapping found for short ID: %s", shortID) | 36 | + | log.Debug("No mapping found for short ID: %s", shortID) |
| 36 | return c.String(http.StatusNotFound, "Image ID not found") | 37 | return c.String(http.StatusNotFound, "Image ID not found") | ||
| 37 | } | 38 | } | ||
| 38 | 39 | ||||
| 39 | - | log.Printf("Found mapping: %s -> %s", shortID, fullID) | 40 | + | log.Debug("Found mapping: %s -> %s", shortID, fullID) |
| 40 | 41 | ||||
| 41 | // Get the image info | 42 | // Get the image info | ||
| 42 | imageInfo, err := docker.GetImageInfo(fullID) | 43 | imageInfo, err := docker.GetImageInfo(fullID) | ||
| @@ -78,15 +79,15 @@ func CreateContainerGET(c echo.Context, a *server.App) error { | |||||
| 78 | func CreateContainerFullGET(c echo.Context, a *server.App) error { | 79 | func CreateContainerFullGET(c echo.Context, a *server.App) error { | ||
| 79 | // Retrieve the ShortID of the image from the URL | 80 | // Retrieve the ShortID of the image from the URL | ||
| 80 | shortID := c.Param("ID") | 81 | shortID := c.Param("ID") | ||
| 81 | - | log.Printf("Received ShortID: %s", shortID) | 82 | + | log.Debug("Received ShortID: %s", shortID) |
| 82 | 83 | ||||
| 83 | fullID, exists := safelyInteractWithIDMap(Fetch, shortID) | 84 | fullID, exists := safelyInteractWithIDMap(Fetch, shortID) | ||
| 84 | if !exists { | 85 | if !exists { | ||
| 85 | - | log.Printf("No mapping found for short ID: %s", shortID) | 86 | + | log.Debug("No mapping found for short ID: %s", shortID) |
| 86 | return c.String(http.StatusNotFound, "Image ID not found") | 87 | return c.String(http.StatusNotFound, "Image ID not found") | ||
| 87 | } | 88 | } | ||
| 88 | 89 | ||||
| 89 | - | log.Printf("Found mapping: %s -> %s", shortID, fullID) | 90 | + | log.Debug("Found mapping: %s -> %s", shortID, fullID) |
| 90 | 91 | ||||
| 91 | // Get the image info | 92 | // Get the image info | ||
| 92 | imageInfo, err := docker.GetImageInfo(fullID) | 93 | imageInfo, err := docker.GetImageInfo(fullID) | ||
| @@ -116,7 +117,7 @@ func CreateContainerFullGET(c echo.Context, a *server.App) error { | |||||
| 116 | 117 | ||||
| 117 | renderedHTML, err := rendererData.Render(data, a) | 118 | renderedHTML, err := rendererData.Render(data, a) | ||
| 118 | if err != nil { | 119 | if err != nil { | ||
| 119 | - | log.Printf("Error rendering template: %v", err) | 120 | + | log.Debug("Error rendering template: %v", err) |
| 120 | return sendError(c, err) | 121 | return sendError(c, err) | ||
| 121 | } | 122 | } | ||
| 122 | 123 | ||||
| @@ -166,10 +167,43 @@ func CreateContainerPOST(c echo.Context, a *server.App) error { | |||||
| 166 | } | 167 | } | ||
| 167 | 168 | ||||
| 168 | // Create the container | 169 | // Create the container | ||
| 169 | - | _, err = docker.CreateContainer(cmdParams) | 170 | + | containerID, err := docker.CreateContainer(cmdParams) |
| 170 | if err != nil { | 171 | if err != nil { | ||
| 171 | return sendError(c, err) | 172 | return sendError(c, err) | ||
| 172 | } | 173 | } | ||
| 173 | 174 | ||||
| 175 | + | // Start the container | |||
| 176 | + | err = docker.StartContainer(containerID) | |||
| 177 | + | if err != nil { | |||
| 178 | + | // If start fails, try to cleanup the container | |||
| 179 | + | log.Warn("Failed to start container", "error", err) | |||
| 180 | + | _ = docker.RemoveContainer(containerID) | |||
| 181 | + | return sendError(c, fmt.Errorf("failed to start container: %w", err)) | |||
| 182 | + | } | |||
| 183 | + | ||||
| 184 | + | // Get the container name for logging and as fallback | |||
| 185 | + | containerName, err := docker.GetContainerName(containerID) | |||
| 186 | + | if err != nil { | |||
| 187 | + | log.Warn("Failed to get container name", "error", err) | |||
| 188 | + | } else { | |||
| 189 | + | containerName = strings.TrimPrefix(containerName, "/") | |||
| 190 | + | } | |||
| 191 | + | ||||
| 192 | + | // Get container IP | |||
| 193 | + | containerIP := GetContainerIP(a, containerID, containerName) | |||
| 194 | + | ||||
| 195 | + | // Construct target domain from form inputs | |||
| 196 | + | targetDomain := fmt.Sprintf("%s://%s.%s", | |||
| 197 | + | sanitizedInputs["container_protocol"], | |||
| 198 | + | sanitizedInputs["container_subdomain"], | |||
| 199 | + | sanitizedInputs["container_domain"]) | |||
| 200 | + | ||||
| 201 | + | // Add proxy route for the new container | |||
| 202 | + | err = AddProxyRoute(a, containerID, containerIP, sanitizedInputs["proxy_port"], targetDomain) | |||
| 203 | + | if err != nil { | |||
| 204 | + | log.Error("Failed to add proxy route", "error", err) | |||
| 205 | + | // Continue anyway, don't fail the whole operation | |||
| 206 | + | } | |||
| 207 | + | ||||
| 174 | return c.HTML(http.StatusOK, ActionSuccess(a)) | 208 | return c.HTML(http.StatusOK, ActionSuccess(a)) | ||
| 175 | } | 209 | } | ||
M internal/httpserve/handlers/endpoint_deploy.go +6 -8
| @@ -78,14 +78,11 @@ func PostDeploy(c echo.Context, a *server.App) error { | |||
| 78 | 78 | } | |
| 79 | 79 | ||
| 80 | 80 | // After successfully deploying a container, add a proxy route | |
| 81 | - | err = addProxyRoute(a, containerID, containerName, payload.Port, payload.TargetDomain) | |
| 81 | + | containerIP := GetContainerIP(a, containerID, containerName) | |
| 82 | + | err = AddProxyRoute(a, containerID, containerIP, payload.Port, payload.TargetDomain) | |
| 82 | 83 | if err != nil { | |
| 83 | 84 | log.Error("Failed to add proxy route", "error", err) | |
| 84 | - | return sendJSONResponse(c, http.StatusInternalServerError, DeployResponse{ | |
| 85 | - | Success: false, | |
| 86 | - | Message: fmt.Sprintf("Failed to add proxy route: %v", err), | |
| 87 | - | StatusCode: http.StatusInternalServerError, | |
| 88 | - | }) | |
| 85 | + | return sendDeployErrorResponse(c, "Failed to add proxy route", err) | |
| 89 | 86 | } | |
| 90 | 87 | ||
| 91 | 88 | // Arrived here means deployment was successful | |
| @@ -329,7 +326,8 @@ func processCompleteChunkedDeployTansfert(c echo.Context, a *server.App, transfe | |||
| 329 | 326 | "domain", targetDomain) | |
| 330 | 327 | ||
| 331 | 328 | // After successfully deploying a container, add a proxy route | |
| 332 | - | err = addProxyRoute(a, containerID, containerName, port, targetDomain) | |
| 329 | + | containerIP := GetContainerIP(a, containerID, containerName) | |
| 330 | + | err = AddProxyRoute(a, containerID, containerIP, port, targetDomain) | |
| 333 | 331 | if err != nil { | |
| 334 | 332 | log.Error("Failed to add proxy route", "error", err) | |
| 335 | 333 | return sendDeployErrorResponse(c, "Failed to add proxy route", err) | |
| @@ -392,7 +390,7 @@ func sendDeployErrorResponse(c echo.Context, message string, err error) error { | |||
| 392 | 390 | // } | |
| 393 | 391 | ||
| 394 | 392 | // After successfully deploying a container, add a proxy route | |
| 395 | - | func addProxyRoute(a *server.App, containerID, containerIP, containerPort, targetDomain string) error { | |
| 393 | + | func AddProxyRoute(a *server.App, containerID, containerIP, containerPort, targetDomain string) error { | |
| 396 | 394 | // Create a new proxy instance | |
| 397 | 395 | p, err := proxy.NewProxy(a) | |
| 398 | 396 | if err != nil { | |
| @@ -78,14 +78,11 @@ func PostDeploy(c echo.Context, a *server.App) error { | |||||
| 78 | } | 78 | } | ||
| 79 | 79 | ||||
| 80 | // After successfully deploying a container, add a proxy route | 80 | // After successfully deploying a container, add a proxy route | ||
| 81 | - | err = addProxyRoute(a, containerID, containerName, payload.Port, payload.TargetDomain) | 81 | + | containerIP := GetContainerIP(a, containerID, containerName) |
| 82 | + | err = AddProxyRoute(a, containerID, containerIP, payload.Port, payload.TargetDomain) | |||
| 82 | if err != nil { | 83 | if err != nil { | ||
| 83 | log.Error("Failed to add proxy route", "error", err) | 84 | log.Error("Failed to add proxy route", "error", err) | ||
| 84 | - | return sendJSONResponse(c, http.StatusInternalServerError, DeployResponse{ | 85 | + | return sendDeployErrorResponse(c, "Failed to add proxy route", err) |
| 85 | - | Success: false, | |||
| 86 | - | Message: fmt.Sprintf("Failed to add proxy route: %v", err), | |||
| 87 | - | StatusCode: http.StatusInternalServerError, | |||
| 88 | - | }) | |||
| 89 | } | 86 | } | ||
| 90 | 87 | ||||
| 91 | // Arrived here means deployment was successful | 88 | // Arrived here means deployment was successful | ||
| @@ -329,7 +326,8 @@ func processCompleteChunkedDeployTansfert(c echo.Context, a *server.App, transfe | |||||
| 329 | "domain", targetDomain) | 326 | "domain", targetDomain) | ||
| 330 | 327 | ||||
| 331 | // After successfully deploying a container, add a proxy route | 328 | // After successfully deploying a container, add a proxy route | ||
| 332 | - | err = addProxyRoute(a, containerID, containerName, port, targetDomain) | 329 | + | containerIP := GetContainerIP(a, containerID, containerName) |
| 330 | + | err = AddProxyRoute(a, containerID, containerIP, port, targetDomain) | |||
| 333 | if err != nil { | 331 | if err != nil { | ||
| 334 | log.Error("Failed to add proxy route", "error", err) | 332 | log.Error("Failed to add proxy route", "error", err) | ||
| 335 | return sendDeployErrorResponse(c, "Failed to add proxy route", err) | 333 | return sendDeployErrorResponse(c, "Failed to add proxy route", err) | ||
| @@ -392,7 +390,7 @@ func sendDeployErrorResponse(c echo.Context, message string, err error) error { | |||||
| 392 | // } | 390 | // } | ||
| 393 | 391 | ||||
| 394 | // After successfully deploying a container, add a proxy route | 392 | // After successfully deploying a container, add a proxy route | ||
| 395 | - | func addProxyRoute(a *server.App, containerID, containerIP, containerPort, targetDomain string) error { | 393 | + | func AddProxyRoute(a *server.App, containerID, containerIP, containerPort, targetDomain string) error { |
| 396 | // Create a new proxy instance | 394 | // Create a new proxy instance | ||
| 397 | p, err := proxy.NewProxy(a) | 395 | p, err := proxy.NewProxy(a) | ||
| 398 | if err != nil { | 396 | if err != nil { | ||
M internal/httpserve/handlers/endpoint_helpers.go +37 -0
| @@ -443,3 +443,40 @@ func getTransferData(transferID string) (*ChunkMetadata, map[int][]byte, error) | |||
| 443 | 443 | } | |
| 444 | 444 | return metadata, chunkStore.chunks[transferID], nil | |
| 445 | 445 | } | |
| 446 | + | ||
| 447 | + | // GetContainerIP gets the IP address of a container within its Docker network | |
| 448 | + | func GetContainerIP(a *server.App, containerID, containerName string) string { | |
| 449 | + | // Try to get container info | |
| 450 | + | containerInfo, err := docker.GetContainerInfo(containerID) | |
| 451 | + | if err != nil { | |
| 452 | + | log.Warn("Failed to get container info, using container name as IP", "error", err) | |
| 453 | + | return containerName // Use container name as fallback | |
| 454 | + | } | |
| 455 | + | ||
| 456 | + | // Extract IP address from container info | |
| 457 | + | if containerInfo.NetworkSettings != nil { | |
| 458 | + | // Look for the network specified in the config | |
| 459 | + | networkName := a.Config.ContainerEngine.Network | |
| 460 | + | if networkSettings, exists := containerInfo.NetworkSettings.Networks[networkName]; exists && networkSettings.IPAddress != "" { | |
| 461 | + | log.Debug("Found container IP", | |
| 462 | + | "containerName", containerName, | |
| 463 | + | "containerIP", networkSettings.IPAddress, | |
| 464 | + | "network", networkName) | |
| 465 | + | return networkSettings.IPAddress | |
| 466 | + | } | |
| 467 | + | ||
| 468 | + | // Look for any network if the specified one isn't found | |
| 469 | + | for networkName, networkSettings := range containerInfo.NetworkSettings.Networks { | |
| 470 | + | if networkSettings.IPAddress != "" { | |
| 471 | + | log.Debug("Found container IP in alternative network", | |
| 472 | + | "containerName", containerName, | |
| 473 | + | "containerIP", networkSettings.IPAddress, | |
| 474 | + | "network", networkName) | |
| 475 | + | return networkSettings.IPAddress | |
| 476 | + | } | |
| 477 | + | } | |
| 478 | + | } | |
| 479 | + | ||
| 480 | + | // Fallback to container name if no IP found | |
| 481 | + | return containerName | |
| 482 | + | } | |
| @@ -443,3 +443,40 @@ func getTransferData(transferID string) (*ChunkMetadata, map[int][]byte, error) | |||||
| 443 | } | 443 | } | ||
| 444 | return metadata, chunkStore.chunks[transferID], nil | 444 | return metadata, chunkStore.chunks[transferID], nil | ||
| 445 | } | 445 | } | ||
| 446 | + | ||||
| 447 | + | // GetContainerIP gets the IP address of a container within its Docker network | |||
| 448 | + | func GetContainerIP(a *server.App, containerID, containerName string) string { | |||
| 449 | + | // Try to get container info | |||
| 450 | + | containerInfo, err := docker.GetContainerInfo(containerID) | |||
| 451 | + | if err != nil { | |||
| 452 | + | log.Warn("Failed to get container info, using container name as IP", "error", err) | |||
| 453 | + | return containerName // Use container name as fallback | |||
| 454 | + | } | |||
| 455 | + | ||||
| 456 | + | // Extract IP address from container info | |||
| 457 | + | if containerInfo.NetworkSettings != nil { | |||
| 458 | + | // Look for the network specified in the config | |||
| 459 | + | networkName := a.Config.ContainerEngine.Network | |||
| 460 | + | if networkSettings, exists := containerInfo.NetworkSettings.Networks[networkName]; exists && networkSettings.IPAddress != "" { | |||
| 461 | + | log.Debug("Found container IP", | |||
| 462 | + | "containerName", containerName, | |||
| 463 | + | "containerIP", networkSettings.IPAddress, | |||
| 464 | + | "network", networkName) | |||
| 465 | + | return networkSettings.IPAddress | |||
| 466 | + | } | |||
| 467 | + | ||||
| 468 | + | // Look for any network if the specified one isn't found | |||
| 469 | + | for networkName, networkSettings := range containerInfo.NetworkSettings.Networks { | |||
| 470 | + | if networkSettings.IPAddress != "" { | |||
| 471 | + | log.Debug("Found container IP in alternative network", | |||
| 472 | + | "containerName", containerName, | |||
| 473 | + | "containerIP", networkSettings.IPAddress, | |||
| 474 | + | "network", networkName) | |||
| 475 | + | return networkSettings.IPAddress | |||
| 476 | + | } | |||
| 477 | + | } | |||
| 478 | + | } | |||
| 479 | + | ||||
| 480 | + | // Fallback to container name if no IP found | |||
| 481 | + | return containerName | |||
| 482 | + | } | |||
M pkg/docker/containers.go +1 -0
| @@ -297,6 +297,7 @@ func CreateContainer(cmdParams ContainerCommandParams) (string, error) { | |||
| 297 | 297 | Labels: labels, | |
| 298 | 298 | Env: cmdParams.Environment, | |
| 299 | 299 | ExposedPorts: exposedPorts, | |
| 300 | + | Hostname: cmdParams.ServiceName, | |
| 300 | 301 | }, | |
| 301 | 302 | &container.HostConfig{ | |
| 302 | 303 | PortBindings: portBindings, | |
| @@ -297,6 +297,7 @@ func CreateContainer(cmdParams ContainerCommandParams) (string, error) { | |||||
| 297 | Labels: labels, | 297 | Labels: labels, | ||
| 298 | Env: cmdParams.Environment, | 298 | Env: cmdParams.Environment, | ||
| 299 | ExposedPorts: exposedPorts, | 299 | ExposedPorts: exposedPorts, | ||
| 300 | + | Hostname: cmdParams.ServiceName, | |||
| 300 | }, | 301 | }, | ||
| 301 | &container.HostConfig{ | 302 | &container.HostConfig{ | ||
| 302 | PortBindings: portBindings, | 303 | PortBindings: portBindings, | ||