lima linux installation

(本文适用于 macOS, ChatGPT 为共同作者)

lima https://github.com/lima-vm/lima 是一个轻量级虚拟化解决方案,允许在 macOS 上原生运行 Linux 虚拟机.它使用 macOS 的 Virtualization.framework(vz) 或 QEMU 来实现虚拟化,适用于开发,测试,容器运行等场景

具体请看官方 README

用 lima 的理由是它足够轻量

Table of Contents

Install lima

这里使用 Homebrew 安装:

brew install lima

lima 会创建一个 ~/.lima 目录

Deploy Linux (Ubuntu)

这里我们以 vz 驱动 (macOS Virtualization.framework)举例, lima 默认就是 vz, vz 具体内容请看后文

在安装好 lima 后,我们开始部署 Ubuntu server:

(直接 start 就行,确认提示后它会自动拉取镜像)

limactl start --name=my_ubuntu template://ubuntu

这时你应该会看到一个提示,确认无误后回车

limactl start ... 执行完后,你的 ~/.lima 目录树状结构应该会变成这样:

.
├── _config/                         # 全局配置 (有时会出现)
└── my_ubuntu/                       # 你的虚拟机目录
    ├── arch                         # 架构信息 (例如 x86_64, aarch64)
    ├── console.log                  # 虚拟机的控制台输出日志
    ├── lima.yaml                    # 启动时使用的配置文件(合并后的)
    ├── user-data                    # cloud-init 的 user-data (初始化脚本)
    ├── network.yaml                 # 网络配置(可能存在)
    ├── serial.sock                  # 串口通信的 Unix socket
    ├── ssh.config                   # SSH 配置 (可以直接 SSH 连接)
    ├── ssh.sock                     # SSH 代理 socket
    ├── vm.sock                      # lima 的控制 socket
    ├── diffdisk/                    # VZ 后端时的挂载目录,包含映射的文件系统变更
    └── mounts/                      # 你挂载的 host 目录的映射配置和 socket

然后进入已启动的虚拟机:

limactl shell my_ubuntu

pwd, ls 一下,可以发现 lima 直接将本机的 home 目录挂载到虚拟机的 /Users 目录下了

⚠️ 它只是 只读 home 目录,不能改动

Update the virtual machine

若想更新镜像,可执行 limactl prune 清除缓存,或更改 lima.yaml 的镜像地址(lima.yaml 配置文件具体请看后文)

cloud-init

lima 使用 cloud-init 来初始化虚拟机,包括设置用户名,SSH 密钥,网络配置等.你在 lima.yaml 文件中指定的初始化配置最终会被生成成一个 ISO 文件 cidata.iso,由虚拟机挂载并自动读取

Change the virtual machine directory

如果想让虚拟机里面是一个“独立”的 Linux 文件系统,不挂载任何宿主目录,我们可以更改虚拟机的配置文件

更改之前先停止虚拟机:

limactl stop my_ubuntu

(在这里如果遇到: ERRO[0000] [hostagent] dhcp: unhandled message type: RELEASE 报错,无需担心,具体请看后文)

然后更改 ~/.lima/my_ubuntu/lima.yaml 文件

未更改的 lima.yaml 应该是这样的:

minimumLimaVersion: 1.1.0
images:
# Try to use release-yyyyMMdd image if available. Note that release-yyyyMMdd will be removed after several months.

- location: "https://cloud-images.ubuntu.com/releases/plucky/release-20250701/ubuntu-25.04-server-cloudimg-amd64.img"
  arch: "x86_64"
  digest: "sha256:92ad8714338b1d3be605b7981137a7c356b23527ff1aba8e80cf44bc3aa2f8da"
- location: "https://cloud-images.ubuntu.com/releases/plucky/release-20250701/ubuntu-25.04-server-cloudimg-arm64.img"
  arch: "aarch64"
  digest: "sha256:26d0ac2236f12954923eb35ddfee8fa9fff3eab6111ba84786b98ab3b972c6d8"
- location: "https://cloud-images.ubuntu.com/releases/plucky/release-20250701/ubuntu-25.04-server-cloudimg-riscv64.img"
  arch: "riscv64"
  digest: "sha256:66f420cb992e3076207ce933b7f96550d27b05ead561b7a5e48d281d01b151de"
- location: "https://cloud-images.ubuntu.com/releases/plucky/release-20250701/ubuntu-25.04-server-cloudimg-armhf.img"
  arch: "armv7l"
  digest: "sha256:f37d82f55df80bdb09bbeb403f84e6921b8e4435610fed22ffec436af2e4dd6d"
- location: "https://cloud-images.ubuntu.com/releases/plucky/release-20250701/ubuntu-25.04-server-cloudimg-s390x.img"
  arch: "s390x"
  digest: "sha256:1d03fedf3aea85438ce70d745edf611b80c6f88a049bb44167c24ae2ec9d4fda"
