距離上次重度使用 WSL 已經快四年了。四年來 WSL 世界起了一些變化:

  • WSL 已經演進到第二版。

  • 以前還會為了要搭配 Cmder 或者 WSLtty 而大費周章,現在則被 Windows Terminal 解決了大部分問題,使用體驗也開始接近 Mac 的 iTerm2。

容器世界也起了很大的變化:

  • Docker Desktop 新規定:只要公司超過 250 人,或是年營收超過美金千萬,就必須付費。1 Docker Hub 也開始對未付費者施以較嚴格的限流措施。 2

  • Kubernetes 從 1.24 起停止支援 dockershim。 3

  • RedHat 釋出的 Podman,挾其完全免費、daemonless、rootless、pod 的特性,開始吸引對 Docker 起異心的人。

因此,我也趁此機會更新這方面的資訊,以免費的組合技,在 Windows 上盡量復刻 Mac 的容器體驗:

  1. 以 WSL 2 與 IDE 的整合,兼顧命令列與 GUI 體驗。
  2. 以 Podman 取代 Docker Desktop 的 container engine。
  3. 以 K3s 取代 Docker Desktop 的 Kubernetes。

註:如果不想以 WSL 2 為工作環境 (1),單純只想要一個 Desktop Desktop 替代方案 (2 + 3) 的人,可以直接選用 Rancher Desktop,就不必往下看了。

WSL 2

請依照保哥的文章〈介紹好用工具:從 Microsoft Store 安裝 WSL 1.0 版〉進行以下步驟:

  1. 更新 Windows 版本(譬如說,Windows 10 請更新至 22H2 以上,並確定套用過 KB5020030 patch)。

  2. 安裝 WSL。

  3. 更新 WSL 版本:wsl --update

  4. 查看 WSL 版本:wsl --version

如果一切順利,應該會看到類似以下的畫面:

請確定 WSL 版本是 1.0.3.0 以上,否則接下來可能會遇到一堆稀奇古怪的問題。 4

接下來,請繼續透過 WSL 安裝 Linux:

  1. 安裝一個 Linux distribution。

  2. 第一次執行 WSL,並設定 Linux 的帳號密碼。

建議編輯一下 WSL 的設定檔 /etc/wsl.conf

[boot]
systemd=true

[network]
# Disable auto-gen /etc/resolv.conf
generateResolvConf = false

# Disable auto-gen /etc/hosts
# @see https://github.com/composer/packagist/issues/950#issuecomment-424913225
generateHosts = false

如果要避免 WSL 占用過多系統資源,可編輯 Windows 的 $env:USERPROFILE\.wslconfig 檔案如下:

[wsl2]
memory=4GB
processors=2

如果要讓 Windows 慣用的 IDE 能夠與 WSL 合作順暢,請參考相關的設定:

Zsh + Oh My ZSH + Homebrew

在 WSL 中安裝 zsh 及 oh-my-zsh:

% sudo apt-get install zsh

% sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"

將 zsh 設為內定 shell:

% chsh -s $(which zsh)

如果你的 zsh theme 含有許多特殊的符號字元,請順便安裝 Powerline 系列字型。

Mac 族群一向愛用 Homebrew。既然它也搬到 Linux 世界了,就來安裝吧!

% sudo apt-get install build-essential curl file git
% sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"

% # 請記得要遵照安裝畫面出現的步驟做最後的設定!

Podman

