返回文章列表

WSL 高效開發環境建置:從安裝到生產力完全指南

深入探討 Windows Subsystem for Linux 開發環境建置的完整實務指南。從 WSL 2 核心架構到 Docker Desktop 整合,涵蓋效能最佳化配置、資源管理策略與 VS Code Remote-WSL 開發工作流程,提供詳細的實作步驟與最佳實務建議。

開發工具 系統架構 容器化技術

傳統上 Windows 開發者若需要使用 Linux 環境,通常只有兩種選擇:安裝雙系統或使用虛擬機器。雙系統需要重新開機切換,嚴重影響工作流程的連續性。虛擬機器雖然能同時執行兩個系統,但會佔用大量的系統資源,而且 Windows 與 Linux 之間的檔案共享與整合相當複雜。這些限制讓許多開發者在 Windows 上開發 Linux 應用程式時面臨諸多不便。

Windows Subsystem for Linux(WSL)的出現徹底改變了這個局面。WSL 讓開發者能夠在 Windows 上直接執行 Linux 二進位執行檔,無需虛擬機器的額外負擔,也不需要重新開機切換系統。特別是 WSL 2 採用了完整的 Linux 核心,大幅提升了系統呼叫的相容性與檔案系統的效能。開發者可以在熟悉的 Windows 環境中使用 Visual Studio Code,同時在 WSL 中執行 Linux 工具鏈,實現真正的無縫整合。

然而要充分發揮 WSL 的潛力,需要正確的配置與調校。WSL 2 雖然效能優異,但預設的資源限制可能不適合所有開發場景。Docker Desktop 與 WSL 的整合雖然方便,但需要理解其架構才能避免常見的陷阱。Visual Studio Code 的 Remote-WSL 擴充套件功能強大,但需要適當的配置才能獲得最佳體驗。

本文將帶領讀者從零開始建構一個高效的 WSL 開發環境。我們將深入探討 WSL 2 的安裝與配置,解說如何整合 Docker Desktop 進行容器化開發,分享效能調校的實務技巧,並示範如何使用 Visual Studio Code 建立流暢的開發工作流程。透過詳細的步驟說明與程式碼範例,讀者將能夠建構一個媲美原生 Linux 的開發環境。

WSL 2 安裝與核心配置

WSL 有兩個主要版本:WSL 1 與 WSL 2。WSL 1 使用轉譯層將 Linux 系統呼叫轉換為 Windows NT 核心呼叫,雖然啟動速度快,但系統呼叫的相容性與檔案 I/O 效能有限。WSL 2 則採用了輕量級虛擬機器技術,執行完整的 Linux 核心,提供了接近原生 Linux 的效能與相容性。對於現代開發工作,強烈建議使用 WSL 2。

# 以系統管理員權限開啟 PowerShell

# 啟用 WSL 功能
# 這個命令會啟用 Windows Subsystem for Linux 功能
# 需要重新啟動電腦才能生效
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

# 啟用虛擬機器平台
# WSL 2 需要虛擬機器平台支援
# 這是 WSL 2 運作的基礎
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

# 重新啟動電腦
# 必須重新啟動才能使上述功能生效
Restart-Computer

# 重新開機後,設定 WSL 2 為預設版本
# 這樣之後安裝的 Linux 發行版都會使用 WSL 2
wsl --set-default-version 2

# 列出可用的 Linux 發行版
# 顯示 Microsoft Store 中所有可安裝的 Linux 發行版
wsl --list --online

# 安裝 Ubuntu 22.04 LTS
# 這是目前最穩定且廣泛使用的發行版之一
# 安裝過程會要求設定使用者名稱與密碼
wsl --install -d Ubuntu-22.04

# 驗證安裝
# 列出所有已安裝的 WSL 發行版
# -v 參數會顯示詳細資訊,包括版本號
wsl --list --verbose

