Windows 的環境,
並且已在 WSL2 上安裝了 Docker 情況下 (不是 Docker
Desktop),
我們一般可以在 WSL 2 上直接執行 Docker 命令,例如 docker ps, docker version 等。
但如果我們想在 WSL 2 外部,也就是使用 CMD 或 PowerShell 來執行 Docker
命令的話,
就必須做些額外設定才能達成。
我們的目標有兩個:
- 讓 WSL 2 中的 Docker daemon 能將 Port 暴露給外部。
- 在 Windows 下要有 Docker CLI 讓 Windows 能使用 Docker 命令,並且要告訴 Docker CLI 要把命令傳給哪一個 Port。
為了讓 Docker daemon 能夠被 Windows 存取,首先我們要先進入 WSL 2 中,
找到或自行建立
/etc/docker/daemon.json,內容改為:
{
"hosts": ["tcp://127.0.0.1:2375", "unix:///var/run/docker.sock"]
}
/etc/docker/daemon.json 設定了 Docker daemon 的連接方式,也就是接受命令的方式,
unix:///var/run/docker.sock 是原本在 WSL 2 中 Docker 指令直接連接的目標。
tcp://127.0.0.1:2375 則是我們多加的,讓 WSL 2 外部能以 tcp localhost (127.0.0.1) + 2375 Port 的方式連接 Docker daemon。
將 Docker daemon 監聽 2375 Port,接著我們要以下指令重新啟動 Docker daemon service :
#service - 較舊的用法 (在現在其實也是去呼叫 systemctl)
service docker restart
#systemctl - 較新的用法
systemctl restart docker
如果設定了 daemon.json 後發現 docker service 無法正常重啟或啟動,
通常是因為 DOcker 本身的 /lib/systemd/system/docker.service 中的
ExecStart 指令設定跟 /etc/docker/daemon.json 互相衝突。
在 /lib/systemd/system/docker.service 中有一句像這樣的設定 (Docker version 29.0.2)
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
其中 -H fd:// 是Systemd 的 Socket Activation (套接字激活) 功能,
關於 Socket Activation 可以參考:
但我們現在不想要 systemd socket 攔截我們的請求,而是想要能直接傳送請求給我們在
/etc/docker/daemon.json 中的那些監聽設定,所以我們必須要重新覆蓋掉
/lib/systemd/system/docker.service 中的 ExecStart 設定。
我們需要去建立
/etc/systemd/system/docker.service.d/override.conf
內容如下:
[Service] ExecStart= ExecStart=/usr/bin/dockerd
這裡注意到我們須要寫兩行的 ExecStart=,第一行用來清除
/lib/systemd/system/docker.service
的 ExecStart 內容,第二行用來定設定我們要的自定義內容。
之後再執行以下指令 :
讓 systemd 重新載入 /etc/systemd/system/docker.service.d/override.conf 的設定
systemctl daemon-reload
重啟 Docker daemon
systemctl restart docker
sudo systemctl daemon-reload
sudo systemctl restart docker
以上都做完以後,從 Windows 就可以用 127.0.0.1:2375 存取 Docker daemon 了,
我們可以在 WSL 2 中用以下命令檢查 2375 Port 有沒有被監聽:
netstat -nl | grep 2375
或
ss -lntp | grep 2375
再來要注意的是有時 Windows 可能會有保留某些範圍的 Port 做特別用途而不給使用,
就算 Port 有被監聽還是無法正常讓 Windows 跟 Docker daemon 連接。
這時可以用以下指令來檢查:
netsh interface ipv4 show excludedportrange protocol=tcp
例如指令結果如果是如下:
Protocol tcp Port Exclusion Ranges
Start Port End Port
---------- --------
2211 2310
2311 2410
2511 2610
2611 2710
5357 5357
7749 7848
10824 10923
14846 14945
50000 50059 *
* - Administered port exclusions.
可以看到 2375 Port 是在 2311 ~ 2410 中被系統保留不能使用 ,
所以這時我們就要改設定其他 Port,不能用 2375。
可參考 Port 2375 not listening · Issue #3546 · docker/for-win
最後,雖然 Windows 也可連上 Docker daemon 了,除非你想直接底層用 Socket 連接 (例如 Testcontainers 這個 Java Library 可以做到),
不然還是裝上 Docker CLI 讓其提供方便的 Docker 指令給 Windows 使用。
我們先去下載相應 Docker 版本的 Docker CLI for Windows,下載網址如下:
https://download.docker.com/win/static/stable/x86_64/
下載後會是一個 zip 檔,解壓縮後得到一個資料夾,裡面有 docker.exe, dockerd.exe, 等檔案。
先設定環境變數的 Path 到資料夾路徑讓我們可以方便使用 Docker CLI 指令後,
還需要設定 DOCKER_HOST 環境變數讓 Docker CLI 知道要去哪裡連接 Docker daemon,
我們設定如下環境變數:
DOCKER_HOST : tcp://127.0.0.1:2375
然後再重新打開 PowerShell 或 cmd 試著執行 Docker 指令,就可以成功連上 Docker daemon 並執行 Docker 指令了,
例如執行 docker version:
docker version
應該就可以成功看到 Docker 的 version 資訊了。
參考資料:
- How to run tests with TestContainers in WSL2 without Docker Desktop
- 如何移除 Docker Desktop 並在 Windows 與 WSL 2 改安裝 Docker Engine | The Will Will Web
- 一次socket activation的探索体验-CSDN博客
- Systemd 的 socket activation 机制 | Zwlin's Blog
- service - Unable to start docker after configuring hosts in daemon.json - Stack Overflow
- Port 2375 not listening · Issue #3546 · docker/for-win
沒有留言 :
張貼留言