-
Notifications
You must be signed in to change notification settings - Fork 5.7k
emit container status events after network reconnection (fixes #13524) #13529
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
emit container status events after network reconnection (fixes #13524) #13529
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR fixes issue #13524 where Docker Compose's TTY UI doesn't reflect the actual state of containers after they are automatically restarted by the Docker engine during a network reconfiguration. When a network's configuration diverges (e.g., IPAM/subnet changes), Compose stops and disconnects containers, recreates the network, and reconnects the containers. If the engine has a restart policy that automatically restarts those containers, the UI previously showed them as "Stopped" even though they were actually "Running".
Changes:
- Adds logic to inspect and emit container status events after reconnecting containers to a recreated network
- Adds a unit test to verify that a "Running" event is emitted for containers restarted by the engine during network recreation
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| pkg/compose/create.go | Added code to inspect containers after network reconnection and emit appropriate status events (Running, Created, or Stopped) based on their actual state |
| pkg/compose/create_test.go | Added unit test TestResolveOrCreateNetworkEmitsRunningEvent to verify the new behavior and a test event processor helper |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
pkg/compose/create.go
Outdated
| if inspected.State != nil && inspected.State.Running { | ||
| s.events.On(runningEvent(name)) | ||
| } else if inspected.State != nil && inspected.State.Status == container.StateCreated { | ||
| s.events.On(createdEvent(name)) | ||
| } else if inspected.State != nil && inspected.State.Status == container.StateExited { | ||
| s.events.On(stoppedEvent(name)) | ||
| } |
Copilot
AI
Jan 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The conditional logic is inconsistent: it checks inspected.State.Running (a boolean field) for running containers but checks inspected.State.Status (a string field) for created and exited containers. For consistency and correctness, all conditions should check the Status field. The first condition should be inspected.State.Status == container.StateRunning to match the pattern used in similar code elsewhere in the codebase (e.g., ps.go lines 72-77).
pkg/compose/create.go
Outdated
| // ignore inspect errors | ||
| continue | ||
| } | ||
| name := "Container " + strings.TrimPrefix(inspected.Name, "/") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use getCanonicalContainerName for consistency with other places we produce events
pkg/compose/create_test.go
Outdated
| } | ||
| } | ||
|
|
||
| func TestResolveOrCreateNetworkEmitsRunningEvent(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We prefer use of e2e tests as mocks are a pain to maintain with many API calls, also in most case we don't get the actual engine behavior demonstrated by such tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi — thanks for the review and the suggestions!
I implemented both fixes you pointed out:
- Switched to using the canonical container name (now using
getContainerProgressName(tmp)) so emitted event names match other code paths. - Fixed the state check to consistently use the
Statusfield (inspected.State.Status == container.StateRunning), consistent with other code.
Per your preference for e2e tests, I added an e2e test:
TestNetworkIPAMChangeReportsStartedchanges the subnet and runsdocker compose up --progress=plain, then asserts the output contains the expected container state transition (Stopped then Started or Recreated).
I left the focused unit test as an additional guard; if you prefer to rely only on e2e tests I can remove the unit test in a follow-up. Happy to tweak wording or add more coverage if you prefer.
— Mahesh
24d36c1 to
fb09730
Compare
|
docker engine to automatically restart container is a corner case. The actual issue on #13524 is Compose not to log an event after a container is (re)started. |
Ack, understood. The auto-restart is just the trigger, but the missing event log is the gap in Compose. This PR addresses that root cause: it inspects the container state after network reconciliation and emits the missing status event. I've updated the logic and added the E2E test to cover this. Ready for review. |
it doesn't. It just emits an additional event, while this one should be managed by |
Got it. So instead of manually emitting the event post-reconnect, we should ensure the standard start lifecycle handles this transition? Could you point me to the specific start method/flow you are referring to? I want to make sure I hook into the correct lifecycle stage rather than patching it here. |
|
this is intentional: Line 193 in c8d6875
if we don't, and compose run attached, the progress UI will collides with first logs |
3f53733 to
6de1e1e
Compare
|
0f35cab to
58afa50
Compare
| display.Mode = display.ModeTTY | ||
| } | ||
|
|
||
| detached, _ := cmd.Flags().GetBool("detach") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm surprised this works, as detach flag is declared on child command
Head branch was pushed to by a user without write access
bb62ddd to
daa6f4b
Compare
Makefile
Outdated
| BINARY_EXT=.exe | ||
| endif | ||
|
|
||
| ifeq ($(DETECTED_OS),Darwin) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was intentionnaly removed from main branch, now managed within Dockerfile
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was intentionnaly removed from main branch, now managed within Dockerfile
My apologies, that was a remnant from my local dev environment on macOS. I've reverted the Makefile changes. Thanks for catching that
Signed-off-by: Mahesh Thakur <maheshthakur9152@gmail.com>
daa6f4b to
f41af27
Compare
Summary
Root cause
Stopped.What I changed
RunningeventCreatedeventStoppedeventTestResolveOrCreateNetworkEmitsRunningEventto assert that a running event is emitted for a container restarted by the engine.Files changed
Testing done
Notes for reviewers
Fixes: #13524