# 更新 WSL 核心
# 確保使用最新的 WSL 核心版本
# 這能獲得最新的功能與安全性修復
wsl --update

# 檢查 WSL 版本
# 顯示 WSL 的版本資訊與已安裝的發行版
wsl --status

安裝完成後,需要進入 WSL 環境進行初始配置。這包括更新套件管理器、安裝常用開發工具與配置環境變數。以下是一個完整的初始化腳本。

#!/bin/bash
# WSL Ubuntu 初始化配置腳本
# 
# 這個腳本會執行以下操作:
# 1. 更新系統套件
# 2. 安裝常用開發工具
# 3. 配置 Git
# 4. 安裝 Node.js 與 Python
# 5. 配置 shell 環境

# 更新套件索引
# 確保套件管理器有最新的套件清單
echo "更新套件索引..."
sudo apt update

# 升級所有已安裝的套件
# 將系統中所有套件更新到最新版本
echo "升級系統套件..."
sudo apt upgrade -y

# 安裝基礎開發工具
# build-essential 包含 gcc、g++、make 等編譯工具
# curl 與 wget 用於下載檔案
# git 用於版本控制
# vim 是文字編輯器
echo "安裝基礎開發工具..."
sudo apt install -y \
    build-essential \
    curl \
    wget \
    git \
    vim \
    tree \
    htop \
    net-tools

# 配置 Git
# 設定全域的使用者名稱與電子郵件
# 這些資訊會出現在 Git 提交記錄中
echo "配置 Git..."
git config --global user.name "Your Name"
git config --global user.email "[email protected]"

# 設定 Git 的預設編輯器為 vim
git config --global core.editor vim

# 設定 Git 的換行符處理
# input 表示在提交時將 CRLF 轉換為 LF
# 這對於跨平台開發很重要
git config --global core.autocrlf input

# 安裝 Node.js 使用 nvm
# nvm 是 Node.js 版本管理器,可以輕鬆切換不同版本
echo "安裝 Node.js 版本管理器 (nvm)..."
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash

# 載入 nvm
# 執行 nvm 的初始化腳本
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

# 安裝最新的 LTS 版本 Node.js
# LTS (Long Term Support) 版本更穩定
echo "安裝 Node.js LTS..."
nvm install --lts
nvm use --lts

# 驗證 Node.js 與 npm 安裝
node --version
npm --version

# 安裝 Python 開發環境
# Python 3 與 pip 套件管理器
echo "安裝 Python 開發環境..."
sudo apt install -y \
    python3 \
    python3-pip \
    python3-venv

# 升級 pip 到最新版本
python3 -m pip install --upgrade pip

# 配置 shell 環境
# 在 .bashrc 中加入自訂配置
echo "配置 shell 環境..."

# 加入自訂的 alias
cat >> ~/.bashrc << 'EOF'

# 自訂 alias
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
alias gs='git status'
alias ga='git add'
alias gc='git commit'
alias gp='git push'

# 設定彩色提示符
export PS1='\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '

# Node.js 路徑
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
EOF

# 重新載入 .bashrc
source ~/.bashrc

echo "WSL 初始化完成!"
echo "請執行 'source ~/.bashrc' 來載入新的環境設定"

WSL 2 的一個重要特性是可以透過 .wslconfig 檔案配置虛擬機器的資源限制。這個檔案位於 Windows 使用者目錄下,可以控制 WSL 2 使用的記憶體、處理器與交換空間。

# .wslconfig 檔案
# 位置:C:\Users\<YourUsername>\.wslconfig
# 
# 這個檔案用於配置 WSL 2 虛擬機器的全域設定
# 修改後需要執行 wsl --shutdown 重新啟動 WSL 才能生效

[wsl2]
# 記憶體限制
# 設定 WSL 2 可以使用的最大記憶體
# 預設是系統記憶體的 50% 或 8GB(取較小值)
# 範例:限制為 8GB
memory=8GB