- location: "https://cloud-images.ubuntu.com/releases/plucky/release-20250701/ubuntu-25.04-server-cloudimg-ppc64el.img"
  arch: "ppc64le"
  digest: "sha256:5922f8ea7958f15af5a5d8a4efec38d66af31c0a853fba5fb0790ec25562b53a"
# Fallback to the latest release image.
# Hint: run `limactl prune` to invalidate the cache

- location: https://cloud-images.ubuntu.com/releases/plucky/release/ubuntu-25.04-server-cloudimg-amd64.img
  arch: x86_64

- location: https://cloud-images.ubuntu.com/releases/plucky/release/ubuntu-25.04-server-cloudimg-arm64.img
  arch: aarch64

- location: https://cloud-images.ubuntu.com/releases/plucky/release/ubuntu-25.04-server-cloudimg-riscv64.img
  arch: riscv64

- location: https://cloud-images.ubuntu.com/releases/plucky/release/ubuntu-25.04-server-cloudimg-armhf.img
  arch: armv7l

- location: https://cloud-images.ubuntu.com/releases/plucky/release/ubuntu-25.04-server-cloudimg-s390x.img
  arch: s390x

- location: https://cloud-images.ubuntu.com/releases/plucky/release/ubuntu-25.04-server-cloudimg-ppc64el.img
  arch: ppc64le

mounts:

- location: "~"

- location: "/lima"
  mountPoint: /tmp/lima
  writable: true
# # NOTE: Intel Mac with macOS prior to 15.5 requires setting vmType to qemu
# # https://github.com/lima-vm/lima/issues/3334
# vmType: qemu

我们只需要将 - location: "~" 注释掉就好了

如果你想要将宿主机的其他目录到虚拟机中,更改 - location: "~" 其中指定的路径即可

lima 还支持 sshfs 和 9p 方式的文件共享,具体配置可以看官方文档

mounts: 下还有一段配置:

- location: "/lima"
  mountPoint: /tmp/lima
  writable: true

该挂载是 lima 默认模板中的临时目录,主要用于 cloud-init 与 containerd 等组件的通信或初始化配置

详细一点来说,这是挂载你宿主机的一个临时目录 (一般在 /tmp/var/folders/...) 到 lima 虚拟机内部的 /tmp/lima,用于 lima 运行时内部通信 (比如提供初始配置数据),不是用户日常使用的共享目录

通常:

如果你只是想运行一个独立的 Ubuntu 虚拟机 (无 nerdctl,无 cloud-init),你可以注释掉这段,通常能正常启动, lima 不强制要求这一段

但是注意:

⚠️ 如果你看到报错类似:

那就说明你不能注释掉这段,得恢复它

修改完配置文件后我们再重新启动虚拟机:

limactl start my_ubuntu

此时, ~/.lima 目录的结构大致如下:

.
├── _config
│   ├── networks.yaml
│   ├── user
│   └── user.pub
└── my_ubuntu
    ├── basedisk
    ├── cidata.iso
    ├── cloud-config.yaml
    ├── default_ep.sock
    ├── default_fd.sock
    ├── diffdisk
    ├── ha.sock
    ├── ha.stderr.log
    ├── ha.stdout.log
    ├── lima-version
    ├── lima.yaml
    ├── serialv.log
    ├── ssh.config
    ├── vz-efi
    └── vz-identifier

虚拟机 my_ubuntu 目录下的东西,具体解释为:

文件/目录名 说明
basedisk / diffdisk 用于 overlay 的磁盘镜像数据 (vz 驱动下管理虚拟机存储的方式)
cidata.iso cloud-init 配置生成的 ISO,用于初始设置用户名,密码, SSH 密钥等
cloud-config.yaml cloud-init 的原始配置
ha.sock, ha.stdout.log hostagent 的 socket 与日志
serialv.log 虚拟串口输出日志(类似串口终端)
ssh.config lima 自动生成的 SSH 配置(你可以 ssh -F ~/.ssh/config lima-my_ubuntu 用它登录)
vz-* 开头的文件 vz 驱动的标识信息,如 EFI 引导,标识符等
lima.yaml 你的虚拟机配置文件

但这时我们发现没有 disk.qcow2, alpine.img, ubuntu.img 这样的文件 (QEMU 驱动下,会产生的虚拟机的硬盘镜像)

这是因为你使用的是 vz 驱动 (macOS Virtualization.framework),不是 QEMU 驱动

Virtual machine hard disk location

(lima) 在 vz 模式下,虚拟磁盘不以 .img.qcow2 的形式暴露出来,而是拆分为内部结构如下:

文件/目录名 作用
basedisk 系统镜像的基础层,通常是只读的 (比如 Ubuntu)
diffdisk 你的所有更改都在这里,包括安装的软件,下载的文件,创建的目录等
cidata.iso cloud-init 设置,比如你的 SSH key,用户名等
vz-efi, vz-identifier EFI 引导信息和虚拟机标识,用于启动

