Lima 中的 Podman 使用指南:Rootless 与 Rootful 两种模式完整上手
【免费下载链接】limaLinux virtual machines, with a focus on running containers项目地址: https://gitcode.com/GitHub_Trending/lim/lima
导读
本文基于 Lima 官方示例文档(website/content/en/docs/examples/containers/podman/_index.md)展开,讲解如何在 Lima 创建的 Linux 虚拟机中运行 Podman 容器引擎,并覆盖Rootless(无根)与Rootful(有根)两种部署模式的启动、配置与日常使用。读完本文,你将掌握:通过limactl start template:podman一键拉起 Podman 虚拟机、在 VM 内与宿主机上两种方式执行podman命令、用CONTAINER_HOST/DOCKER_HOST环境变量让宿主机直接管理 VM 内的容器,以及两个官方模板底层的 provisioning 脚本与 socket 端口转发原理。
Lima 的设计初衷就是"在虚拟机中运行容器",并自动提供文件系统共享与端口转发能力。虽然 Lima 最早是为 macOS 用户推广 containerd 而生的,但当前版本同样支持其他容器引擎,且不依赖 macOS 宿主机(参见 containers 目录索引)。Podman 模板正是"用 Podman 替代 containerd 与 nerdctl"的官方方案。
一、两种模式总览:Rootless 与 Rootful
官方文档将 Podman 的使用分为两个标签页,分别对应两个内置模板:
| 模式 | 模板名称 | 特点 | 典型命令 |
|---|---|---|---|
| Rootless | template:podman | 以普通用户身份运行容器,Podman socket 位于用户目录下 | limactl start template:podman |
| Rootful | template:podman-rootful | 以 root 身份运行容器,Podman socket 位于系统目录/run/podman | limactl start template:podman-rootful |
两个模板的完整源码分别位于 templates/podman.yaml 与 templates/podman-rootful.yaml,二者均声明minimumLimaVersion: 2.0.0,即要求 Lima 2.0.0 及以上版本才能解析。
无论哪种模式,都支持三种使用路径:
- 在 VM 内部直接执行
podman命令; - 在宿主机上通过
CONTAINER_HOST环境变量 +podman --remote连接 VM; - 在宿主机上通过
DOCKER_HOST环境变量让dockerCLI 直接操作 VM 内的 Podman 守护进程(兼容 Docker CLI 习惯)。
下面依次给出两种模式的完整命令。
二、Rootless 模式完整操作
Rootless 模式是最常用的默认方案,容器以非 root 用户身份运行,安全性更好。
2.1 启动实例
limactl start template:podmantemplate:podman会创建一个名为podman的 Lima 实例。若想自定义实例名,可改为:
limactl start template:podman --name my-podman2.2 在 VM 内使用 podman
limactl shell podman podman run -d --name nginx -p 127.0.0.1:8080:80 docker.io/library/nginx:alpinelimactl shell会在 VM 内执行后续命令,随后即可通过宿主机访问http://127.0.0.1:8080,这是因为 Lima 默认把实例的全部回环端口自动转发到宿主机(见 pkg/portfwd 的实现)。
2.3 在宿主机上使用 podman(需 podman-remote)
export CONTAINER_HOST=$(limactl list podman --format 'unix://{{.Dir}}/sock/podman.sock') podman --remote run -d --name nginx -p 127.0.0.1:8080:80 docker.io/library/nginx:alpine这里的核心机制是:limactl list --format支持 Go 模板输出(见 cmd/limactl/list.go),{{.Dir}}是实例目录(通常为$LIMA_HOME/podman),而sock/podman.sock正是模板portForwards中定义的宿主机侧 socket 路径。CONTAINER_HOST指向该 socket 后,podman --remote就会把请求转发进 VM。
2.4 在宿主机上使用 docker CLI(需 docker-cli)
export DOCKER_HOST=$(limactl list podman --format 'unix://{{.Dir}}/sock/podman.sock') docker run -d --name nginx -p 127.0.0.1:8080:80 docker.io/library/nginx:alpine由于 Podman 的 API 与 Docker API 兼容,设置DOCKER_HOST后,宿主机上已安装的docker命令可以直接管理 VM 内的容器,无需在 VM 内再装 Docker。
三、Rootful 模式完整操作
Rootful 模式以 root 身份运行容器,适用于需要特权能力(如修改网络配置、使用 iptables 等)的场景。
3.1 启动实例
limactl start template:podman-rootful实例名为podman-rootful。
3.2 在 VM 内使用 podman
注意命令前需要sudo:
limactl shell podman-rootful sudo podman run -d --name nginx -p 127.0.0.1:8080:80 docker.io/library/nginx:alpine3.3 在宿主机上使用 podman(需 podman-remote)
export CONTAINER_HOST=$(limactl list podman-rootful --format 'unix://{{.Dir}}/sock/podman.sock') podman --remote run -d --name nginx -p 127.0.0.1:8080:80 docker.io/library/nginx:alpine3.4 在宿主机上使用 docker CLI(需 docker-cli)
export DOCKER_HOST=$(limactl list podman-rootful --format 'unix://{{.Dir}}/sock/podman.sock') docker run -d --name nginx -p 127.0.0.1:8080:80 docker.io/library/nginx:alpine四、模板源码拆解:底层到底做了什么
官方文档只给出命令,而命令背后的自动化逻辑全部封装在两个模板中。理解模板有助于排查问题与自定义扩展。
4.1 基础继承:镜像与挂载
两个模板都通过base机制继承两部分配置:
base: - template:_images/fedora - template:_default/mountstemplate:_images/fedora(见 templates/_images/fedora.yaml):提供 Fedora 云镜像(当前为 Fedora 44),覆盖x86_64、aarch64、riscv64三种架构,并带 SHA-256 digest 校验;template:_default/mounts(见 templates/_default/mounts.yaml):把宿主机家目录~只读挂载进 VM。
base模板合并发生在实例创建时(参见 pkg/limayaml/default.yaml 的说明),合并后的完整 lima.yaml 会保存在实例目录中。
4.2 关闭 Lima 自带的 containerd
containerd: system: false user: falseLima 默认会为 Linux 客户机启用用户级(rootless)containerd。本模板明确将其关闭,因为 Podman 接管了容器运行时职责——这与 templates/docker.yaml 中"containerd 由 Docker 管理,故设为 false"的做法一致。
4.3 Provision 脚本:安装 Podman 并启用 socket
Rootless 模板的 provision 部分:
provision: - mode: system script: | #!/bin/bash set -eux -o pipefail command -v podman >/dev/null 2>&1 && test -e /etc/lima-podman && exit 0 dnf -y install --best podman && touch /etc/lima-podman - mode: user script: | #!/bin/bash set -eux -o pipefail systemctl --user enable --now podman.socket要点:
- 第一个
mode: system脚本以 root 权限执行,通过dnf安装podman包;用/etc/lima-podman标记文件保证幂等性(provision 脚本可能被多次执行,如实例重启时,参见 default.yaml 的说明); - 第二个
mode: user脚本以普通用户身份执行,启用用户级 systemd 的podman.socket。
Rootful 模板则不同:
provision: - mode: system script: | #!/bin/bash set -eux -o pipefail command -v podman >/dev/null 2>&1 && test -e /etc/lima-podman && exit 0 if [ ! -e /etc/systemd/system/podman.socket.d/override.conf ]; then mkdir -p /etc/systemd/system/podman.socket.d cat <<-EOF >/etc/systemd/system/podman.socket.d/override.conf [Socket] SocketUser={{.User}} EOF fi if [ ! -e /etc/tmpfiles.d/podman.conf ]; then mkdir -p /etc/tmpfiles.d echo "d /run/podman 0700 {{.User}} -" > /etc/tmpfiles.d/podman.conf fi dnf -y install --best podman && touch /etc/lima-podman - mode: system script: | #!/bin/bash set -eux -o pipefail systemctl --system enable --now podman.socketRootful 模式的差异点:
- 通过
override.conf把podman.socket的SocketUser设为 Lima 用户,使非 root 用户也能访问系统级 socket; - 通过 tmpfiles 规则在
/run/podman(权限 0700)创建 socket 目录; - 第二个脚本启用的是系统级(
--system)的podman.socket,而不是用户级。
4.4 Probes:就绪探针
两个模板都带就绪探针,等待podman命令可用:
probes: - script: | #!/bin/bash set -eux -o pipefail if ! timeout 30s bash -c "until command -v podman >/dev/null 2>&1; do sleep 3; done"; then echo >&2 "podman is not installed yet" exit 1 fi hint: See "/var/log/cloud-init-output.log" in the guest若 30 秒内podman仍未安装成功,实例会判定启动失败,hint指向/var/log/cloud-init-output.log以便排查。
4.5 端口转发:把 guest socket 暴露给宿主机
这是"宿主机直接使用 podman/docker"的关键。Rootless 模板:
portForwards: - guestSocket: "/run/user/{{.UID}}/podman/podman.sock" hostSocket: "{{.Dir}}/sock/podman.sock"Rootful 模板:
portForwards: - guestSocket: "/run/podman/podman.sock" hostSocket: "{{.Dir}}/sock/podman.sock"guestSocket:VM 内的 Podman 守护 socket 路径(rootless 在用户运行时目录,rootful 在/run/podman);hostSocket:宿主机上的 socket 路径,{{.Dir}}为实例目录,统一放在sock/子目录下,避免与 Lima 内部 socket 冲突(此约定同样见 default.yaml 的注释)。
Lima 的端口转发器会在宿主机上创建对应的 Unix socket 监听器,并把连接转发到 guest socket(相关实现见 pkg/portfwd/listener.go 与prepareUnixSocket)。这正是文档中CONTAINER_HOST=unix://{{.Dir}}/sock/podman.sock能生效的底层原因。
4.6 启动提示消息
模板末尾的message字段会在实例启动成功后显示一条快捷提示,内容同样适用于手动配置podman --remote:
podman system connection add lima-{{.Name}} "unix://{{.Dir}}/sock/podman.sock" podman system connection default lima-{{.Name}} podman{{if eq .HostOS "linux"}} --remote{{end}} run quay.io/podman/hello即除了用环境变量CONTAINER_HOST,也可以借助podman system connection把该 socket 注册为持久化的连接lima-<实例名>,之后免去每次导出环境变量的麻烦。
五、常见使用场景与组合命令
5.1 挂载家目录并运行交互容器
模板继承的mounts会把宿主机家目录只读挂载进 VM,因此可以直接在容器内访问宿主机文件:
limactl shell podman podman run -it -v $HOME:$HOME --rm docker.io/library/alpine这也是模板头部注释给出的示例(见 templates/podman.yaml)。注意模板把家目录挂载为只读(见 mounts.yaml),如需可写请通过$LIMA_HOME/_config/override.yaml或修改实例 lima.yaml 中的mounts[].writable。
5.2 同时管理多个 Podman 实例
由于每个实例的 socket 路径以{{.Dir}}(实例目录)区分,可以同时启动多个实例并分别导出不同的CONTAINER_HOST/DOCKER_HOST:
export CONTAINER_HOST=$(limactl list podman --format 'unix://{{.Dir}}/sock/podman.sock') export DOCKER_HOST=$(limactl list podman-rootful --format 'unix://{{.Dir}}/sock/podman.sock')5.3 验证连通性
实例启动完成后,可以先做最小验证:
# 在 VM 内 limactl shell podman podman info # 在宿主机(任选其一) podman --remote info docker info若连接失败,优先检查:
- 实例目录下的 socket 是否存在:
ls "$LIMA_HOME/podman/sock/"; - VM 内 podman socket 是否监听:
limactl shell podman podman system service --time=0(需先systemctl --user start podman.socket); - 安装日志:
limactl shell podman sudo tail -f /var/log/cloud-init-output.log。
六、与其他容器模板的对比
Lima 仓库中还提供了同类的容器引擎模板,便于按需选择:
| 模板 | 容器引擎 | 基础镜像 | 说明 |
|---|---|---|---|
template:podman | Podman(rootless) | Fedora | 本文主角 |
template:podman-rootful | Podman(rootful) | Fedora | 本文主角 |
template:docker | Docker(rootless) | Ubuntu LTS | 见 templates/docker.yaml |
template:docker-rootful | Docker(rootful) | Ubuntu LTS | 见 templates/docker-rootful.yaml |
Lima 默认(template:default)则使用 containerd + nerdctl。Podman 方案的价值在于:无需在宿主机安装任何守护进程,仅靠 socket 转发即可让宿主机的podman/dockerCLI 无缝操作 VM 内容器,兼顾隔离性与工具链兼容性。
【免费下载链接】limaLinux virtual machines, with a focus on running containers项目地址: https://gitcode.com/GitHub_Trending/lim/lima
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考