2024-12-28

在用 Docker 架設 MSSQL 時,容器的啟用會警告 [Error response from daemon: Ports are not available...]

在網路上查到的文章大至上得到的說明是,這是因為 windows 可能在某個版本的升級開始會把某些 port 或某個範圍的 port 給「保留」,其中就有包含 mssql 一般慣用的 1433/tcp,而 windows 的一個 HNS 的服務有把一些 port 給「保留」

但也有一說是因為 windows 本身使用了 Hyper-V 把 1433/tcp 給保留了起來

我比較認為是 hyper-v 的問的,因為我目前的 docker 並不是運行在 WSL2 的,還是在比較早期要用 hyper-v 的虛擬機上,所以我比較認為是 hyper-v 引起的

故,如果有跟我遇到一樣問是的,可以先用

netsh interface ipv4 show excludedportrange protocol=tcp

的指定來列出被「保留」下來的 tcp port (注: 上述的指令要用「管理員身份」去執行)

如果上述的指令沒有列出你用到的 port ,那你的問題就比較偏向是你要用的 port 已被你電腦中其他的程序佔用,又或者是其他的程序先加到他自己的「保留」了,那有以下方式你可以試試

  • netstat -ano|findstr "port"
    • 此是先找目前電腦 listen 的 port 是不是有你要用的,如果有出現,此指令也會列出用這個 port 的 process id(PID),你如果確定這個程序你沒有要用或可以改 port 那你就中止這個程序或去改 port
    • 如果沒列出來,那再走以下的建議方式
  • net stop winnat && net start winnat
    • 把 winnat 這服務重啟,這個服務重啟後再去看上述「excludedportrange」的指令,理論上應該就會列出來的項目變少了
    • 此方式理論上應該是可以直接解決問題,但只是麻煩點,有可能要你在啟動 docker 容器時發現「Ports are not available...」時就要把 winnat 服務重啟,但我覺得此方式相對保險
  • 因為認為是 hyper-v 搞的,那來對 hyper-v 處理
    1. dism.exe /Online /Disable-Feature:Microsoft-Hyper-V
      • 先把 hyper-v 這功能停用(注意: 如果你跟我一樣 docker 目前是跑在 hyper-v 上面的,這指令下去你 docker 就會異常,直到重新把 hyper-v 啟用)
    2. netsh interface ipv4 add excludedportrange protocol=tcp startport={port} numberofports=1
      • 把你的 {port} 增加到你自己要保留的設定中,這設定會讓有其他程序要用 {port} 時反而系統會告知該程序這個 {port} 已被保留不能用
    3. dism.exe /Online /Enable-Feature:Microsoft-Hyper-V /ALL
      • 重新啟用 Hyper-v(注意: 如果重新啟用 hyper-v 後 docker 啟動有問題,那建議把 docker 重新安裝)
  • reg add HKLM\SYSTEM\CurrentControlSet\Services\hns\State /v EnableExcludedPortRange /d 0 /f
    • 此項…我認為是上述的方式都不行時再用,因為畢竟要動到regedit,多少有點風險
上述的方式請在做好備份後再使用,以免有一些嚴重的風險
我個人是只有把 winnat 服務重啟的動作後,重新啟動 mssql 容器就正常了

沒有留言: