From fed8f1f74fb0ded9bac8fea9b540e214c5d73ae7 Mon Sep 17 00:00:00 2001 From: maziggy Date: Sun, 10 May 2026 15:22:10 +0200 Subject: [PATCH] Added install_docker for Windows 11 --- install/README.md | 47 +++++ install/docker-install.ps1 | 345 +++++++++++++++++++++++++++++++++++++ 2 files changed, 392 insertions(+) create mode 100644 install/docker-install.ps1 diff --git a/install/README.md b/install/README.md index 443810db6..d7aa097d0 100644 --- a/install/README.md +++ b/install/README.md @@ -11,6 +11,13 @@ Interactive installation scripts for BamBuddy with support for both native and D curl -fsSL https://raw.githubusercontent.com/maziggy/bambuddy/main/install/docker-install.sh -o docker-install.sh && chmod +x docker-install.sh && ./docker-install.sh ``` +**Windows (Command Prompt or PowerShell):** +```cmd +powershell -ExecutionPolicy Bypass -Command "iwr -useb https://raw.githubusercontent.com/maziggy/bambuddy/main/install/docker-install.ps1 -OutFile docker-install.ps1; .\docker-install.ps1" +``` + +> Requires Docker Desktop running. Printer auto-discovery is unavailable in Docker Desktop — add printers manually by IP. + ### Native Installation **Linux/macOS:** @@ -26,6 +33,7 @@ curl -fsSL https://raw.githubusercontent.com/maziggy/bambuddy/main/install/insta |--------|----------|--------| | `install.sh` | Linux, macOS | Native (Python venv) | | `docker-install.sh` | Linux, macOS | Docker | +| `docker-install.ps1` | Windows (Docker Desktop) | Docker | | `update.sh` | Linux (systemd) | Native update helper | --- @@ -100,6 +108,45 @@ Installs BamBuddy using Docker containers. ./docker-install.sh --build --yes ``` +### `docker-install.ps1` (Windows) + +PowerShell mirror of `docker-install.sh` for Windows + Docker Desktop. Verifies +Docker Desktop is running, downloads `docker-compose.yml`, rewrites it to use +port mappings instead of host networking (Docker Desktop doesn't support host +networking), and starts the container. + +**Requirements:** +- Docker Desktop installed and running ([download](https://www.docker.com/products/docker-desktop)) +- PowerShell 5.1+ (ships with Windows 10/11) or PowerShell 7+ + +**Parameters:** +``` +-InstallPath PATH Installation directory (default: %USERPROFILE%\bambuddy) +-Port PORT Port to expose (default: 8000) +-TimeZone TZ IANA timezone (default: derived from Get-TimeZone or UTC) +-Build Build from source instead of pulling pre-built image +-Yes Non-interactive mode, accept defaults +-Help Show full help (Get-Help) +``` + +**Examples:** +```powershell +# Interactive +.\docker-install.ps1 + +# Unattended +.\docker-install.ps1 -InstallPath C:\bambuddy -Port 8080 -TimeZone Europe/Berlin -Yes + +# Build from source +.\docker-install.ps1 -Build -Yes +``` + +> **Limitations on Windows / Docker Desktop:** Printer auto-discovery (SSDP) +> does not work — add printers manually by IP. The Virtual Printer feature +> requires manually uncommenting the relevant port mappings in +> `docker-compose.yml` (the script leaves them commented because most users +> don't need them). + --- ## Configuration Options diff --git a/install/docker-install.ps1 b/install/docker-install.ps1 new file mode 100644 index 000000000..5a2a45f0d --- /dev/null +++ b/install/docker-install.ps1 @@ -0,0 +1,345 @@ +<# +.SYNOPSIS + BamBuddy Docker installation script for Windows (Docker Desktop). + +.DESCRIPTION + Mirrors install/docker-install.sh for Windows. Verifies Docker Desktop is + installed and running, downloads docker-compose.yml, rewrites it for + Docker Desktop (no host networking), writes a .env, and starts the + container. + +.PARAMETER InstallPath + Installation directory. Default: $env:USERPROFILE\bambuddy + +.PARAMETER Port + Port to expose. Default: 8000 + +.PARAMETER TimeZone + IANA timezone string (e.g. Europe/Berlin). Default: derived from + Get-TimeZone or UTC. + +.PARAMETER Build + Build the image from source instead of pulling the pre-built image. + +.PARAMETER Yes + Non-interactive mode; accept defaults. + +.EXAMPLE + Interactive install (cmd or PowerShell): + powershell -ExecutionPolicy Bypass -Command "iwr -useb https://raw.githubusercontent.com/maziggy/bambuddy/main/install/docker-install.ps1 -OutFile docker-install.ps1; .\docker-install.ps1" + +.EXAMPLE + Unattended install: + .\docker-install.ps1 -InstallPath C:\bambuddy -Port 8080 -TimeZone Europe/Berlin -Yes +#> + +[CmdletBinding()] +param( + [string]$InstallPath, + [int]$Port, + [string]$TimeZone, + [switch]$Build, + [switch]$Yes, + [switch]$Help +) + +$ErrorActionPreference = 'Stop' +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + +# --- Helpers -------------------------------------------------------------- + +function Write-Banner { + Write-Host '' + Write-Host '==========================================================' -ForegroundColor Cyan + Write-Host ' Bambuddy - Docker Installation (Windows)' -ForegroundColor Cyan + Write-Host '==========================================================' -ForegroundColor Cyan + Write-Host '' +} + +function Info { param($m) Write-Host "[INFO] $m" -ForegroundColor Blue } +function Ok { param($m) Write-Host "[OK] $m" -ForegroundColor Green } +function Warn { param($m) Write-Host "[WARN] $m" -ForegroundColor Yellow } +function Fail { param($m) Write-Host "[ERR] $m" -ForegroundColor Red } + +function Read-Default { + param([string]$Prompt, [string]$Default) + if ($Yes) { return $Default } + $val = Read-Host "$Prompt [$Default]" + if ([string]::IsNullOrWhiteSpace($val)) { return $Default } + return $val +} + +function Read-YesNo { + param([string]$Prompt, [string]$Default = 'y') + if ($Yes) { return ($Default -eq 'y') } + $hint = if ($Default -eq 'y') { '[Y/n]' } else { '[y/N]' } + while ($true) { + $val = Read-Host "$Prompt $hint" + if ([string]::IsNullOrWhiteSpace($val)) { $val = $Default } + switch -Regex ($val.Trim().ToLower()) { + '^(y|yes)$' { return $true } + '^(n|no)$' { return $false } + default { Write-Host 'Please answer yes or no.' } + } + } +} + +function Show-Help { + Get-Help $PSCommandPath -Full + exit 0 +} + +# --- Detection ------------------------------------------------------------ + +function Test-Docker { + if (-not (Get-Command docker -ErrorAction SilentlyContinue)) { + Fail 'Docker is not installed.' + Write-Host '' + Write-Host ' Install Docker Desktop for Windows:' -ForegroundColor Yellow + Write-Host ' https://www.docker.com/products/docker-desktop' -ForegroundColor Cyan + Write-Host '' + Write-Host ' After install, launch Docker Desktop and re-run this script.' -ForegroundColor Yellow + exit 1 + } + + Info 'Docker found, checking daemon...' + try { + docker info --format '{{.ServerVersion}}' *> $null + if ($LASTEXITCODE -ne 0) { throw 'docker info failed' } + } catch { + Fail 'Docker daemon is not reachable. Is Docker Desktop running?' + Write-Host '' + Write-Host ' Open Docker Desktop, wait for the whale icon to settle,' -ForegroundColor Yellow + Write-Host ' then re-run this script.' -ForegroundColor Yellow + exit 1 + } + Ok 'Docker daemon is running' + + docker compose version *> $null + if ($LASTEXITCODE -eq 0) { + $script:DockerCompose = 'docker compose' + Ok 'Found Docker Compose v2' + } elseif (Get-Command docker-compose -ErrorAction SilentlyContinue) { + $script:DockerCompose = 'docker-compose' + Ok 'Found Docker Compose v1' + } else { + Fail 'Docker Compose not found. Install Docker Desktop 4.x+ (ships compose v2).' + exit 1 + } +} + +function Get-DefaultTimeZone { + if ($TimeZone) { return $TimeZone } + try { + $tz = (Get-TimeZone).Id + # Get-TimeZone returns Windows IDs ("W. Europe Standard Time"). Docker + # expects IANA. Fall back to UTC if we can't translate. + $iana = ConvertTo-IanaTimeZone $tz + if ($iana) { return $iana } + } catch {} + return 'UTC' +} + +function ConvertTo-IanaTimeZone { + param([string]$WindowsId) + # Minimal mapping of common Windows IDs to IANA. Users can override via -TimeZone. + $map = @{ + 'UTC' = 'UTC' + 'GMT Standard Time' = 'Europe/London' + 'W. Europe Standard Time' = 'Europe/Berlin' + 'Central European Standard Time' = 'Europe/Warsaw' + 'Romance Standard Time' = 'Europe/Paris' + 'Russian Standard Time' = 'Europe/Moscow' + 'Eastern Standard Time' = 'America/New_York' + 'Central Standard Time' = 'America/Chicago' + 'Mountain Standard Time' = 'America/Denver' + 'Pacific Standard Time' = 'America/Los_Angeles' + 'AUS Eastern Standard Time' = 'Australia/Sydney' + 'Tokyo Standard Time' = 'Asia/Tokyo' + 'China Standard Time' = 'Asia/Shanghai' + 'India Standard Time' = 'Asia/Kolkata' + } + return $map[$WindowsId] +} + +function Get-LanIp { + try { + $ip = Get-NetIPAddress -AddressFamily IPv4 -ErrorAction Stop | + Where-Object { + $_.IPAddress -notmatch '^(127\.|169\.254\.)' -and + $_.PrefixOrigin -ne 'WellKnown' -and + $_.InterfaceAlias -notmatch '^(vEthernet|Loopback)' + } | Select-Object -First 1 + if ($ip) { return $ip.IPAddress } + } catch {} + return '' +} + +# --- Steps ---------------------------------------------------------------- + +function Initialize-InstallDir { + Info "Creating installation directory: $InstallPath" + if (-not (Test-Path $InstallPath)) { + New-Item -ItemType Directory -Path $InstallPath -Force | Out-Null + } + Set-Location $InstallPath + Ok "Directory ready: $InstallPath" +} + +function Get-ComposeFile { + Info 'Downloading docker-compose.yml...' + + if ($Build) { + if (-not (Get-Command git -ErrorAction SilentlyContinue)) { + Fail 'git is required for --Build but was not found. Install Git for Windows: https://git-scm.com/download/win' + exit 1 + } + if (Test-Path '.git') { + Info 'Existing repository found, updating...' + git fetch origin + git reset --hard origin/main + } else { + git clone https://github.com/maziggy/bambuddy.git . + } + } else { + Invoke-WebRequest ` + -Uri 'https://raw.githubusercontent.com/maziggy/bambuddy/main/docker-compose.yml' ` + -OutFile 'docker-compose.yml' ` + -UseBasicParsing + } + + Ok 'docker-compose.yml ready' +} + +function Write-EnvFile { + Info 'Writing .env...' + $envBody = @" +# BamBuddy Docker Configuration +# Generated by docker-install.ps1 on $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') + +PORT=$Port +TZ=$TimeZone +"@ + [System.IO.File]::WriteAllText((Join-Path $InstallPath '.env'), $envBody) + Ok '.env written' +} + +function Update-ComposeForDockerDesktop { + # Docker Desktop on Windows does not support network_mode: host. Comment + # it out and uncomment the port mappings. Mirrors what the bash script + # does on macOS via sed. + $path = Join-Path $InstallPath 'docker-compose.yml' + Info 'Rewriting compose for Docker Desktop (no host networking)...' + + $content = [System.IO.File]::ReadAllText($path) + Copy-Item $path "$path.bak" -Force + + $content = $content -replace '(?m)^(\s*)network_mode: host', '#$1network_mode: host' + $content = $content -replace '(?m)^(\s*)#ports:', '$1ports:' + $content = $content -replace '(?m)^(\s*)#(\s*)- "\$\{PORT:-8000\}:8000"', '$1$2- "$${PORT:-8000}:8000"' + + [System.IO.File]::WriteAllText($path, $content) + Warn 'Printer auto-discovery (SSDP) does NOT work on Docker Desktop. Add printers manually by IP.' + Warn 'Virtual Printer ports (322, 990, 2024-2026, 3000/3002, 6000, 8883, 50000-50100) stay commented out.' + Warn 'If you plan to use a Virtual Printer, edit docker-compose.yml and uncomment the relevant `- "PORT:PORT"` lines under `ports:`.' +} + +function Start-Bambuddy { + Info 'Starting Bambuddy container...' + if ($Build) { + & cmd /c "$DockerCompose up -d --build" + } else { + & cmd /c "$DockerCompose up -d" + } + if ($LASTEXITCODE -ne 0) { + Fail 'Container start failed. Inspect logs with:' + Write-Host " cd $InstallPath" -ForegroundColor Yellow + Write-Host " $DockerCompose logs bambuddy" -ForegroundColor Yellow + exit 1 + } + + Info 'Waiting for container to be Up...' + $attempts = 0 + while ($attempts -lt 15) { + Start-Sleep -Seconds 2 + $ps = & cmd /c "$DockerCompose ps" 2>&1 + if ($ps -match 'Up') { Ok 'Bambuddy container is running'; return } + if ($ps -match 'Exited') { + Fail 'Container exited unexpectedly.' + Write-Host " $DockerCompose logs bambuddy" -ForegroundColor Yellow + exit 1 + } + $attempts++ + } + Warn "Container may still be starting. Check with: $DockerCompose ps" +} + +# --- Main ----------------------------------------------------------------- + +if ($Help) { Show-Help } + +Write-Banner + +Info 'Detecting environment...' +Test-Docker + +# Defaults +if (-not $InstallPath) { $InstallPath = Read-Default 'Installation directory' (Join-Path $env:USERPROFILE 'bambuddy') } +if (-not $Port) { $Port = [int](Read-Default 'Port to expose' '8000') } +if (-not $TimeZone) { + $detected = Get-DefaultTimeZone + $TimeZone = Read-Default 'Timezone (IANA)' $detected +} +if (-not $Build -and -not $Yes) { + if (Read-YesNo 'Build from source? (No = use pre-built image)' 'n') { $Build = $true } +} + +Write-Host '' +Write-Host 'Installation Summary' -ForegroundColor Cyan +Write-Host '-----------------------------------------' +Write-Host " Install path: $InstallPath" +Write-Host " Port: $Port" +Write-Host " Timezone: $TimeZone" +Write-Host " Build source: $Build" +Write-Host '' + +if (-not (Read-YesNo 'Proceed with installation?' 'y')) { + Write-Host 'Cancelled.' -ForegroundColor Yellow + exit 0 +} + +Initialize-InstallDir +Get-ComposeFile +Write-EnvFile +Update-ComposeForDockerDesktop +Start-Bambuddy + +$lanIp = Get-LanIp + +Write-Host '' +Write-Host '==========================================================' -ForegroundColor Green +Write-Host ' Installation Complete!' -ForegroundColor Green +Write-Host '==========================================================' -ForegroundColor Green +Write-Host '' +Write-Host " Access Bambuddy: http://localhost:$Port" -ForegroundColor Cyan +Write-Host " http://${lanIp}:$Port (from other devices)" -ForegroundColor Cyan +Write-Host '' +Write-Host ' Manage container:' +Write-Host " Status: cd `"$InstallPath`"; $DockerCompose ps" +Write-Host " Logs: cd `"$InstallPath`"; $DockerCompose logs -f bambuddy" +Write-Host " Stop: cd `"$InstallPath`"; $DockerCompose down" +Write-Host " Start: cd `"$InstallPath`"; $DockerCompose up -d" +Write-Host " Restart: cd `"$InstallPath`"; $DockerCompose restart" +Write-Host '' +Write-Host ' Update Bambuddy:' +if ($Build) { + Write-Host " cd `"$InstallPath`"; git pull; $DockerCompose up -d --build" +} else { + Write-Host " cd `"$InstallPath`"; $DockerCompose pull; $DockerCompose up -d" +} +Write-Host '' +Write-Host ' Documentation: https://wiki.bambuddy.cool' -ForegroundColor Cyan +Write-Host '' +Write-Host ' Note: Printer discovery is unavailable on Docker Desktop.' -ForegroundColor Yellow +Write-Host ' Add your printers manually by IP address in the UI.' -ForegroundColor Yellow +Write-Host ''