透過 WSL 安裝好 Linux 之後,其實我們大可在裡面安裝純粹的 Docker Engine](https://docs.docker.com/engine/install/),即過去俗稱的 CE 版 (community edition) 或 Moby,它採用 Apache License 2.0 授權,不會有 Docker Desktop 的收費問題。

不過,我還是想玩玩具有 daemonless & rootless 特性的替代方案:Podman。

安裝

請依照 Podman 官方文件所載步驟安裝 Podman。譬如說,如果 WSL 的 distribution 是 Ubuntu 22.04.1 LTS,可如此安裝:

% sudo apt update
% sudo apt -y install podman

或是直接透過 Homebrew 安裝。好處是容易更新版本,缺點是安裝較慢:

% sudo apt install uidmap
% brew install podman

設定

Podman 是 daemonless + rootless 的架構。如果你希望讓 container 能夠自由綁定 port 80 以利本地開發,可以考慮在 /etc/sysctl.conf 添加設定:

net.ipv4.ip_unprivileged_port_start=80

還有一個選擇性步驟。如果你希望讓 image 不會被綁在 docker.io/library/ 這個預設的 registry,可以考慮在 /etc/containers/registries.conf 添加設定 5

unqualified-search-registries=[
  "registry.access.redhat.com", "registry.fedoraproject.org",
  "quay.io",
  "gcr.io",
  "ghcr.io",
  "docker.io"
]

便利性

為了讓 Podman 能盡量沿用過往 Docker 的使用習慣,建議在 $HOME/.bashrc 添加 alias:

alias docker='podman'

如果遇到 alias 也無法避開的問題,建議索性放一個 /usr/local/bin/docker 檔案:

#!/bin/bash

exec podman "$@"

Podman play kube

Podman 有一個介於 Docker 與 Kubernetes 之間的功能:pod。如果懂得善用,在許多情況下可以取代 Docker Compose,也做為邁向 Kubernetes 的踏腳石。

譬如說,如果我們稍加修改 Kubernetes 官網的 pod 範例 simple-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
spec:
  containers:
    - name: nginx
      image: docker.io/library/nginx:1.14.2
      ports:
        - containerPort: 80
          hostPort: 8080     # add this line

接下來就可用 podman play kube 指令在 WSL 啟用這個 nginx-pod

% sudo podman play kube simple-pod.yaml

如果一切順利,就可以在 WSL 裡面看到 nginx pod 成功執行:

% podman pod ps
POD ID        NAME        STATUS      CREATED            INFRA ID      # OF CONTAINERS
46be4ed3a73f  nginx-pod   Degraded    About an hour ago  93d658fa1939  2

% wget -O - localhost:8080

也可以在 Windows host 用瀏覽器看到 nginx 順利執行:

Podman Compose

Kubernetes 生態圈有一大堆媲美 Docker Compose 便利性的工具(譬如我愛用的 Skaffold)。不過,如果你實在太想念 Docker Compose,有兩種做法:

➀ 可直接沿用舊的 Docker Compose,但是需要將 Podman 啟動成 daemon 6

Docker Compose 的安裝方法:

% sudo curl -SL https://github.com/docker/compose/releases/download/v2.15.1/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose

% sudo chmod +x /usr/local/bin/docker-compose

➁ 如果不需顧及相容性,不妨試試 Podman 陣營端出的替代品 Podman Compose

對於 Podman Compose 感興趣的,請參考以下文章:

K3s

K3s 是由 Rancher Labs 貢獻給 CNCF 的輕量級 Kubernetes 開源方案,很適合應用程式開發者使用,作為 Docker Desktop 內建 Kubernetes 的替代方案。

請依照 K3s 官方文件所載步驟安裝: 7

% curl -sfL https://get.k3s.io | K3S_KUBECONFIG_MODE="644" sh -

為了讓其他 Kubernetes 相關工具順利運作,建議在 $HOME/.bashrc 添加 KUBECONFIG 環境變數:

export KUBECONFIG="~/.kube/config:/etc/rancher/k3s/k3s.yaml"

K9s

K9s 是很方便的 Kubernetes 終端機工具,請依照官方文件所載步驟安裝:

% brew install derailed/k9s/k9s

現在,我們可以用 k9s 指令查看剛剛安裝好的最陽春的 K3s 環境到底跑了哪些東西:

全部看一遍

截至目前為止,我們安裝好了 Podman 及 K3s,也利用 Podman 啟動一個 nginx pod。現在,讓我們看看整個 WSL 系統的 process tree:

整個 process tree 非常扁平,是不是跟以前 Docker Desktop 的版本很不一樣呢?

希望這篇文章,能夠讓你更放心擺脫 Docker Desktop。


  1. 根據 Docker FAQs 文件所載:“Docker Desktop requires a paid, per-user subscription for organizations with more than 250 employees or more than $10 million in annual revenue per our terms of service. [..] The updated terms for Docker Desktop were effective August 31, 2021, with a grace period until January 31, 2022.” ↩︎

  2. 根據 Docker Hub Download rate limit 文件所載:“For anonymous users, the rate limit is set to 100 pulls per 6 hours per IP address. For authenticated users, it’s 200 pulls per 6 hour period. Users with a paid Docker subscription get up to 5000 pulls per day.” ↩︎

  3. 關於 Kubernetes 1.24 停止支援 dockershim 的始末,請見 Updated: Dockershim Removal FAQ 這份文件。 ↩︎

  4. 譬如說在 “Systemd support is now available in WSL!” 一文就提到,如果 WSL 版本過舊,甚至連 Linux systemd 功能都會有問題。 ↩︎

  5. 關於 registries.conf 的更多設定內容,請見 How to manage Linux container registries 一文。 ↩︎

  6. 關於將 Podman 以 daemon mode 運作的具體步驟,請參考〈Podman Tips〉一文。 ↩︎

  7. 大部份的人會依照 K3s 首頁所載的步驟 curl -sfL https://get.k3s.io | sh - 來安裝 K3s,但這樣安裝好的 K3s 常會需要動用 sudo 才能執行相關指令。我認為,與其事後再用 k3s permission denied when using kubectl 所介紹的方法調整設定,不如從一開始就以不需動用 sudo 的方式安裝。 ↩︎