# 處理器核心數
# 設定 WSL 2 可以使用的處理器核心數
# 預設使用所有可用的核心
# 範例:限制為 4 個核心
processors=4

# 交換空間大小
# 設定 WSL 2 的虛擬記憶體大小
# 預設是實體記憶體的 25%
# 設定為 0 可以停用交換空間
# 範例:設定為 2GB
swap=2GB

# 交換檔案路徑
# 指定交換檔案的儲存位置
# 預設在 %USERPROFILE%\AppData\Local\Temp\swap.vhdx
swapfile=C:\\temp\\wsl-swap.vhdx

# 本地主機轉發
# 啟用後可以從 Windows 存取 WSL 中監聽的埠
# 預設為 true
localhostforwarding=true

# 巢狀虛擬化
# 允許在 WSL 2 中執行虛擬機器
# 某些容器化工作負載可能需要這個功能
# 預設為 false
nestedVirtualization=true

# 核心命令列參數
# 傳遞給 Linux 核心的額外參數
# 可以用於啟用特定的核心功能
# kernelCommandLine = vsyscall=emulate

# 安全啟動
# 是否啟用安全啟動
# 預設為 true
# safeMode=true

# 除錯控制台
# 啟用核心除錯控制台輸出
# 用於診斷核心問題
# debugConsole=false
@startuml
!define PLANTUML_FORMAT svg
!theme _none_

skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 14
skinparam minClassWidth 100

|Windows 使用者|
start

:執行 wsl --install;

|Windows PowerShell|
:檢查系統需求;

if (支援虛擬化?) then (是)
  :啟用 WSL 功能;
  
  :啟用虛擬機器平台;
  
  :提示重新啟動;
  
  |Windows 使用者|
  :重新啟動電腦;
  
  |Windows PowerShell|
  :下載 Linux 核心更新;
  
  :安裝 Linux 核心;
  
  :下載 Ubuntu 映像檔;
  
  |Hyper-V|
  :建立 WSL 2 虛擬機器;
  
  :配置虛擬硬碟;
  
  :載入 Linux 核心;
  
  |Ubuntu|
  :初始化檔案系統;
  
  :啟動 init 程序;
  
  :提示建立使用者;
  
  |Windows 使用者|
  :輸入使用者名稱與密碼;
  
  |Ubuntu|
  :建立使用者帳號;
  
  :配置 sudo 權限;
  
  :啟動 shell;
  
  |Windows 使用者|
  :執行初始化腳本;
  
  :更新套件;
  
  :安裝開發工具;
  
  :配置環境變數;
  
  :安裝完成;
  
  stop
else (否)
  :顯示錯誤訊息;
  
  |Windows 使用者|
  :檢查 BIOS 設定;
  
  stop
endif

@enduml

Docker Desktop 與 WSL 2 深度整合

Docker Desktop 是 Windows 上最流行的容器化平台,它與 WSL 2 的整合提供了卓越的效能與開發體驗。相較於傳統的 Hyper-V 後端,WSL 2 後端啟動更快,資源使用更有效率,且能與 WSL 發行版無縫整合。開發者可以在 WSL 中使用 docker 命令列工具,同時享受 Docker Desktop 的圖形介面管理功能。

# 在 Windows 上下載並安裝 Docker Desktop
# 從官方網站下載:https://www.docker.com/products/docker-desktop

# 安裝後,在 Docker Desktop 設定中:
# 1. 進入 Settings -> General
# 2. 勾選 "Use the WSL 2 based engine"
# 3. 進入 Settings -> Resources -> WSL Integration
# 4. 啟用想要使用 Docker 的 WSL 發行版

# 驗證 Docker 是否正確安裝(在 WSL 中執行)
docker --version
docker-compose --version

# 測試 Docker 執行
# 執行一個簡單的 hello-world 容器
docker run hello-world

在 WSL 環境中,Docker 的使用與原生 Linux 幾乎完全相同。以下範例展示如何建立一個完整的開發環境,包括資料庫、快取與應用程式伺服器。

