3540 字
18 分鐘
【DevOps】在 Windows 安裝 WSL2 和 Podman
程式寫好後,打包與部署也是一段繁雜的操作流程,這就是現代 DevOps 重要的一環;來學一點現代的解方——容器化(Containerization)。
Why?
先講一些基礎概念和我為何選擇、需要這些工具:
Why 容器化(Containerization)?
- 新技術的推出總是因為想解決舊技術的一些問題——以一個前後端分離的 web app 舉例,容器化技術想解決的舊問題大致如下:
- 部署一個 web app 的多個服務需要一台 VM,從裝 Linux 作業系統開始,然後前端需要 web server 如 Apache 或 nginx、後端需要程式語言的執行環境如 Java 或 Node.js 等等、還需要裝資料庫,都裝好後依序設環境變數,流程繁雜。
- 如果有第二個 web app 想要部署?再開一台 VM 比較穩定、但耗更多資源;和之前的 web app 共用一台 VM 也不是不行,不過就會互相影響,比如其中一個 app 把記憶體或硬碟佔滿導致 VM 掛掉、兩個 app 一起死。
- 開發過程在開發電腦的環境裡測試沒問題,但是上到生產環境 VM 裡有些不曉得哪裡的執行環境設定不太一樣、導致跑起來出問題,除錯麻煩……
- 容器化技術能夠解決以上這些問題,原理……簡單講是把虛擬化的層級從傳統 VM 的作業系統層級往上一層,每個環境不需要各自有一個完整的作業系統、而是多個 container 共用一個作業系統核心。
- 一個 web app 的多個服務各打包為一個 image,透過
compose.yaml這類腳本一併處理打包為多個 image 與執行多個 container,方便自動化處理、省下人工操作的麻煩與高錯誤率。- 前端可以把 web server 和前端 build 好的結果包成一個 container,後端也可以把執行環境和 build 出的結果包成一個 container,再一個資料庫的 container,就能跑起前後端分離的 web app 了。
- 多個 container 是獨立的,不過能透過 port 溝通、所以後端 container 還是能用傳統的方式連接到資料庫 container。
- 開發電腦上也用一樣的 image 建立 container 測試執行,就與生產環境 VM 裡幾乎相同了。
- 一個 web app 的多個服務各打包為一個 image,透過
Image 與 Container
- Image:譯作「映像檔」,是已打包好、但靜態躺著未被執行的程式模板;有點像是 OOP 概念裡的 class。
- Container:譯作「容器」,是照著程式模板執行起來的實例;有點像是 OOP 概念裡基於 class 創建的 instance。
- Container 使用的資料會存放在 Volume,類似於電腦的硬碟、拔掉換一顆資料就全部不見;管理 Container 的工具通常可以一併管理其 Volume。
Why WSL2?
- WSL,全稱「Windows Subsystem for Linux」,是 Windows 官方內建的 Linux 核心
- 比跑在 VirtualBox VM 裡的 Linux 更原生支援、且可以和平常使用的 Windows 作業系統同時運行
- 有分 WSL 和 WSL2,前者的概念比較像把 Linux 指令翻譯成 Windows 作業系統聽得懂的指令去執行,後者就真的是 VM 了,也因此後者支援 Linux 的功能較為完整
- 稍早說明容器化時有提到可在同個 VM 裡透過容器管理工具執行 container,不過目前的容器管理工具僅支援在 Linux 作業系統上執行……所以要想在 Windows 上執行,就要靠 WSL2 了!
Why Podman?
- 容器化技術現已有開放標準「OCI(Open Container Initiative)」,所以各家可以根據標準做自己的實現產品、打包出的 image 可以共用
- 較早推出、目前也最普及的容器管理工具是 Docker,學習資源也較多;相較之下 Podman 又是新技術了,相比的優勢大概有以下幾點:
- Docker 的本體是開源的,但 Windows 上需要一併使用的 Docker Desktop 不是開源,只是非營利下可免費使用;Podman 和 Podman Desktop 則皆為開源。
- Docker 執行時需要 root 權限,Podman 則不需要,隔離權限以提高安全性。
- Podman 作為市場挑戰者(?),設計基本指令時用法幾乎都和 Docker 一模一樣,在兩者之間轉換的重新學習成本很低。
- 考量到 Podman 有其優勢,又因為 OCI 和指令用法相同、未來如果一些情境必須用 Docker 也不難轉換,所以我決定直接從 Podman 學起。
Why Podman Desktop?
- 雖然確實可以只在 WSL2 VM 裡裝 Podman,但那樣的話在 Windows 作業系統這邊就沒辦法用了
- Podman Desktop 就是為了能在 Windows 作業系統這邊執行而設計的工具,而且還有 GUI、方便檢視和操作
Podman、Podman Desktop 與 Podman Machine
- 待會安裝過程可能會對這三者有點迷糊,可以先知道一點概念、再去實際操作安裝步驟、再回來讀一次,就會比較瞭解這兩者了
- Podman 需要在一個 Linux 作業系統裡執行;雖然確實可以只在 WSL2 VM 裡裝 Podman,但那樣的話在 Windows 作業系統這邊就沒辦法用了。
- Podman Desktop 就是為了能在 Windows 作業系統這邊執行而設計的工具,而且還有 GUI、方便檢視和操作
- Podman Desktop 的實現方式是透過 WSL2 建立一個專屬的 Linux VM 給 Podman 用、也就是 Podman machine
- 所以 Podman Desktop、Podman machine、Podman 是三個不同的服務,Podman 依賴 Podman machine、Podman Desktop 則用於管理 Podman machine 與其裡面的 Podman
- 如果沒有設好一連串的自動啟動,想要用 Podman 時要記得先啟動 Podman machine、才能用 Podman。
- 如果 Podman 沒開、就先開 Podman Desktop,會發現[Containers]等頁籤畫面都顯示「No Container Engine」,就是指你還沒開 Podman machine。
- 進階情境下甚至可以在一個 Windows 的 WSL2 裡有多個 Podman machine
- 不過預設設定是登入 Windows 就會自動啟動 Podman Desktop、啟動 Podman Desktop 就會自動啟動安裝時一併裝好的 Podman machine,就不會遇到這些問題了。
步驟
啟用 WSL
- 確保已開啟虛擬化:工作管理員 >[效能]頁籤 >[CPU]頁籤 > 右下角「模擬」顯示「已啟用」
- 如果沒啟用怎麼辦?似乎是要進 BIOS 改設定……我沒碰到,就暫不深入研究了。
- 安裝 WSL:在 CLI 執行
wsl --install,下載與安裝、看到提示後重新啟動電腦 - 重啟後安裝 Ubuntu
- 「Ubuntu」是 WSL 預設安裝的 Linux distribution
- 應是會自動安裝 Ubuntu、跳出 Terminal 視窗提示創建使用者帳號
- 可能由於某些因素沒有自動安裝……
- 先執行
wsl -l -v確認 WSL 已正常安裝(應會跳出Windows 子系統 Linux 版 沒有已安裝的發佈。) - 執行
wsl --install -d Ubuntu
- 先執行
- 創建使用者帳號
- 提示訊息像是
Create a default Unix user account:,依序輸入要設的使用者名稱與密碼 - 打密碼的時候畫面上完全不會有任何反應、係屬正常現象,Linux 都是這樣設計的、請安心繼續打字 XD
- 這個使用者不是 root,不過系統會自動把這個使用者加入 sudo group、未來可以打
sudo輸入這個使用者的密碼、暫時取得 root 權限做操作
- 提示訊息像是
- 退出 WSL、回到原本的 shell:
exit - 列出正在運行的 WSL VM:
wsl -l -v - 關掉 WSL:
wsl --shutdown- 閒置時還是會佔資源,如果在意可以手動關掉
安裝 Podman Desktop 與 Podman
- 到 官網 下載安裝檔
- 執行安裝檔、選一下要僅安裝給此使用者還是所有使用者……然後就可以點[完成]了 OuO
- 進入 Get started 引導——「Choose the extensions to include」有三個選項、選擇要安裝的部分
- Podman:本體、包含 CLI 和 Podman machine,當然要勾選
- kubectl CLI:Kubernetes 的控制工具,我大概暫時還用不到、先略過,反正按照提示說明、以後都可以再啟用
- Compose:多容器管理工具,開發 web app 會常用、這次順便裝起來
- 選好 extensions 後回到主畫面,跟著引導依序安裝 Podman 和 Compose
安裝 Podman
- 顯示「We could not find Podman. Let’s install it!」,就順著引導去安裝
- 要選擇「Virtualization Provider for the Podman machine」,在這裡我就選擇剛裝好的「WSL v2」
- 「Autostart Podman engine when launching Podman Desktop」:我就選擇 Enabled
- 這是 CLI
創建 Podman machine
- 顯示「We could not find any Podman machine. Let’s create one!」,順著引導按右下角的[Next]
- 「Create a Podman machine」頁面,有一些選項可選,可以都保持預設就好、繼續[Create]
- 一般情況下 Machine with root priviledges 可以關閉,這就是之前提到 Podman 可以在無 root 權限執行的優勢
- 這是一個 VM,如果之前 Virtualization Provider 選擇「WSL v2」,就是 WSL 裡面的一個 Linux instance,名稱就是自己設定的 Name
- 在檔案總管左下方[Linux]頁籤,可以看到目前所有的 Linux instance、有稍早安裝的 Ubuntu 和剛剛創建的 Podman machine……原來兩者其實是獨立不相干的 😅
podman machine開頭的 CLI 指令就是針對這台 Podman machine,podman開頭的指令才是 Podman CLI
安裝 Compose
- 第一頁有個 Note 提示:
If you would like to use docker compose up or docker-compose with Podman, enable Docker Compatibility.,先記在腦袋裡、下一步會去處理它。 - 接著就一路[Next]到底
根據個人偏好改一些設定……
偏好設定都在左下角[Settings]> 左方[Preference]頁籤
- Appearance > Zoom Level:介面縮放,從 0 調到 1,眼睛舒服多了 😆
- Docker Compatibility > Enabled:啟用後在 CLI 打
docker會自動導向使用podman,就像設 alias 的概念- 如果這台電腦上只有裝 Podman、沒裝 Docker,那就啟用它吧、打錯沒煩惱 XD
- 前一步說記在腦袋裡的提示就是這個
- Start on login > Start:登入 Windows 時是否自動啟動 Podman Desktop 、並接著自動啟動 Podman Machine
- 如果沒開,開機後直接在 CLI 打
podman指令是無效的;要自己先啟動 Podman Desktop 或執行podman machine start後才能用。
- 如果沒開,開機後直接在 CLI 打
嘗試執行第一個 container:nginx
- 先準備一個目錄的靜態網頁檔案、並
cd到該目錄,待會用來透過 nginx serve - 創建並啟動 container:
runTerminal window podman run -d `--name test-nginx `-p 3001:80 `-v "${PWD}:/usr/share/nginx/html:ro" `nginx:1.29.7-alpine-d:detached,背景執行、不佔用 terminal-p 3001:80:port 映射(mapping),冒號前面是本機、冒號後面是容器內,意思是把傳遞給本機3001port 的 request 轉發進容器裡的80port、也就是 nginx 在監聽的 port- 本機 port 可以隨自己喜好挑、只要不要和其他正在執行的服務衝突就好
-v "${PWD}:/usr/share/nginx/html:ro":掛載 volume,值以冒號分隔- 第一個欄位:volume 資料位置,有兩種模式:
- Bind Mount:寫本機的絕對路徑,檔案就存放在本機的這個位置
${PWD}是目前目錄的變數;變數只能在雙引號內使用,若在單引號內、變數不會解析出來。- 順帶一提,
${PWD}是 Powershell 的語法,cmd 和 bash 會有所不同。
- Named Volume:寫名稱,由 Podman 管理,相同的名稱就指向相同的 volume
- Bind Mount:寫本機的絕對路徑,檔案就存放在本機的這個位置
- 第二個欄位是 container 內的位置,表示把本機於第一個欄位填寫的位置綁定到 container 裡的這裡
- 第三個欄位非必填,
ro表示 Read-Only、在這個 nginx 的使用情境適合加上。
- 第一個欄位:volume 資料位置,有兩種模式:
nginx:1.29.7-alpine:指定用哪個 image 創建這個 container;這裡輸入的 tag 可以去 Docker Hub 上面找,熱門工具幾乎都有官方出的 image- 以
nginx舉例,tag 裡還有好幾個後綴,舉兩個現階段用得到的說明一下:- (無後綴的普通版):通常基於 Debian、常見的 Linux distribution,有基礎的預裝 bash 工具如
grep。 alpine:基於 Alpine、是另一個 Linux distribution,主打安全、輕量級和極簡,不過相較於普通版,可能不支援一些開發時常用的額外功能,且由於缺少某些 C 語言擴充套件、某些使用情境會有相容性問題;一般推薦開發時用普通版、到生產環境且不會撞到相容性問題再用此版本。
- (無後綴的普通版):通常基於 Debian、常見的 Linux distribution,有基礎的預裝 bash 工具如
- 以
- 執行
podman ps看這個test-nginxcontainer 是否正在執行,如果是、開瀏覽器去localhost:3001應該就看得到網頁了podman ps -a才能看到所有 container、包含目前非執行中的- 是否正在執行要看
STATUS欄位,正在執行會顯示Up <啟動至今過了多久>、非執行中會顯示Exited <多久前停止>
- 啟動和停止 container:
podman start test-nginx/podman stop test-nginx- 未來就不用再執行
run了,只有創建 container 時才會用到,且run時設定的 port 等資訊都已經寫死在裡面了。
- 未來就不用再執行
後記閒聊
我在寫文章時會刁鑽一些用字遣詞(?),比如該用「占用」還是「佔用」;這次遇到一個大問題是該用「nginx(全小寫)」、「NGINX(全大寫)」還是「Nginx(首字母大寫)」?
- nginx 官網 上是全小寫、且不因在句首或標題而首字母轉大寫
- 但在公司和產品方面,F5 公司的產品介紹 是全大寫;IThome 的相關新聞 也是用全大寫
- 維基百科 是固定首字母大寫,不過右邊資訊卡上又是全大寫?
- 多篇網路上的技術部落格分享是固定首字母大寫,如 古古的後端筆記
- 發現了這則不太確定來源的論壇回文:How exactly is NGINX spelled?,看起來回文者的 Email 是屬於
nginx.org網域、代表是內部人員;不過這是 2012 年的回文了、2019 年 F5 收購 NGINX, Inc.。
最後我的決定是指軟體工具時用「nginx(全小寫)」,品牌商標之類的情境再用「NGINX(全大寫)」——不過可能沒什麼機會用到就是了。
順帶一提,唸法是「Engine X」,這點就沒爭議了。