Modules/businessdev.ALbuild.Containers/Private/Get-BcContainerIpAddress.ps1
|
function Select-BcLanIpAddress { <# .SYNOPSIS Picks the reachable LAN IPv4 from a list of candidate addresses. .DESCRIPTION Drops loopback (127.*) and link-local/APIPA (169.254.*) and anything that is not a dotted IPv4. When both a routable LAN address and a Docker NAT address (172.16-31.x) are present, the routable one wins - a transparent container's DHCP LAN IP is what an external host must use, not the NAT IP. Returns $null when no usable address remains. #> [CmdletBinding()] [OutputType([string])] param([string[]] $Candidates) $ips = @($Candidates | ForEach-Object { "$_".Trim() } | Where-Object { $_ -match '^\d{1,3}(\.\d{1,3}){3}$' -and $_ -ne '127.0.0.1' -and $_ -notlike '169.254.*' } | Select-Object -Unique) if ($ips.Count -eq 0) { return $null } # Prefer a routable LAN IP over Docker's NAT range (172.16.0.0-172.31.255.255). $lan = $ips | Where-Object { $_ -notmatch '^172\.(1[6-9]|2[0-9]|3[01])\.' } | Select-Object -First 1 if ($lan) { return $lan } return $ips[0] } function Get-BcContainerIpAddress { <# .SYNOPSIS Resolves a Business Central container's reachable IPv4 address. .DESCRIPTION Reads the container IP robustly across network modes: 1. 'docker inspect' NetworkSettings.Networks[].IPAddress - works for the default NAT/bridge network. 2. Fallback for a TRANSPARENT (DHCP) network: on Docker-for-Windows the NetworkSettings IP is empty for a transparent/l2bridge network, so the DHCP-assigned LAN IP is read from INSIDE the container (docker exec -> Get-NetIPAddress). This is the fix for the empty webClientUrl/ ipAddress bug on transparent containers. When several addresses are found, the routable LAN address wins over Docker's NAT range (see Select-BcLanIpAddress). Returns $null when no address can be resolved (e.g. the container is not running yet). .PARAMETER Name Container name. .PARAMETER DockerExecutable The Docker executable to use (default 'docker'). #> [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [Alias('ContainerName')] [string] $Name, [string] $DockerExecutable = 'docker' ) $candidates = @() $inspect = Invoke-BcDocker -DockerExecutable $DockerExecutable -Quiet -PassThru -SuccessExitCodes @(0, 1) ` -Arguments @('inspect', '-f', '{{range .NetworkSettings.Networks}}{{.IPAddress}} {{end}}', $Name) if ($inspect.Success) { $candidates += ("$($inspect.StdOut)" -split '\s+') } if (-not (Select-BcLanIpAddress -Candidates $candidates)) { # Transparent/DHCP: NetworkSettings has no IP; read the assigned IPv4 from inside the container. # Single-quoted so the host does not expand $_ - the script runs in the container's PowerShell. $inner = '(Get-NetIPAddress -AddressFamily IPv4 | Where-Object { $_.IPAddress -ne "127.0.0.1" -and $_.IPAddress -notlike "169.254.*" } | Select-Object -ExpandProperty IPAddress) -join " "' $exec = Invoke-BcDocker -DockerExecutable $DockerExecutable -Quiet -PassThru -SuccessExitCodes @(0, 1) ` -Arguments @('exec', $Name, 'powershell', '-NoProfile', '-NonInteractive', '-Command', $inner) if ($exec.Success) { $candidates += ("$($exec.StdOut)" -split '\s+') } } return Select-BcLanIpAddress -Candidates $candidates } |