[CmdletBinding()] param( [string]$ContainerName = "zhibaotong-mysql" ) $ErrorActionPreference = "Stop" $ProjectRoot = Split-Path -Parent $PSScriptRoot $SqlPath = Join-Path $ProjectRoot "database\mysql.sql" $ContainerSqlPath = "/tmp/zbt-init.sql" if (-not (Test-Path -LiteralPath $SqlPath)) { throw "缺少数据库快照:$SqlPath" } if ($null -eq (Get-Command docker -ErrorAction SilentlyContinue)) { throw "未找到 Docker 命令,请先安装并启动 Docker Desktop。" } docker inspect $ContainerName *> $null if ($LASTEXITCODE -ne 0) { throw "未找到 MySQL 容器 $ContainerName。可通过 -ContainerName 指定实际容器名。" } $Running = docker inspect --format '{{.State.Running}}' $ContainerName if ($LASTEXITCODE -ne 0) { throw "无法读取 MySQL 容器 $ContainerName 的运行状态。" } if ($Running.Trim() -ne "true") { docker start $ContainerName | Out-Null if ($LASTEXITCODE -ne 0) { throw "MySQL 容器 $ContainerName 启动失败。" } } # MySQL 首次创建容器时会先启动临时实例初始化系统表,随后再启动正式实例。 # 要求连续多次响应,避免 SQL 恰好导入到临时实例与正式实例的切换窗口。 $Ready = $false $ConsecutiveSuccesses = 0 for ($Attempt = 1; $Attempt -le 90; $Attempt++) { docker exec $ContainerName sh -c 'mysqladmin ping -uroot -p"$MYSQL_ROOT_PASSWORD" --silent >/dev/null 2>&1' if ($LASTEXITCODE -eq 0) { $ConsecutiveSuccesses++ if ($ConsecutiveSuccesses -ge 5) { $Ready = $true break } } else { $ConsecutiveSuccesses = 0 } Start-Sleep -Seconds 1 } if (-not $Ready) { throw "MySQL 容器 $ContainerName 在 90 秒内未就绪。" } try { docker cp $SqlPath "${ContainerName}:$ContainerSqlPath" if ($LASTEXITCODE -ne 0) { throw "数据库快照复制到容器失败。" } docker exec $ContainerName sh -c 'mysql -uroot -p"$MYSQL_ROOT_PASSWORD" --default-character-set=utf8mb4 < /tmp/zbt-init.sql' if ($LASTEXITCODE -ne 0) { throw "数据库快照导入失败,请检查容器中的 MYSQL_ROOT_PASSWORD。" } Write-Host "第二阶段 MySQL 数据初始化完成。" -ForegroundColor Green } finally { docker exec $ContainerName rm -f $ContainerSqlPath *> $null }