Skip to content

Conversation

@MaheshThakur9152
Copy link

Summary

  • When a network configuration (for example IPAM/subnet) changes, Compose stops containers and recreates the network.
  • The Docker engine can restart those containers automatically (e.g., due to a restart policy). Compose previously did not emit any event representing the containers' resumed state after reconnect, so the TTY UI could be left showing only "Stopped" even though the containers were actually running.
  • This PR makes Compose inspect containers after reconnecting them and emits the correct container status (Running / Created / Stopped), so the UI reflects the real state.

Root cause

  • The code path that handles diverged networks stops and disconnects containers, removes the network, recreates it and then reconnects containers.
  • If the engine restarts those containers between disconnection and reconnection, Compose had no further event for them, so the TTY progress UI only displayed the earlier Stopped.

What I changed

  • After reconnecting previously-dangled containers, inspect each container and emit one of the following events depending on the container state:
    • Running -> Running event
    • Created -> Created event
    • Exited -> Stopped event
  • Ignore inspect errors to avoid failing network creation due to races where a container disappears between disconnect and reconnect.
  • Add unit test TestResolveOrCreateNetworkEmitsRunningEvent to assert that a running event is emitted for a container restarted by the engine.

Files changed

  • create.go — emits container status events after reconnecting containers
  • create_test.go — new unit test simulating the diverged network flow and the engine restarting a container

Testing done

  • Unit test: go test ./pkg/compose -run TestResolveOrCreateNetworkEmitsRunningEvent -v — passes locally.
  • Full test suite: will run in CI (needs Docker daemon access and runs in their environments).

Notes for reviewers

  • Small, focused change to event emission — no new event types or UI changes.
  • Emitted events use existing statuses (Running, Created, Stopped) so the current UI picks them up.
  • If maintainers prefer a different message (e.g., “Reconnected”), I’m happy to adjust.
  • Signed-off-by: Mahesh Thakur maheshthakur9152@gmail.com

Fixes: #13524

Copilot AI review requested due to automatic review settings January 19, 2026 16:39
@MaheshThakur9152 MaheshThakur9152 requested a review from a team as a code owner January 19, 2026 16:39
Copy link

Copilot AI left a 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.

Comment on lines 1431 to 1437
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))
}
Copy link

Copilot AI Jan 19, 2026

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).

Copilot uses AI. Check for mistakes.
// ignore inspect errors
continue
}
name := "Container " + strings.TrimPrefix(inspected.Name, "/")
Copy link
Contributor

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

}
}

func TestResolveOrCreateNetworkEmitsRunningEvent(t *testing.T) {
Copy link
Contributor

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.

Copy link
Author

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 Status field (inspected.State.Status == container.StateRunning), consistent with other code.

Per your preference for e2e tests, I added an e2e test:

  • TestNetworkIPAMChangeReportsStarted changes the subnet and runs docker 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

@MaheshThakur9152 MaheshThakur9152 force-pushed the fix/network-status-events-13524 branch from 8f43d7c to 24d36c1 Compare January 19, 2026 18:04
MaheshThakur9152 and others added 4 commits January 19, 2026 23:55
…#13524)

Signed-off-by: Mahesh Thakur <maheshthakur9152@gmail.com>
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
Signed-off-by: Mahesh Thakur <maheshthakur9152@gmail.com>
Signed-off-by: Mahesh Thakur <maheshthakur9152@gmail.com>
Signed-off-by: Mahesh Thakur <maheshthakur9152@gmail.com>
@MaheshThakur9152 MaheshThakur9152 force-pushed the fix/network-status-events-13524 branch from 24d36c1 to fb09730 Compare January 19, 2026 18:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] misleading status for non-host-mode containers

2 participants