The outer loop over network interfaces had no break, so ip_address was
overwritten by every subsequent up/non-loopback interface with a
matching address family. On hosts with Docker, this meant the bridge
IP (e.g. 172.18.0.1) was returned instead of the actual LAN address,
because virtual interfaces can sort after the real one in dict order.
Add a break once a match is found so the function returns the first
qualifying interface, plus regression tests covering the Docker case,
loopback/down-interface skipping, and the no-match case.
Fixes#3617
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015NJfi2d6yvmmDzvPmm4eof