Skip to content

Commit df8385c

Browse files
author
mirkobrombin
committed
feat: enhance ensureContainer method to check for existing containers and manage host port allocation
1 parent 053e9b2 commit df8385c

File tree

1 file changed

+34
-11
lines changed

1 file changed

+34
-11
lines changed

plugins/docker_standard.go

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ func (d *DockerStandardPlugin) OnExit() error {
159159
return nil
160160
}
161161

162+
// ensureContainer first checks if a container already exists.
163+
// If it does, it reads the assigned host port from the container's labels (goup_port)
164+
// and stores it in state.hostPort. Otherwise, it builds/pulls the image,
165+
// allocates a free port, and starts the container (adding a label to record the port).
162166
func (d *DockerStandardPlugin) ensureContainer(domain string) error {
163167
d.mu.Lock()
164168
defer d.mu.Unlock()
@@ -170,26 +174,38 @@ func (d *DockerStandardPlugin) ensureContainer(domain string) error {
170174
return nil
171175
}
172176

173-
// Generate unique container name using domain and container port.
174-
containerName := fmt.Sprintf("goup_%s_%s", domain, state.config.ContainerPort)
175-
176-
d.DomainLogger.Infof("[DockerStandardPlugin] Starting container for domain=%s with tag %s", domain, containerName)
177177
cliCmd := state.config.CLICommand
178178
if cliCmd == "" {
179179
cliCmd = "docker"
180180
if _, err := exec.LookPath("docker"); err != nil {
181181
cliCmd = "podman"
182182
}
183183
}
184-
var workDir string
185-
if state.config.DockerfilePath != "" {
186-
workDir = filepath.Dir(state.config.DockerfilePath)
187-
} else {
188-
workDir = "."
184+
185+
// Generate unique container name using domain and container port.
186+
containerName := fmt.Sprintf("goup_%s_%s", domain, state.config.ContainerPort)
187+
d.DomainLogger.Infof("[DockerStandardPlugin] Checking for existing container with name=%s", containerName)
188+
189+
// Check if a container with the expected name already exists.
190+
existingContainerID, err := RunDockerCLI(cliCmd, state.config.DockerfilePath, "ps", "-a",
191+
"--filter", fmt.Sprintf("name=%s", containerName),
192+
"--format", "{{.ID}}")
193+
if err == nil && strings.TrimSpace(existingContainerID) != "" {
194+
// Container exists; read its assigned port from the container labels.
195+
assignedPort, err := RunDockerCLI(cliCmd, state.config.DockerfilePath, "inspect",
196+
"--format", "{{ index .Config.Labels \"goup_port\"}}", containerName)
197+
if err != nil || strings.TrimSpace(assignedPort) == "" {
198+
return fmt.Errorf("container exists but goup_port label is missing or empty")
199+
}
200+
state.containerID = strings.TrimSpace(existingContainerID)
201+
state.hostPort = strings.TrimSpace(assignedPort)
202+
d.DomainLogger.Infof("[DockerStandardPlugin] Found existing container for domain=%s with ID=%s and hostPort=%s", domain, state.containerID, state.hostPort)
203+
return nil
189204
}
190205

191206
// Build image if Dockerfile is provided; otherwise, pull the image.
192207
if state.config.DockerfilePath != "" {
208+
workDir := filepath.Dir(state.config.DockerfilePath)
193209
buildArgs := []string{"build", "-f", state.config.DockerfilePath, "-t", state.config.ImageName, workDir}
194210
for key, val := range state.config.BuildArgs {
195211
buildArgs = append(buildArgs, "--build-arg", fmt.Sprintf("%s=%s", key, val))
@@ -208,14 +224,21 @@ func (d *DockerStandardPlugin) ensureContainer(domain string) error {
208224
}
209225
d.PluginLogger.Infof("Pull output: %s", pullOutput)
210226
}
227+
211228
// Allocate a free host port from a high range.
212229
hostPort, err := tools.GetFreePort()
213230
if err != nil {
214231
return fmt.Errorf("failed to get free port: %v", err)
215232
}
216233

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)}
234+
// Run container with host port mapping using the free port,
235+
// and add a label to record the assigned port.
236+
runArgs := []string{
237+
"run", "-d",
238+
"--name", containerName,
239+
"-p", fmt.Sprintf("%s:%s", hostPort, state.config.ContainerPort),
240+
"--label", fmt.Sprintf("goup_port=%s", hostPort),
241+
}
219242
runArgs = append(runArgs, state.config.RunArgs...)
220243
runArgs = append(runArgs, state.config.ImageName)
221244
d.PluginLogger.Infof("[DockerStandardPlugin] Running container with command: %s %s", cliCmd, strings.Join(runArgs, " "))

0 commit comments

Comments
 (0)