Attach to externally-started LS container#190
Attach to externally-started LS container#190carole-lavillonniere wants to merge 5 commits intomainfrom
Conversation
e9dc1e9 to
470cc59
Compare
When `lstk start` is run and a LocalStack container is already running (started outside lstk, e.g. via docker run or Compose), lstk now attaches to it rather than failing or trying to start a duplicate. Detection uses two complementary strategies: - Docker API: `FindRunningByImage` filters by image repo + bound host port via the `ancestor` filter, returning the running container regardless of its name or tag - HTTP fallback: if the Docker filter misses it (different image name, mid-restart), `/_localstack/info` is probed on the configured port Behaviour on attach: - Same version as config: "LocalStack is already running" (exit 0) - Different version: warning with both versions shown (exit 0) - Port in use by non-LocalStack process: existing error (exit 1) `lstk stop` also gains the same fallback: if no container matches the configured name, `FindRunningByImage` is used to locate and stop the externally-started container. `ContainerRemove` conflict/not-found errors (e.g. container started with --rm) are now silently ignored since removal was already in progress.
470cc59 to
9e2a2b4
Compare
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.
Tip: disable this comment in your organization's Code Review settings.
|
Looking at this now! 👀 |
There was a problem hiding this comment.
Nice one, @carole-lavillonniere! 💯
Added a first round of comments in some relevant lines of code, let me know if something does not make sense. 🙏
Thanks for testing extensively @gtsiolis |
31e00ab to
868d212
Compare
gtsiolis
left a comment
There was a problem hiding this comment.
Left some more comments, @carole-lavillonniere! What do you think?
| if found.BoundPort != c.Port { | ||
| output.EmitError(sink, output.ErrorEvent{ | ||
| Title: fmt.Sprintf("LocalStack is already running on port %s", found.BoundPort), | ||
| Summary: fmt.Sprintf("Config expects port %s. Only one instance can run at a time.", c.Port), |
There was a problem hiding this comment.
thought: We previously didn't have this restriction.
Only one instance can run at a time.
I'd expect to be able to spin up more than one instance as long as the port is different. This is how it works now, you can set GATEWAY_LISTEN="0.0.0.0:4567" and start a second instance side by side. See also relevant feedback.
| } | ||
| if conflictPort, err := ports.CheckAvailable(extraSpecs...); err != nil { | ||
| output.EmitError(sink, output.ErrorEvent{ | ||
| Title: fmt.Sprintf("Port %s is already in use", conflictPort), |
There was a problem hiding this comment.
praise: This works as expected, even if it's another service running! 💯
| if conflictPort, err := ports.CheckAvailable(extraSpecs...); err != nil { | ||
| output.EmitError(sink, output.ErrorEvent{ | ||
| Title: fmt.Sprintf("Port %s is already in use", conflictPort), | ||
| Summary: "LocalStack requires this port. Another instance may be running.", |
There was a problem hiding this comment.
thought: This might not be true when another service is using the port you configured. Could show this line only when port 4566 is configured?
# When configured to use port 4566
✗ Port 4566 already in use
> LocalStack may already be running.
# When configured to use port any other port other than 4566
✗ Port 4568 already in use| if found != nil { | ||
| if found.BoundPort != c.Port { | ||
| output.EmitError(sink, output.ErrorEvent{ | ||
| Title: fmt.Sprintf("LocalStack is already running on port %s", found.BoundPort), |
There was a problem hiding this comment.
issue: If you are running two instances, on port 4566 and port 4567, this message now is partially true as it captures only one instance. Since we're doing plain port check for now, I'd highlight the port conflict and only assume LS is running when the config is using 4566.
| emitEmulatorStartError(ctx, tel, c, telemetry.ErrCodePortConflict, fmt.Sprintf("running on port %s, configured port %s", found.BoundPort, c.Port)) | ||
| return nil, output.NewSilentError(fmt.Errorf("LocalStack already running on port %s", found.BoundPort)) | ||
| } | ||
| output.EmitInfo(sink, "LocalStack is already running") |


Summary
lstk startnow attaches to an already-running LocalStack container instead of failing. It fails if the port is different than the configured one.lstk stoplocates and stops an externally-started containerlstk statusreturns status of an externally-started container if anyTowards DRG-553
Started outside of
lstk(eg CLI v1, or locally built and ran in docker):Already running on a different port:
Status command shows details about the version and container name:
Possible improvement:
Add interactivity and let user decide if the existing container should be picked up or replaced