# docker-compose.yml
# 定義一個完整的 Web 應用程式開發環境
# 包含 PostgreSQL 資料庫、Redis 快取與 Node.js 應用程式

version: '3.8'

# 定義服務
services:
  # PostgreSQL 資料庫服務
  postgres:
    # 使用官方的 PostgreSQL 14 映像檔
    image: postgres:14-alpine
    
    # 容器名稱
    container_name: dev_postgres
    
    # 環境變數配置
    environment:
      # 資料庫超級使用者密碼
      POSTGRES_PASSWORD: devpassword
      
      # 預設資料庫名稱
      POSTGRES_DB: appdb
      
      # 預設使用者名稱(預設為 postgres)
      POSTGRES_USER: devuser
    
    # 埠號映射
    # 將容器的 5432 埠映射到主機的 5432 埠
    ports:
      - "5432:5432"
    
    # 資料卷掛載
    # 持久化資料庫資料
    volumes:
      # 將資料庫資料儲存在 Docker 管理的卷中
      - postgres_data:/var/lib/postgresql/data
      
      # 掛載初始化 SQL 腳本
      # 容器啟動時會自動執行這個目錄中的 .sql 檔案
      - ./init-scripts:/docker-entrypoint-initdb.d
    
    # 健康檢查
    # 確保資料庫服務正常運作
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U devuser -d appdb"]
      interval: 10s
      timeout: 5s
      retries: 5
    
    # 網路配置
    networks:
      - dev_network
  
  # Redis 快取服務
  redis:
    # 使用官方的 Redis Alpine 映像檔
    image: redis:7-alpine
    
    container_name: dev_redis
    
    # 埠號映射
    ports:
      - "6379:6379"
    
    # 啟動命令
    # 啟用 AOF 持久化
    command: redis-server --appendonly yes
    
    # 資料卷掛載
    volumes:
      - redis_data:/data
    
    # 健康檢查
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
    
    networks:
      - dev_network
  
  # Node.js 應用程式服務
  app:
    # 使用 Node.js 18 Alpine 映像檔
    image: node:18-alpine
    
    container_name: dev_app
    
    # 工作目錄
    working_dir: /app
    
    # 環境變數
    environment:
      # Node.js 環境
      NODE_ENV: development
      
      # 資料庫連線字串
      DATABASE_URL: postgresql://devuser:devpassword@postgres:5432/appdb
      
      # Redis 連線字串
      REDIS_URL: redis://redis:6379
    
    # 埠號映射
    ports:
      - "3000:3000"
    
    # 資料卷掛載
    volumes:
      # 掛載當前目錄到容器的 /app
      # 這樣可以即時反映程式碼變更
      - .:/app
      
      # 使用匿名卷避免 node_modules 被覆蓋
      # WSL 與 Windows 之間的 node_modules 可能不相容
      - /app/node_modules
    
    # 啟動命令
    # 使用 nodemon 監視檔案變更並自動重啟
    command: sh -c "npm install && npm run dev"
    
    # 依賴關係
    # 等待資料庫與快取服務啟動
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    
    networks:
      - dev_network

# 定義資料卷
# 用於持久化資料
volumes:
  # PostgreSQL 資料卷
  postgres_data:
    driver: local
  
  # Redis 資料卷
  redis_data:
    driver: local

# 定義網路
# 所有服務在同一個網路中可以互相通訊
networks:
  dev_network:
    driver: bridge

Docker 在 WSL 中的使用還包括一些效能最佳化技巧。由於 WSL 2 使用虛擬檔案系統,跨 Windows 與 Linux 檔案系統的操作會有效能損失。因此建議將專案檔案存放在 WSL 檔案系統中(例如 /home/username/projects)而非 Windows 檔案系統(例如 /mnt/c/Users/...)。

# 在 WSL 中管理 Docker 的常用命令

