當你想要對 IIS 站台調整許多設定,又怕調整到一半突然出問題,這時候會殘留許多調整到一半的設定,如果想要做到 IaC (Infrastructure as code) 自動化,這個問題就必須被解決。還好 IISAdministration 模組中有提供「交易」相關的 Cmdlets 可用,本篇文章就來說說如何使用它。
建立容器
官方的 mcr.microsoft.com/dotnet/framework/aspnet:4.8
容器映象,已經預先安裝好 Web Server (IIS)
與 ASP.NET 4.8
角色服務,我將會使用這個 image 為主要的執行環境。
docker run --name=mysite -d --isolation=process -p 80:80 -p 443:443 -v C:\Projects\WebApplication1:C:\Inetpub\wwwroot mcr.microsoft.com/dotnet/framework/aspnet:4.8
以下對上述參數進行說明:
--name=mysite
設定容器好記名稱為 mysite
,方便後續命令說明。
-d
代表我們要將容器執行在 detach 模式(背景執行)。
--isolation=process
由於我們要複製現有的 PFX 憑證進容器,在 Windows 10 的 Windows Containers 必須要使用 proccess
隔離模式執行,才能執行 docker cp
命令複製檔案。
-p 80:80 -p 443:443
由於 Windows Containers 執行容器時,預設採用 nat
模式,所以需要將容器的 IP:Ports
對應到本機 Ports
比較方便測試。
-v C:\Projects\WebApplication1:C:\Inetpub\wwwroot
將一個現有的 ASP.NET MVC 5 專案對應到容器的 C:\Inetpub\wwwroot
路徑。
--entrypoint powershell
因為微軟官方的 aspnet
容器映象預設只能跑在 detach
(-d
) 模式,為了方便我們測試,我想改用 powershell
來當成預設進入程式。
mcr.microsoft.com/dotnet/framework/aspnet:4.8
已經預載 Web Server (IIS)
與 ASP.NET 4.8
角色服務。這是微軟官方的「多架構」容器映象,詳見 Windows Container 版本相容性與多重架構容器映像介紹 文章。
接著透過 docker exec
進入容器中操作:
docker exec -it -w c:\inetpub\wwwroot mysite powershell
新增站台繫結
-
新增 HTTP 站台繫結
綁定特定域名 ( 以 blog.miniasp.com
為例 )
New-IISSiteBinding -Name "Default Web Site" -Protocol http -BindingInformation "*:80:blog.miniasp.com"
綁定特定IP ( 以 192.168.9.100
為例 )
New-IISSiteBinding -Name "Default Web Site" -Protocol http -BindingInformation "192.168.9.100:80:"
綁定特定埠號 ( 以 8080
為例 )
New-IISSiteBinding -Name "Default Web Site" -Protocol http -BindingInformation ":8080:"
移除綁定
Remove-IISSiteBinding -Name "Default Web Site" -Protocol http -BindingInformation "*:80:blog.miniasp.com" -Confirm:$false
Remove-IISSiteBinding -Name "Default Web Site" -Protocol http -BindingInformation "192.168.9.100:80:" -Confirm:$false
Remove-IISSiteBinding -Name "Default Web Site" -Protocol http -BindingInformation ":8080:" -Confirm:$false
-
新增 HTTPS 站台繫結
綁定 IP-based SSL (不指定特定域名)
$cert = New-SelfSignedCertificate -DnsName blog.miniasp.com -CertStoreLocation cert:\LocalMachine\My
New-IISSiteBinding -Name "Default Web Site" -Protocol https -BindingInformation "*:443:" -CertificateThumbPrint $cert.Thumbprint -CertStoreLocation My
綁定 SNI-based SSL (指定特定域名)
$cert = New-SelfSignedCertificate -DnsName blog.miniasp.com -CertStoreLocation cert:\LocalMachine\My
New-IISSiteBinding -Name "Default Web Site" -Protocol https -BindingInformation "*:443:blog.miniasp.com" -SslFlag Sni -CertificateThumbPrint $cert.Thumbprint -CertStoreLocation My
移除綁定
Remove-IISSiteBinding -Name "Default Web Site" -Protocol https -BindingInformation "*:443:" -Confirm:$false
Remove-IISSiteBinding -Name "Default Web Site" -Protocol https -BindingInformation "*:443:blog.miniasp.com" -Confirm:$false
批次新增站台繫結
如果你一次需要新增好幾個站台繫結,或是一口氣要用 PowerShell 調整多項 IIS 設定的話,透過一行一行執行其實是不太好的。因為這些 PowerShell Cmdlets 每次執行時,都會確實寫入到 applicationHost.config
設定檔中,若你有其中一段設定掛掉的話,就可能會有設定不一致的問題!
在 IISAdministration 有兩個 Cmdlets 可以讓你的批次作業擁有「交易特性」(Transaction)。
以下是使用範例:
Start-IISCommitDelay
New-IISSite -Name "Test" -PhysicalPath "c:\Inetpub\wwwroot" -BindingInformation ":80:www.example.com" -Protocol http
New-IISSiteBinding -Name "Test" -Protocol http -BindingInformation "*:80:i1.example.com"
New-IISSiteBinding -Name "Test" -Protocol http -BindingInformation "*:80:i2.example.com"
New-IISSiteBinding -Name "Test" -Protocol http -BindingInformation "*:80:i3.example.com"
New-IISSiteBinding -Name "Test" -Protocol http -BindingInformation "*:80:i4.example.com"
New-IISSiteBinding -Name "Test" -Protocol http -BindingInformation "*:80:i5.example.com"
Stop-IISCommitDelay -Commit $True
如果你發現設定的過程有問題發生,就可以用 Stop-IISCommitDelay -Commit $False
來取消取消之前所有的變更!
以下是完整的使用範例:
$ErrorActionPreference = "Stop"
Get-IISSite
try
{
Write-Host "開始建立站台"
Start-IISCommitDelay
New-IISSite -Name "Test" -PhysicalPath "c:\Inetpub\wwwroot" -BindingInformation ":80:www.example.com" -Protocol http
New-IISSiteBinding -Name "Test" -Protocol http -BindingInformation "*:80:i1.example.com"
New-IISSiteBinding -Name "Test" -Protocol http -BindingInformation "*:80:i2.example.com"
New-IISSiteBinding -Name "Test" -Protocol http -BindingInformation "*:80:i2.example.com" # 重複的域名
New-IISSiteBinding -Name "Test" -Protocol http -BindingInformation "*:80:i4.example.com"
New-IISSiteBinding -Name "Test" -Protocol http -BindingInformation "*:80:i5.example.com"
Write-Host "站台建立成功!"
Stop-IISCommitDelay -Commit $True
}
catch
{
Write-Host "建立站台發生錯誤,復原所有設定"
Stop-IISCommitDelay -Commit $False
}
Get-IISSite
透過 IISAdministration 模組下的 Get-IISServerManager 也可以讓你的批次作業擁有「交易特性」(Transaction)。
透過 Get-IISServerManager 可以取回 .NET 的 Microsoft.Web.Administration 物件,讓你直接透過 .NET 物件來操作 IIS 內的各項設定。以下是使用範例:
$sm = Get-IISServerManager
$sm.Sites["Default Web Site"].Bindings.Add("*:80:www.example.com", "http")
$sm.Sites["Default Web Site"].Bindings.Add("*:80:a.example.com", "http")
$sm.Sites["Default Web Site"].Bindings.Add("*:80:b.example.com", "http")
$sm.Sites["Default Web Site"].Bindings.Add("*:80:c.example.com", "http")
$sm.Sites["Default Web Site"].Bindings.Add("*:80:d.example.com", "http")
$sm.Sites["Default Web Site"].Bindings.Add("*:80:e.example.com", "http")
$sm.CommitChanges();
我個人還是比較喜歡用 IISAdministration 模組下標準的 Cmdlets 來調整 IIS 設定,一來比較簡單,二來就算沒有 .NET 經驗也可以使用。
不過,透過 .NET 物件操作的彈性,會比用 PowerShell 來的強大很多,至於你想用哪種方式調整設定,就全看你個人喜好囉! 🙂
相關連結