也就是说,你的个人文件,安装软件的数据都存在 diffdisk

vz

vz 是 lima 的一种虚拟机驱动,在 macOS 上专门用来创建轻量虚拟机,背后依赖的是 macOS 的虚拟化框架

vz 相比于 QEMU,它的性能更加好,硬件加速更好 (因为 vz 原生支持 macOS),但 vz 的限制也多一些 (e.g. 网络, USB),而 QEMU 更灵活,硬件模拟能力强

如果你在启动时看到类似:

INFO[0005] Starting the instance "my_ubuntu" with VM driver "vz"

就说明你用的是 vz 驱动.默认配置模板 template://ubuntu 就会启用 vz(除非你手动设定为 QEMU)

如果你想你可以这样启动:

limactl start --name=qemu_vm --set vmType=qemu template://ubuntu

这样 lima 会用 QEMU 启动 VM,并下载 .qcow2 镜像到 ~/.lima/qemu_vm

Using ISO files

如果你有 Ubuntu 的 .iso 镜像,你也可以用 ISO 镜像启动 lima 虚拟机

但是我们不推荐你使用自己下载的 ISO 镜像启动 lima 虚拟机:

问题 原因
❌ 不支持自动安装 ISO 不是 cloud image, lima 的 cloud-init 配置没用
❌ 没有 SSH ISO 安装前没有 SSH 服务, lima 的自动 SSH 登录失效
❌ 手动安装麻烦 每次重启还得选择安装,或你要自己创建持久磁盘、引导配置
✅ Cloud Image 优点 启动快、有 cloud-init、自带 SSH、公钥登录、最适合 lima

如果你要用 ISO 镜像启动 lima 虚拟机的话,请在 lima.yaml 中指定这个 ISO:

(假设你的 ISO 在 /Users/yourname/Downloads/ubuntu.iso)

arch: "aarch64"  # 或 "x86_64",看你的 ISO 是哪种架构
images:
  - location: "/Users/yourname/Downloads/ubuntu.iso"
    arch: "aarch64"
    digest: ""  # 不验证 sha256

但这样只是挂载 ISO 镜像为光驱启动,它不会自动安装,系统启动后会进入 Ubuntu 安装器界面 (就像你在实体机装系统一样),你必须一步步安装

Linux desktop

虽然我们使用 lima 就是为了轻量快速,但 lima 也可以启动 Ubuntu desktop

如果你想用 lima 启动 Ubuntu desktop 你要先安装 lima 的 Ubuntu desktop 版本的虚拟机

然后在你的 Ubuntu desktop 版本的虚拟机中的 lima.yaml 文件的最上面写入:

vmType: "vz"
gui: true

当然你也可以用一个 server 版本的 Ubuntu 在修改配置文件后再 sudo apt install ubuntu-desktop,安装一个图形化桌面

若你启动的是 ISO 镜像且想修改引导方式,可在启动时快速按 EscF2 进入 UEFI 界面

如果你是用 ISO 镜像来启动 Ubuntu desktop, 同理

Report an error

⚠️ 非致命警告

这是 DHCP 发来的释放 (RELEASE)类型消息, hostagent 没有处理它

这类信息常见于虚拟网络接口关闭时,对 lima 的实际运行没有影响,可以忽略

View Architecture

查看我们的 lima 虚拟机架构,可以先运行虚拟机,然后进入虚拟机,使用:

uname -m

看输出就知道了

Unix domain socket

“共享套接字” 是指将一个 Unix 域套接字 (Unix domain socket) 挂载 (bind-mount) 到 lima 虚拟机中,使得虚拟机内的程序可以通过这个套接字访问宿主机的服务,反之亦然

它本质上是通过文件系统中的套接字路径完成跨虚拟机与宿主机进程之间通信的桥梁

举个例子: Docker 的共享套接字

containerd:
  system: false
  user: false

这意味着 lima 不会内置启动 containerd,它就需要通过共享套接字连接宿主机 Docker (或者你手动启用的 containerd)

你就会在 YAML 里看到 lima 把宿主机的 Docker 套接字映射进 VM 里:

mounts:
  - location: "/var/run/docker.sock"
    writable: false

在虚拟机里,这个文件就像在宿主机上一样存在,运行容器工具就能用它来控制 Docker 了

反过来也可以: lima VM 内暴露套接字给宿主机

比如你在 lima 里跑了个 containerd,想让 host macOS 使用它,也可以这么挂:

mounts:
  - location: "/Users/yourname/.lima/sockets/containerd.sock"
    mountPoint: "/run/containerd.sock"
    writable: true

若你在 lima 虚拟机中使用 nerdctl,并希望控制宿主机的 Docker,可映射:

mounts:
  - location: "/var/run/docker.sock"
    mountPoint: "/var/run/docker.sock"
    writable: false

然后在 VM 中使用:

nerdctl ps

为什么用套接字,而不是 TCP?