@@ -12,6 +12,7 @@ import (
1212
1313 "github.com/mirkobrombin/goup/internal/config"
1414 "github.com/mirkobrombin/goup/internal/plugin"
15+ "github.com/mirkobrombin/goup/internal/tools"
1516 log "github.com/sirupsen/logrus"
1617)
1718
@@ -29,6 +30,7 @@ type DockerStandardConfig struct {
2930
3031type dockerStandardState struct {
3132 containerID string
33+ hostPort string // dynamically assigned host port
3234 config DockerStandardConfig
3335}
3436
@@ -123,8 +125,8 @@ func (d *DockerStandardPlugin) HandleRequest(w http.ResponseWriter, r *http.Requ
123125 return false
124126 }
125127 }
126- // If proxy path is "/" use the container's root .
127- targetURL := fmt .Sprintf ("http://0.0.0.0:%s" , state .config . ContainerPort )
128+ // Build target URL using the assigned host port .
129+ targetURL := fmt .Sprintf ("http://0.0.0.0:%s" , state .hostPort )
128130 if len (state .config .ProxyPaths ) == 1 && state .config .ProxyPaths [0 ] == "/" {
129131 d .proxyToContainer (targetURL , w , r )
130132 return true
@@ -151,6 +153,7 @@ func (d *DockerStandardPlugin) OnExit() error {
151153 out , err := RunDockerCLI (state .config .CLICommand , state .config .DockerfilePath , "rm" , "-f" , state .containerID )
152154 d .PluginLogger .Infof ("Stopped container for domain %s: %s (err=%v)" , domain , out , err )
153155 state .containerID = ""
156+ state .hostPort = ""
154157 }
155158 }
156159 return nil
@@ -170,12 +173,6 @@ func (d *DockerStandardPlugin) ensureContainer(domain string) error {
170173 // Generate unique container name using domain and container port.
171174 containerName := fmt .Sprintf ("goup_%s_%s" , domain , state .config .ContainerPort )
172175
173- // Checking if a container with this unique name is already running.
174- existingID , err := RunDockerCLI (state .config .CLICommand , state .config .DockerfilePath , "ps" , "--filter" , fmt .Sprintf ("name=%s" , containerName ), "--format" , "{{.ID}}" )
175- if err == nil && strings .TrimSpace (existingID ) != "" {
176- state .containerID = strings .TrimSpace (existingID )
177- return nil
178- }
179176 d .DomainLogger .Infof ("[DockerStandardPlugin] Starting container for domain=%s with tag %s" , domain , containerName )
180177 cliCmd := state .config .CLICommand
181178 if cliCmd == "" {
@@ -211,7 +208,14 @@ func (d *DockerStandardPlugin) ensureContainer(domain string) error {
211208 }
212209 d .PluginLogger .Infof ("Pull output: %s" , pullOutput )
213210 }
214- runArgs := []string {"run" , "-d" , "--name" , containerName , "-p" , fmt .Sprintf ("%s:%s" , state .config .ContainerPort , state .config .ContainerPort )}
211+ // Allocate a free host port from a high range.
212+ hostPort , err := tools .GetFreePort ()
213+ if err != nil {
214+ return fmt .Errorf ("failed to get free port: %v" , err )
215+ }
216+
217+ // Run container with host port mapping using the free port.
218+ runArgs := []string {"run" , "-d" , "--name" , containerName , "-p" , fmt .Sprintf ("%s:%s" , hostPort , state .config .ContainerPort )}
215219 runArgs = append (runArgs , state .config .RunArgs ... )
216220 runArgs = append (runArgs , state .config .ImageName )
217221 d .PluginLogger .Infof ("[DockerStandardPlugin] Running container with command: %s %s" , cliCmd , strings .Join (runArgs , " " ))
@@ -220,6 +224,7 @@ func (d *DockerStandardPlugin) ensureContainer(domain string) error {
220224 return fmt .Errorf ("run error: %v, output: %s" , err , runOutput )
221225 }
222226 state .containerID = strings .TrimSpace (runOutput )
227+ state .hostPort = hostPort
223228 return nil
224229}
225230
0 commit comments