# 啟動所有服務
# -d 參數表示在背景執行
docker-compose up -d

# 查看服務狀態
# 顯示所有容器的狀態、埠號映射等資訊
docker-compose ps

# 查看服務日誌
# -f 參數表示持續追蹤日誌輸出
docker-compose logs -f

# 查看特定服務的日誌
docker-compose logs -f app

# 進入容器的 shell
# 用於除錯或執行命令
docker-compose exec app sh

# 停止所有服務
# 容器會被停止但不會被刪除
docker-compose stop

# 停止並刪除所有容器
# -v 參數會同時刪除匿名卷
docker-compose down -v

# 重新建構映像檔
# 當 Dockerfile 或依賴項變更時使用
docker-compose build

# 重新建構並啟動服務
docker-compose up -d --build

# 清理未使用的資源
# 刪除停止的容器、未使用的網路與映像檔
docker system prune -a

# 查看 Docker 磁碟使用情況
docker system df

Visual Studio Code Remote-WSL 開發環境

Visual Studio Code 的 Remote-WSL 擴充套件讓開發者能夠在 Windows 中使用 VS Code 的圖形介面,同時在 WSL 中執行所有的開發工具與執行環境。這種架構結合了兩個系統的優勢:Windows 的熟悉介面與 Linux 的強大工具鏈。

# 在 WSL 中安裝 VS Code 伺服器元件
# 實際上不需要手動安裝,Remote-WSL 會自動處理

# 從 WSL 中開啟 VS Code
# 這個命令會在 Windows 中啟動 VS Code
# 並自動連接到 WSL 環境
code .

# 如果這是第一次執行,VS Code 會自動安裝 WSL 伺服器元件
# 之後的啟動會更快

在 VS Code 中配置 WSL 開發環境需要安裝適當的擴充套件,並設定工作區的配置。以下是一個完整的 Node.js 專案配置範例。

// .vscode/settings.json
// VS Code 工作區設定檔
{
  // 整合終端機設定
  "terminal.integrated.defaultProfile.linux": "bash",
  
  // 檔案監視排除
  // 排除不需要監視的目錄以提升效能
  "files.watcherExclude": {
    "**/node_modules/**": true,
    "**/.git/objects/**": true,
    "**/.git/subtree-cache/**": true,
    "**/dist/**": true
  },
  
  // 檔案搜尋排除
  "search.exclude": {
    "**/node_modules": true,
    "**/dist": true,
    "**/.git": true
  },
  
  // ESLint 配置
  "eslint.enable": true,
  "eslint.validate": [
    "javascript",
    "typescript"
  ],
  
  // Prettier 配置
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  
  // TypeScript 配置
  "typescript.updateImportsOnFileMove.enabled": "always",
  
  // Git 配置
  "git.autofetch": true,
  "git.confirmSync": false,
  
  // 編輯器配置
  "editor.tabSize": 2,
  "editor.insertSpaces": true,
  "editor.rulers": [80, 120],
  
  // 遠端開發設定
  // 指定在 WSL 中安裝的擴充套件
  "remote.extensionKind": {
    "ms-vscode.cpptools": ["workspace"]
  }
}
// .vscode/launch.json
// VS Code 除錯配置檔
{
  "version": "0.2.0",
  "configurations": [
    {
      // Node.js 應用程式除錯配置
      "type": "node",
      "request": "launch",
      "name": "Launch Program",
      
      // 要執行的程式進入點
      "program": "${workspaceFolder}/src/index.js",
      
      // 執行前先編譯 TypeScript(如果使用 TS)
      "preLaunchTask": "tsc: build - tsconfig.json",
      
      // 輸出配置
      "outFiles": [
        "${workspaceFolder}/dist/**/*.js"
      ],
      
      // 環境變數
      "env": {
        "NODE_ENV": "development"
      },
      
      // 控制台配置
      "console": "integratedTerminal",
      
      // 自動附加子程序
      "autoAttachChildProcesses": true
    },
    {
      // Docker 容器中的應用程式除錯配置
      "type": "node",
      "request": "attach",
      "name": "Attach to Docker",
      
      // 連接埠號(容器需要開放除錯埠)
      "port": 9229,
      
      // 本地檔案與遠端檔案的路徑映射
      "localRoot": "${workspaceFolder}",
      "remoteRoot": "/app",
      
      // 重啟時自動重新附加
      "restart": true,
      
      // 跳過不需要除錯的檔案
      "skipFiles": [
        "<node_internals>/**"
      ]
    }
  ]
}
@startuml
!define PLANTUML_FORMAT svg
!theme _none_

skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 14
skinparam minClassWidth 100

|開發者|
start

:在 WSL 中開啟專案目錄;

:執行 code .;

|VS Code (Windows)|
:啟動 VS Code 視窗;

if (已安裝 Remote-WSL?) then (是)
  :檢查 WSL 伺服器元件;
  
  if (伺服器已安裝?) then (是)
    :連接到 WSL;
  else (否)
    :下載並安裝伺服器元件;
    
    |WSL|
    :安裝 VS Code Server;
    
    :啟動伺服器程序;
    
    |VS Code (Windows)|
    :建立連線;
  endif
else (否)
  :提示安裝 Remote-WSL 擴充套件;
  
  |開發者|
  :安裝擴充套件;
  
  |VS Code (Windows)|
  :重新連接;
endif

:載入工作區設定;

:掃描專案檔案;

|WSL|
:執行檔案系統操作;

:回傳檔案清單;

|VS Code (Windows)|
:顯示專案結構;

|開發者|
:編輯程式碼;

|VS Code (Windows)|
:傳送變更到 WSL;

|WSL|
:更新檔案;

:觸發 nodemon 重新載入;

|Docker Container|
:重新啟動應用程式;

|開發者|
:在瀏覽器測試;

if (需要除錯?) then (是)
  :設定中斷點;
  
  :啟動除錯器;
  
  |VS Code (Windows)|
  :連接到 Node.js 除錯埠;
  
  |WSL / Docker|
  :暫停於中斷點;
  
  :回傳變數狀態;
  
  |VS Code (Windows)|
  :顯示除錯資訊;
  
  |開發者|
  :檢查變數;
  
  :繼續執行;
endif

stop

@enduml

從實務角度來看,WSL 2 已經成為 Windows 開發者不可或缺的工具。它消除了傳統跨平台開發的諸多障礙,讓開發者能夠在 Windows 上享受接近原生 Linux 的開發體驗。Docker Desktop 與 WSL 2 的整合更是將容器化開發帶入了新的境界,啟動速度與資源效率都遠超傳統的虛擬機器方案。

效能調校是充分發揮 WSL 潛力的關鍵。透過 .wslconfig 適當配置記憶體與處理器資源,可以在效能與系統穩定性之間找到平衡。將專案檔案存放在 WSL 檔案系統而非 Windows 檔案系統,能夠顯著提升檔案 I/O 效能。理解 WSL 與 Windows 之間的檔案系統互動機制,有助於避免常見的效能陷阱。

Visual Studio Code 的 Remote-WSL 擴充套件完美地整合了兩個系統。開發者可以使用熟悉的 Windows 圖形介面,同時在 WSL 中執行所有的建構工具、測試框架與除錯器。這種架構不僅提升了生產力,也讓多人協作更加順暢,因為整個團隊可以使用相同的 Linux 環境,而不必擔心 Windows 與 macOS 或 Linux 之間的差異。

展望未來,WSL 的發展將繼續深化 Windows 與 Linux 的整合。WSLg 已經為圖形應用程式提供了良好的支援,未來可能會看到更多的系統層級整合。對於開發者而言,掌握 WSL 不僅是一個技術選擇,更是提升開發效率與擴展技術能力的重要途徑。