Docker容器安装PowerShell Azure模块后命令无法使用 主机运行正常
我需要在Windows Docker容器中运行各类Azure PowerShell操作,因为Octopus Cloud要求我在该环境下运行工作节点。其标准脚本步骤似乎不支持该需求,官方建议我使用Docker容器提前构建好PowerShell运行环境。
在我的Win10主机上安装这些模块并运行脚本完全正常
我经过一些调整后可以成功安装模块,但模块包含的命令似乎无法被识别。我已经尝试过修改模块路径、切换用户上下文、设置执行策略、手动导入模块等操作,但均无效果。如下示例中,通过Get-InstalledModule可以查到模块已安装,但执行对应命令时却报错,注意使用Get-InstalledModule -Name查询时该模块不会显示。直接调用Connect-AzAccount连接时也会出现类似错误。
下图展示了三个现象:(a) 模块已安装 (b) 执行模块对应命令报错 (c) 模块安装路径中找不到该模块。

复现步骤
使用已构建容器复现
- 拉取标签为
windowsV2的镜像,命令为:docker pull mariusvrstr/azure-powershell-manager:windowsV2 - 执行Az.Accounts、Az.KeyVault下的命令,比如
Connect-AzAccount或Get-AzKeyVaultCertificate -VaultName $vault -Name $certkey(不需要变量实际有值,只要命令能被识别即可)
使用基础容器复现
- 拉取并启动标签为
nanoserver-1909的Windows PowerShell镜像实例。 - 安装前置依赖:
Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
- 安装所需的PowerShell Azure模块:
Install-Module Az.Accounts -AllowClobber -SkipPublisherCheck -Scope CurrentUser Install-Module Az.KeyVault -AllowClobber -SkipPublisherCheck -Scope CurrentUser Install-Module -Name Az -AllowClobber -Scope CurrentUser
- 执行Az.Accounts、Az.KeyVault下的命令,比如
Connect-AzAccount或Get-AzKeyVaultCertificate -VaultName $vault -Name $certkey(不需要变量实际有值,只要命令能被识别即可)
测试脚本
以下是检查证书过期时间的示例脚本,该脚本在本地可以正常运行,问题是即便模块已经安装,容器中依然找不到Azure相关命令。
param ($appId, $secret, $tenant, $vault, $certkey, $expiryDays) $pass = ConvertTo-SecureString $secret -AsPlainText -Force $isCertificateHealthy = $false # Ensure the correct Azure module in PowerShell is installed $azAccountsInstalled = Get-InstalledModule Az.Accounts if( ! $azAccountsInstalled) { Install-Module Az.Accounts -AllowClobber -a } else{ Write-Host "Az.Accounts already present" -ForegroundColor Yellow } $azCertificateInstalled = Get-InstalledModule Az.KeyVault if( ! $azCertificateInstalled) { Install-Module Az.KeyVault -a } else{ Write-Host "Az.KeyVault already present" -ForegroundColor Yellow } $cred = New-Object System.Management.Automation.PSCredential($appId,$pass) Connect-AzAccount -ServicePrincipal -Credential $cred -Tenant $tenant $cert = Get-AzKeyVaultCertificate -VaultName $vault -Name $certkey $expiryDate = $cert.Expires Write-Host "Certificate expiry: [$expiryDate]" $daysToExpire = [math]::Ceiling(($expiryDate-(Get-Date)).TotalDays) Write-Host "Days to expiry: [$daysToExpire]" if ($daysToExpire -ge $expiryDays) { $isCertificateHealthy = $true } if ($isCertificateHealthy) { Write-Host "Certificate is healthy" } else { Write-Host "Warning! Certificate is not healthy" }
恳请大家提供帮助,我对Docker还比较陌生,该功能在主机上可以正常运行,所以很可能是我在Docker相关配置上有遗漏。我已经配置好Octopus Cloud项目使用该容器,只需要让容器可以正常识别相关命令即可。
解决方案
该问题由Nano Server容器环境的特性导致,按以下步骤修改即可修复:
- 调整模块安装Scope:不要使用
-Scope CurrentUser,改为-Scope AllUsers,Nano Server容器默认运行在管理员上下文,AllUsers路径默认在PowerShell的模块检索路径中,可避免路径识别问题。 - 避免重复安装模块:不需要单独安装Az.Accounts、Az.KeyVault后再安装完整Az合集,直接安装完整Az模块即可,避免版本冲突导致的命令识别失败。
- 手动注册模块路径(兜底方案):如果仍有识别问题,在安装模块后执行以下命令将模块路径加入环境变量:
$env:PSModulePath += ";$([Environment]::GetFolderPath('MyDocuments'))\WindowsPowerShell\Modules"
- 镜像替换优化:如果nanoserver-1909仍有依赖缺失问题,可改用Azure官方预装好Az模块的PowerShell镜像,无需手动安装模块即可直接使用。
修改后的容器构建安装命令参考:
Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 Install-Module -Name Az -AllowClobber -SkipPublisherCheck -Scope AllUsers -Force
修改后执行Get-Command Connect-AzAccount即可正常识别命令,脚本可正常运行。
内容的提问来源于stack exchange,提问作者Marius Vorster

