# 如何移除 Docker Desktop 並在 Windows 與 WSL 2 改安裝 Docker Engine

今天我的 [Docker Desktop for Windows](https://docs.docker.com/desktop/setup/install/windows-install/) 又掛掉了，五年來的第三次，毫無原因，導致我所有容器、所有 Image 全部都被清空。這次真的氣到，不用了，決定把 Docker 全部都移往 WSL 2 執行，聽幾個可靠的朋友說，讓 Docker Engine 跑在原生的 WSL 2 底下，不但速度快，服務也穩定許多。所以這篇文章，我要來記錄一下完整的設定過程。

![image](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/486352efc093b848dfdb-5a029151-7f3c-4bcc-a27d-198e135a3b2e.webp)

### 1\. 完整移除 Docker Desktop for Windows

首先，你必須從 Windows 的控制台移除 Docker Desktop 程式。

然後，你要登入 WSL 2 移除以下兩個符號連結檔案 (Symbolic Link File)：

```bash
rm -f ~/.docker/contexts ~/.docker/features.json
```

接著，從 WSL 2 刪除所有 `cli-plugins` 檔案：

```bash
sudo rm /usr/local/lib/docker/cli-plugins/docker-*
```

最後，在 Windows 重啟 WSL 服務！

```powershell
wsl.exe --shutdown
```

然後確認 WSL 核心是最新版本：

```powershell
wsl --version
wsl --update
wsl --version
```

### 2\. 在 WSL 2 安裝 Docker / Docker Compose v2

```bash
# 下載安裝腳本
# https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script
curl -fsSL https://get.docker.com -o get-docker.sh

# 執行安裝命令，過程會提示你要安裝 Docker Desktop
# 但我們就是不爽才改裝到 WSL 這裡的，請不要理會這些訊息，等十秒就會自動開始安裝
sudo sh get-docker.sh

# 把你個人的帳號加入到 docker 群組
# Manage Docker as a non-root user
# https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user
sudo usermod -aG docker $USER

# 檢查已安裝版本
docker --version
docker compose version
```

### 3\. 透過 WSL 2 的 systemd 服務啟動 Docker Engine

要在 WSL 2 啟動 Docker Engine 有兩種方式：

1.  登入帳號時才啟動引擎
    
    把以下這段命令加入到 `~/.profile` 檔案即可：
    
    ```bash
    if grep -q "\-WSL2" /proc/version > /dev/null 2>&1; then
        if service docker status 2>&1 | grep -q "is not running"; then
            wsl.exe --distribution "${WSL_DISTRO_NAME}" --user root \
                --exec /usr/sbin/service docker start > /dev/null 2>&1
        fi
    fi
    ```
    
    💡 如果你想透過 `systemd` 啟動 Docker Engine 的話，這段命令是不需要設定的！
    
2.  透過 `systemd` 服務啟動 Docker Engine
    
    總之，就是隨著電腦一起啟動 WSL 2 中的背景服務。詳見: [Systemd support is now available in WSL!](https://devblogs.microsoft.com/commandline/systemd-support-is-now-available-in-wsl/?WT.mc_id=DT-MVP-4015686)
    
    我不太確定 systemd 目前是否是自動會啟用，但你依然可以檢查一下 `/etc/wsl.conf` 這個設定檔：
    
    ```ini
    [boot]
    systemd=true
    ```
    
    你可以透過以下命令查找是否有個 `docker.service` 服務：
    
    ```bash
    systemctl list-unit-files --type=service
    ```
    
    查看 `docker.service` 的狀態：
    
    ```bash
    systemctl status docker.service
    ```
    

### 4\. 讓 dockerd 同時聽 Unix socket file 與 TCP 連線

我主要是希望跑在 WSL 2 的 Docker Engine 同時也可以讓 Windows 原生環境下也能直接使用，而且也想讓開在 Windows 的 Visual Studio Code 也能直接連到 Docker Engine 進行管理！

以下命令請在 WSL 2 環境中執行：

```bash
# 1. 讓 dockerd 同時聽 Unix 與 TCP
sudo tee /etc/docker/daemon.json <<'EOF'
{
  "hosts": [
    "unix:///var/run/docker.sock",
    "tcp://127.0.0.1:2375"
  ]
}
EOF

# 2. 新增或編輯 systemd 背景服務設定 (docker.service)
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo tee /etc/systemd/system/docker.service.d/override.conf <<'EOF'
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd --containerd=/run/containerd/containerd.sock
EOF

# 3. 套用變更
sudo systemctl daemon-reload
sudo systemctl restart docker

# 4. 驗證
# 看到 LISTEN 狀態代表成功
ss -lntp | grep 2375
```

💡 我們在 `/etc/docker/daemon.json` 檔案中加入 `tcp://0.0.0.0:2375` 或 `tcp://127.0.0.1:2375` 之後，你就可以從 Windows 直接透過 `localhost:2375` 就可以連上 WSL 2 環境下的 Docker Engine！

### 5\. 讓 Windows 命令提示字元下也能使用 docker 命令

我使用 Chocolatey 安裝 [Docker CLI](https://community.chocolatey.org/packages/docker-cli) 與 [Docker Compose V2](https://community.chocolatey.org/packages/docker-compose) 命令列工具：

```bash
choco install docker-cli docker-compose -y
```

安裝好之後，還要設定一個 `DOCKER_HOST` 環境變數，你可以設定到控制台中，也可以直接用以下命令設定：

-   PowerShell
    
    ```bash
    $env:DOCKER_HOST='localhost:2375'
    ```
    
-   Command Prompt
    
    ```batch
    set DOCKER_HOST=localhost:2375
    ```
    

最後我們查詢一下 CLI 工具版本，也順便查詢 Docker Engine 版本：

```bash
docker compose version

docker version
```

💡 注意：如果 `docker verison` 有顯示連不上，出現以下錯誤訊息：

```log
error during connect: Get "http://localhost:2375/v1.50/version": dial tcp [::1]:2375: connectex: No connection could be made because the target machine actively refused it.
```

那就有可能是你的 WSL 2 目前是停止狀態，啟動 WSL 2 之後 systemd 會一併把 `docker.service` 啟動，只是時間可能會花上 10 ~ 20 秒左右。

如果都可以成功連上的話，就可以測試跑跑看一個簡單容器：

```bash
docker run --rm -it hello-world
```

然後可以進階一點，直接把 SQL Server 2022 執行起來：

```bash
docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=P@ssw0rd1234' -p 1433:1433 -d --name=sqlserver mcr.microsoft.com/mssql/server:2022-latest
```

接著你就可以用 [sqlcmd](https://learn.microsoft.com/en-us/sql/tools/sqlcmd/sqlcmd-utility?view=sql-server-ver17&tabs=go%2Clinux%2Cwindows-support&pivots=cs1-powershell&WT.mc_id=DT-MVP-4015686)、[SqlPackage](https://learn.microsoft.com/zh-tw/sql/tools/sqlpackage/sqlpackage-download?view=sql-server-ver16&WT.mc_id=DT-MVP-4015686) 或 [SSMS](https://learn.microsoft.com/en-us/ssms/release-notes-21?view=sql-server-ver17&WT.mc_id=DT-MVP-4015686) 來連接容器中的 SQL Server：

```bash
# 建議不要用 localhost 連線，改用 127.0.0.1 才是比較可靠的方法，因為 localhost 有可能被解析成 IPv6 位址！
sqlcmd -H 127.0.0.1 -U sa -P P@ssw0rd1234 -Q "SELECT database_id FROM sys.databases"
```

或者是直接把 [Portainer](https://www.portainer.io/) 裝起來，直接取代 Docker Desktop 的 UI 介面：

```bash
docker volume create portainer_data
docker run -d -p 8000:8000 -p 9000:9000 -p 9443:9443 --name portainer \
        --restart=always \
        -v /var/run/docker.sock:/var/run/docker.sock \
        -v portainer_data:/data \
        portainer/portainer-ce:latest
```

💡 透過 [http://localhost:9000/](http://localhost:9000/) 就可以連上管理介面！

### 6\. 讓 VS Code 的 Container Tools 也能管理 Docker Engine

怕有人不知道，所先聲明一下，微軟近期將他們做的 Docker 擴充套件，更名為 [Container Tools](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-containers)。

直接在 VS Code 使用者設定中，加入以下設定即可：

```json
{
  "containers.environment": {
      "DOCKER_HOST": "tcp://localhost:2375"
  }
}
```

### 7\. 直接從 WSL 啟動 VS Code Server

其實在多年前開始，[WSL](https://docs.microsoft.com/en-us/windows/wsl) 與 [VS Code](https://code.visualstudio.com/) 早就已經無縫整合在一起，只要你 Windows 下的 VS Code 有安裝 [Remote Development](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack) 擴充套件，你直接在 WSL 的 Terminal 下執行 `code .` 就可以將目前資料夾開在 Windows 本機環境的 VS Code 之中，過程中會自動下載 VS Code Server 在你的 WSL 2 環境中，然後可以直接「遠端開發」，非常厲害！

詳細文件請參考 [Remote Development with Linux](https://code.visualstudio.com/docs/remote/linux)

下載 [Remote Development](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack) 擴充套件也會連同安裝以下這幾個擴充套件，全部都是遠端開發的威力套件：

-   [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
-   [Remote - Tunnels](https://marketplace.visualstudio.com/items?itemName=ms-vscode.remote-server)
-   [Remote - SSH](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh)
-   [WSL](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-wsl)

### 相關連結

-   [Install Docker in WSL 2 without Docker Desktop](https://nickjanetakis.com/blog/install-docker-in-wsl-2-without-docker-desktop)
-   [Container Tools - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-containers)
-   [Configure remote access for Docker daemon | Docker Docs](https://docs.docker.com/engine/daemon/remote-access/)
-   [Running Docker Engine on WSL 2](https://blog.avenuecode.com/running-docker-engine-on-wsl-2)
-   [WSL](https://docs.microsoft.com/en-us/windows/wsl)
