將 Docker 安裝進 WSL (不使用 Docker Desktop)

前言

docker入門很推薦透過dcoker-desktop開始,畢竟UI還是很方便的

其他還有RedHat的podman也有desktop,但是podman主打的特色其中之一就是使用較低的權限在執行container,相對來講比較安全

但是新手入門肯定都是系統管理員的權限開著到處跑的,也比較不會碰到一些權限上的問題

不過docker-desktop實際上並不是可以免費商用的軟體(雖然門檻也不低),不過不能使用的只有desktop,所以建立一個linux的機器,把docker放進去執行是可以的

在windows中,現在可以使用wsl(windows subsystem for linux)來建立一個linux的系統,然後再把docker放進去就是這次想做的事情

絕對不是有幾次碰到docker desktop開不起來的狀況想換 呵呵


環境

  • OS: Windows Server 2025
  • WSL2: Ubuntu

在Hyper-V中準備這個Lab的環境,如何準備可以看之前的文章 在 Hyper-V 虛擬機(windows)中安裝 docker-desktop,需要開啟 巢狀虛擬化的功能

1
Set-VMProcessor -VMName {你的VM名稱} -ExposeVirtualizationExtensions $true  

實作流程

啟用 WSL 與安裝 Linux 發行版

執行powershell指令來安裝wsl (如果還沒有裝的話)

1
wsl --install

安裝wsl

執行完畢後, 就依照指示 重新啟動伺服器

重啟後,執行powershell指令來檢查有哪些linux版本可以安裝,挑選一個版本來安裝
linux發行版列表

1
2
3
4
5
# 列出線上有哪些linux版本可以安裝
wsl --list --online

# 執行安裝
wsl --install "{發行版本名稱}"

選個最簡單不用什麼設定的ubuntu

選擇ubuntu安裝

安裝docker

其實到這一步應該就和直接裝在linux上差不多了,可以直接參考docker官方文件來操作就好

設定 Docker 官方金鑰與儲存庫

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Add Docker's official GPG key:
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF

sudo apt update

執行安裝

1
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

執行完之後就可以透過指令來檢查是不是docker已經在執行了

1
sudo systemctl status docker

docker安裝完畢

建立權限

將使用者加入到docker group中,這樣之後就不用使用sudo來執行指令

1
sudo usermod -aG docker $USER

宿主機透過wsl執行docker

執行docker的範本image “hello-world”

1
wsl docker run --rm -it hello-world

執行測試


讓宿主機直接使用docker指令

安裝 docker cli

因為不想每次都要多打個wsl,所以再來在宿主機上安裝 docker cli

1
winget install Docker.DockerCLI

安裝docker-cli

如果碰到憑證錯誤,可以試試看

1
WINGET SETTINGS --ENABLE BypassCertificatePinningForMicrosoftStore

如果需要docker compose,在winget中的名稱是 “Docker.DockerCompose”

1
winget install Docker.DockerCompose

讓docker接受TCP連線

回到wsl中,建立docker的設定檔

1
sudo nano /etc/docker/daemon.json

修改daemon.json內容

1
2
3
{
"hosts": ["unix:///var/run/docker.sock", "tcp://127.0.0.1:2375"]
}

調整 systemd 啟動參數

1
2
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo nano /etc/systemd/system/docker.service.d/override.conf

修改 override.conf 內容
避免 systemd 預設參數與 daemon.json 的 hosts 設定發生衝突

1
2
3
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd

重啟docker

1
2
sudo systemctl daemon-reload
sudo systemctl restart docker

宿主機測試

設定環境變數,讓docker可以指向wsl內

1
$env:DOCKER_HOST='localhost:2375'

然後執行範例的image測試

1
docker run --rm -it hello-world

docker-run

直接執行 docker run --rm -it hello-world 會出現錯誤,因為還需要設定環境變數 DOCKER_HOST

1
failed to connect to the docker API at npipe:////./pipe/docker_engine; check if the path is correct and if the daemon is running: open //./pipe/docker_engine: The system cannot find the file specified.

如果想將 DOCKER_HOST 變成持久的環境變數,可以試試看以下指令,但執行完後,需要另外開一個powershell的session才會生效

1
[Environment]::SetEnvironmentVariable("DOCKER_HOST", "tcp://localhost:2375", "Machine")

補充:路徑轉換的坑

當在宿主機使用 Docker CLI 連接 WSL 內的 Docker Engine 時,最容易遇到的問題就是 掛載磁碟卷 (Volume Mounting)

問題描述

當執行以下指令時:

1
docker run --rm -v C:\mydata:/data alpine ls /data

會發現路徑掛載失敗,或者掛載進去的是一個空的資料夾。這是因為宿主機的 Docker CLI 只是把路徑字串傳給 WSL 內的 Docker Daemon,而 WSL 內的 Daemon 並不認識 C:\ 這種 Windows 路徑格式。

訊息內容大概如下:

1
2
3
4
PS C:\Users\Administrator> docker run --rm -v C:\mydata:/data alpine ls /data
docker: Error response from daemon: invalid mode: /data

Run 'docker run --help' for more information

測試與驗證

可以透過以下步驟來驗證這個行為:

  1. 在 Windows 建立測試檔案:

    1
    echo "hello from windows host" > C:\host-test.txt
  2. 使用 Windows 路徑嘗試掛載 (失敗預期):

    1
    2
    # 這通常會報錯或看不到檔案內容
    docker run --rm -v C:\host-test.txt:/test.txt alpine cat /test.txt

    錯誤訊息是:

    1
    2
    3
    4
    PS C:\Users\Administrator> docker run --rm -v C:\host-test.txt:/test.txt alpine cat /test.txt
    docker: Error response from daemon: invalid mode: /test.txt

    Run 'docker run --help' for more information
  3. 使用 WSL 路徑格式掛載 (成功預期):
    在 WSL 中,Windows 的 C:\ 通常被掛載在 /mnt/c/

    1
    2
    # 注意這裡使用的是 Linux 格式的路徑
    docker run --rm -it -v "/mnt/c/host-test.txt:/test.txt" alpine cat /test.txt

結語

在做這篇文章的lab時,偷偷讓我試了一下winget,意外的碰上了憑證問題,看來我還是乖乖的用比較熟悉的chocolatey比較穩定

感覺這樣的用法比較適合用在喜歡使用cli環境的人,雖然平常開發上都會使用docker來模擬環境

但是要做一些常用操作我都寫成powershell或者shell檔案,在做的時候還需要去查一下要怎麼下指令

或許之後可以再來試試看使用podman desktop吧

但現在都用mac開發,orbstack真的比docker desktop啟動速度快多了,似乎也不太需要來用podman

參考資料

  1. Docker Desktop license agreement
  2. Install Docker Engine on Ubuntu
  3. 如何移除 Docker Desktop 並在 Windows 與 WSL 2 改安裝 Docker Engine