|
<# |
|
.SYNOPSIS |
|
Initializes a Docker Swarm manager on WSL2 using the Windows host's IP for advertising and WSL2 IP for listening. |
|
|
|
.DESCRIPTION |
|
This script identifies the Windows 11 host's IP address on the local network |
|
using PowerShell cmdlets (for advertising), gets the WSL2 instance's IP address |
|
(for listening), checks if a Docker Swarm is already active in the WSL2 instance, |
|
and if not, initializes a new swarm advertising the host's IP and listening |
|
on the WSL2 IP. It then displays the worker join token. |
|
|
|
.NOTES |
|
Author: Gemini |
|
Date: 2025-05-01 |
|
Requires: Administrator privileges, running WSL2 instance with Docker installed. |
|
|
|
.EXAMPLE |
|
.\Setup-SwarmManager.ps1 |
|
#> |
|
[CmdletBinding()] |
|
param() |
|
|
|
# Function to get the Windows host IP address accessible by other machines |
|
function Get-WindowsHostIP { |
|
Write-Host "Detecting Windows host IP address..." |
|
try { |
|
# Get all network adapters, exclude virtual and loopback adapters |
|
$adapters = Get-NetAdapter | Where-Object { |
|
$_.Status -eq 'Up' -and |
|
$_.Virtual -eq $false -and |
|
$_.Name -notmatch 'vEthernet \(WSL\)' -and |
|
$_.Name -notmatch 'Docker Desktop' -and |
|
$_.Name -notmatch 'Loopback' |
|
} |
|
|
|
if (-not $adapters) { |
|
Write-Warning "No active, non-virtual network adapters found. Checking all non-loopback IPs." |
|
# If no standard adapters found, check all non-loopback IPs |
|
$ipAddresses = Get-NetIPAddress | Where-Object { |
|
$_.AddressFamily -eq 'IPv4' -and |
|
$_.IPAddress -ne '127.0.0.1' -and |
|
$_.InterfaceAlias -notmatch 'vEthernet \(WSL\)' -and |
|
$_.InterfaceAlias -notmatch 'Docker Desktop' -and |
|
$_.InterfaceAlias -notmatch 'Loopback' |
|
} | Select-Object -ExpandProperty IPAddress |
|
|
|
} else { |
|
# Get IPv4 addresses for the found adapters |
|
$ipAddresses = Get-NetIPAddress | Where-Object { |
|
$_.InterfaceIndex -in $adapters.IfIndex -and |
|
$_.AddressFamily -eq 'IPv4' -and |
|
$_.IPAddress -ne '127.0.0.1' |
|
} | Select-Object -ExpandProperty IPAddress |
|
} |
|
|
|
|
|
if (-not $ipAddresses) { |
|
Write-Error "Could not automatically determine a suitable Windows host IP address." |
|
Write-Host "Please manually identify the correct IP address using 'ipconfig /all' in Command Prompt or PowerShell and update the script." |
|
exit 1 |
|
} |
|
|
|
# Prioritize a non-private IP if available, otherwise take the first private one |
|
$publicIp = $ipAddresses | Where-Object { $_ -notmatch '^10\.' -and $_ -notmatch '^172\.(1[6-9]|2[0-9]|3[0-1])\.' -and $_ -notmatch '^192\.168\.' } | Select-Object -First 1 |
|
|
|
if ($publicIp) { |
|
$finalIp = $publicIp |
|
if ($ipAddresses.Count -gt 1) { |
|
Write-Host "Multiple potential IP addresses found: $($ipAddresses -join ', '). Selected non-private IP: $($finalIp)." |
|
} |
|
} else { |
|
$finalIp = $ipAddresses | Select-Object -First 1 |
|
if ($ipAddresses.Count -gt 1) { |
|
Write-Host "Multiple potential IP addresses found: $($ipAddresses -join ', '). No non-private IP found, selected first private IP: $($finalIp)." |
|
} |
|
} |
|
|
|
|
|
if (-not $finalIp) { |
|
Write-Error "Could not automatically determine a suitable Windows host IP address after filtering." |
|
Write-Host "Please manually identify the correct IP address using 'ipconfig /all' in Command Prompt or PowerShell and update the script." |
|
exit 1 |
|
} |
|
|
|
Write-Host "Windows host IP address found: $($finalIp)" |
|
return $finalIp |
|
|
|
} catch { |
|
Write-Error "An error occurred while getting the Windows host IP address: $($_.Exception.Message)" |
|
Write-Host "Please manually identify the correct IP address using 'ipconfig /all' in Command Prompt or PowerShell and update the script." |
|
exit 1 |
|
} |
|
} |
|
|
|
# Function to get the WSL2 IP address |
|
function Get-WslIPAddress { |
|
Write-Host "Detecting WSL2 IP address..." |
|
try { |
|
# Use wsl.exe to get the IP address |
|
$wslIP = wsl.exe hostname -I | Where-Object { $_ -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}' } |
|
|
|
if (-not $wslIP) { |
|
Write-Error "Could not determine WSL2 IP address. Make sure your WSL2 instance is running." |
|
exit 1 |
|
} |
|
# Take the first IP address if multiple are returned by hostname -I |
|
$wslIP = $wslIP.Split(' ')[0] |
|
Write-Host "WSL2 IP Address found: $($wslIP.Trim())" |
|
return $wslIP.Trim() |
|
} catch { |
|
Write-Error "An error occurred while getting the WSL2 IP address: $($_.Exception.Message)" |
|
exit 1 |
|
} |
|
} |
|
|
|
|
|
$WINDOWS_IP = Get-WindowsHostIP |
|
$WSL2_IP = Get-WslIPAddress |
|
|
|
|
|
# Check if Swarm is already initialized in WSL2 |
|
Write-Host "Checking Docker Swarm state in WSL2..." |
|
# Use -c directly with the command string for better handling by wsl.exe |
|
$swarmStateResult = wsl.exe bash -c "docker info --format '{{.Swarm.LocalNodeState}}'" |
|
$swarmState = $swarmStateResult.Trim() |
|
|
|
if ($swarmState -eq "inactive") { |
|
Write-Output "Initializing Docker Swarm on manager..." |
|
Write-Output "Advertising address: $($WINDOWS_IP)" |
|
Write-Output "Listening address (WSL2): $($WSL2_IP):2377" |
|
|
|
# Initialize Swarm using the detected Windows IP for advertise and WSL2 IP for listen |
|
# Ensure the command is correctly quoted for bash |
|
$initCommand = "docker swarm init --advertise-addr $($WINDOWS_IP) --listen-addr $($WSL2_IP):2377" |
|
Write-Host "Executing in WSL2: $($initCommand)" |
|
wsl.exe bash -c "$initCommand" |
|
|
|
if ($LASTEXITCODE -ne 0) { |
|
Write-Error "Failed to initialize Docker Swarm. Check the output above for errors from the 'docker swarm init' command." |
|
exit 1 |
|
} |
|
|
|
Write-Host "Docker Swarm initialized successfully." |
|
|
|
# Get the worker join token |
|
Write-Host "Getting worker join token..." |
|
# Use -c directly with the command string |
|
$joinCommandResult = wsl.exe bash -c "docker swarm join-token worker" |
|
$joinCommand = $joinCommandResult.Trim() |
|
|
|
Write-Host "`n==================================================" |
|
Write-Host "Swarm Manager Setup Complete!" |
|
Write-Host "Run the following command on your worker nodes (in PowerShell as Administrator) to join the swarm:" |
|
Write-Host "`n$($joinCommand)" # Output the full join command |
|
Write-Host "==================================================" |
|
|
|
} elseif ($swarmState -eq "active") { |
|
Write-Output "Swarm is already active on this node." |
|
|
|
# If active, still provide the join token in case it's needed |
|
Write-Host "Getting worker join token..." |
|
# Use -c directly with the command string |
|
$joinCommandResult = wsl.exe bash -c "docker swarm join-token worker" |
|
$joinCommand = $joinCommandResult.Trim() |
|
|
|
|
|
Write-Host "`n==================================================" |
|
Write-Host "Swarm is already active." |
|
Write-Host "If you need to join other workers, run the following command on them (in PowerShell as Administrator):" |
|
Write-Host "`n$($joinCommand)" # Output the full join command |
|
Write-Host "==================================================" |
|
|
|
} else { |
|
Write-Warning "Unexpected Docker Swarm state: $($swarmState). Manual intervention may be required." |
|
} |