Lima
Lima 是一個 MacOS 上的 Docker Desktop 開源解決方案。
使用 Homebrew 安裝:
brew install lima接著使用 limactl 指令啟動預配置好的 Linux 虛擬機:
$ limactl start? Creating an instance "default" [Use arrows to move, type to filter]> Proceed with the default configuration Open an editor to override the configuration Exit這裡會詢問是否要調整設定,可以直接使用預設配置懶人包即可。接著 lima 會下載虛擬機的映像檔並啟動,會花點時間,等完成後,即可使用 lima 指令對虛擬機操作。
lima 指令是別名,它等同於 limactl shell default。預設的懶人包是使用 containerd + nerdctl
來管理容器,指令是使用 nerdctl,完整的指令如下:
$ lima nerdctl psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESnerdctl 指令官方說明是 Docker-compatible CLI,包括 Docker Compose 也有實作,理想上,可以設定下面這兩個別名:
alias docker="lima nerdctl"alias docker-compose="lima nerdctl compose"以下為了區分與 Docker 指令的不同,會採用原始指令。
來啟動 Hello world container 和起 Nginx 服務試試:
# Hello World,可以看到下載的進度表完全不一樣,這是 nerdctl 的介面lima nerdctl run --rm -it hello-world
# 啟動 Nginx 服務並開 8080 portlima nerdctl run -d -p 8080:80 nginx:alpine
# 測試是否可從 localhost 存取到 Nginxcurl http://localhost:8080官方有提供幾個預設設定範例檔可以直接套用,包含 Linux 發行版和 container engine 都可以更換。
目前使用經驗上,nerdctl 在 Docker Compose 的相容度還是有待改善,因此直接使用 Docker 作為 container engine 踩的雷會比較少一點:
# 下載官方的範例檔curl -o docker.yaml https://raw.githubusercontent.com/lima-vm/lima/master/examples/docker.yaml
# 依 yaml 檔啟動虛擬機,並取名為 dockerlimactl start docker.yaml預設虛擬機已裝好 Docker,但沒有裝 Docker Compose,參考官方文件,使用下面指令安裝:
注意:官方提供的 artifacts 環境與版本,如果沒有找到的話會下載失敗,這時就會需要自行 compile。
# 進入虛擬機limactl shell docker
# 執行安裝指令sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose# Version 2.0# sudo curl -L "https://github.com/docker/compose/releases/download/v2.0.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-composesudo chmod +x /usr/local/bin/docker-compose上面有提到,因為 lima = limactl shell default,因此它會使用 default 這個虛擬機,但上面建立好的會叫 docker,如果有需要用別名的話,要改成下面這樣:
alias docker="limactl shell docker docker"alias docker-compose="limactl shell docker docker-compose"Mount host 檔案無法寫入
Section titled “Mount host 檔案無法寫入”這是預設配置,主要是安全性考量。
如果想調整的話,修改 ~/.lima/default/lima.yaml 設定如下:
mounts: - location: "~" # CAUTION: `writable` SHOULD be false for the home directory. # Setting `writable` to true is possible, but untested and dangerous. writable: true - location: "/tmp/lima" writable: true這裡是設定本機的哪些目錄可以寫入。把想要寫入的目錄設定好後,重新啟動 Linux VM 即可:
limactl stop defaultlimactl start defaultMakefile 不吃 alias
Section titled “Makefile 不吃 alias”參考 Stackoverflow,因此不能使用,直接一點的做法是寫個 script:
#!/usr/bin/env bash# file: dockerlimactl shell docker docker $@#!/usr/bin/env bash# file: docker-composelimactl shell docker docker-compose $@然後把這個檔案放在 /path/to/your/bin,然後在啟動 shell 的時候加入 PATH 環境變數即可:
PATH=/path/to/your/bin:$PATH最後用 which 指令或 version 的子指令,確認有接到正確的指令即可:
# 查詢指令位置$ witch docker/path/to/your/bin/docker$ witch docker-compose/path/to/your/bin/docker-compose
# 直接查看版本$ docker version$ docker-compose versionLima VM 出現 Broken 的狀態
Section titled “Lima VM 出現 Broken 的狀態”出現的原因目前不明,在這個狀態下,使用 limactl ls 的範例如下:
$ limactl lsWARN[0000] instance "docker" has errors errors="[failed to connect to \"/Users/miles/.lima/docker/ha.sock\": stat /Users/miles/.lima/docker/ha.sock: no such file or directory]"NAME STATUS SSH ARCH DIRdocker Broken 127.0.0.1:60006 x86_64 /Users/miles/.lima/docker從 log 來看,
ha.sock應該是指的是hostagent,類似地,ga.sock指的是guestagent
以筆者遇到的狀況來說,會看到裡面有提到 ha.sock 找不到,但是 limacrl shell 卻又能正常進入 VM 執行 Docker 指令,甚至 Container 都能互相連結,這表示 VM 運作正常,但與 Host 的連結出現了問題。筆者在這個狀態下還有發現另一個現象是,port forwarding 運作有問題。
後來使用 limactl 都無法正常對 VM 做任何操作,最後只能使用 htop 或 ps 找到 QEMU 執行緒:
$ ps -aA | grep qemu67116 ttys000 2:19.15 /usr/local/bin/qemu-system-x86_64 ...終止程序(kill -9)後,它的狀態就會變 Stopped:
$ limactl lsNAME STATUS SSH ARCH DIRdocker Stopped 127.0.0.1:60006 x86_64 /Users/miles/.lima/docker重新 start 後就沒有出現錯誤訊息了:
$ limactl lsNAME STATUS SSH ARCH DIRdocker Running 127.0.0.1:60006 x86_64 /Users/miles/.lima/dockerLima Mount sshfs 出現錯誤訊息
Section titled “Lima Mount sshfs 出現錯誤訊息”在啟動 VM 的時候,看到錯誤訊息如下:
INFO[0034] [hostagent] Mounting "/Users/miles"INFO[0034] [hostagent] fuse: mountpoint is not emptyINFO[0034] [hostagent] fuse: if you are sure this is safe, use the 'nonempty' mount optionINFO[0066] [hostagent] time="2021-10-19T16:40:55+08:00" level=warning msg="failed to confirm whether /Users/miles [remote] is successfully mounted" error="failed to execute script \"wait-for-remote-ready\": stdout=\"\", stderr=\"sshfs does not seem to be mounted on /Users/miles\\n\": exit status 1"影響是啟動完 VM 後,裡面會沒有 host 的任何檔案,這會無法 Docker build 或 volume mount 等。
這個問題重啟也無效,最後只能砍掉重練解決:
limactl stop dockerlimactl rm docker