Skip to main content

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 ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

nerdctl 指令官方說明是 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 port
lima nerdctl run -d -p 8080:80 nginx:alpine

# 測試是否可從 localhost 存取到 Nginx
curl 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 檔啟動虛擬機,並取名為 docker
limactl 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-compose
sudo 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 檔案無法寫入

這是預設配置,主要是安全性考量。

如果想調整的話,修改 ~/.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 default
limactl start default

Makefile 不吃 alias

參考 Stackoverflow,因此不能使用,直接一點的做法是寫個 script:

#!/usr/bin/env bash
# file: docker
limactl shell docker docker $@
#!/usr/bin/env bash
# file: docker-compose
limactl shell docker docker-compose $@

然後把這個檔案放在 /path/to/your/bin,然後在啟動 shell 的時候加入 PATH 環境變數即可:

# ~/.bash_profile
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 version

Lima VM 出現 Broken 的狀態

出現的原因目前不明,在這個狀態下,使用 limactl ls 的範例如下:

$ limactl ls
WARN[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 DIR
docker 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 qemu
67116 ttys000 2:19.15 /usr/local/bin/qemu-system-x86_64 ...

終止程序(kill -9)後,它的狀態就會變 Stopped:

$ limactl ls
NAME STATUS SSH ARCH DIR
docker Stopped 127.0.0.1:60006 x86_64 /Users/miles/.lima/docker

重新 start 後就沒有出現錯誤訊息了:

$ limactl ls
NAME STATUS SSH ARCH DIR
docker Running 127.0.0.1:60006 x86_64 /Users/miles/.lima/docker

Lima Mount sshfs 出現錯誤訊息

在啟動 VM 的時候,看到錯誤訊息如下:

INFO[0034] [hostagent] Mounting "/Users/miles"
INFO[0034] [hostagent] fuse: mountpoint is not empty
INFO[0034] [hostagent] fuse: if you are sure this is safe, use the 'nonempty' mount option
INFO[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 docker
limactl rm docker