跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
Shell / Bash

MacOS 下通过 HyperKit 运行 Podman 的方法

MacOS 下无法直接运行 Podman,需借助虚拟化技术。演示利用 HyperKit 和 Multipass 创建轻量级 Ubuntu 虚拟机,在其中安装 Podman 并开启远程 API。客户端通过 SSH 免密登录连接虚拟机中的 Podman Socket,实现类似 Docker Desktop 的体验。相比 Docker Desktop,此方案资源占用更低,适合需要在 macOS 上高效使用 Podman 的用户。

猫巷少女发布于 2025/1/19更新于 2026/4/252 浏览
MacOS 下通过 HyperKit 运行 Podman 的方法

前言

Podman 是一个无守护程序与 Docker 命令兼容的下一代 Linux 容器工具,该项目由 RedHat 主导。Podman 一直以来只能跑在 Linux 系统上,macOS 和 Windows 只能通过 CLI 远程连接 Podman 的 API 来管理容器。对于 Podman 来说,想要在 macOS 上运行也只能通过虚拟化来实现。

HyperKit 介绍

HyperKit 是一个具有 hypervisor 能力的轻量级虚拟化工具集,包含了基于 xhyve(The BSD Hypervisor)的完整 hypervisor。HyperKit 设计成上层组件诸如 VPNKit 和 DataKit 的接口。xhyve 是 基于 bhyve 的 Mac OS X 移植版本。

我们知道,Docker 在 Linux 上利用了 Linux 原生支持的容器方式实现资源和环境的隔离,直接利用宿主内核,性能接近原生。然而,在 macOS 上却仍然需要虚拟化的技术。早期的 Docker 干脆直接在开源的 VirtualBox 中构建虚拟机,性能低下。后期的 Docker 基于轻量化的虚拟化框架 HyperKit 开发,据说性能得到很大提升。

本文将介绍如何通过 HyperKit 来使用 Podman。方法也很简单,先通过 Hyperkit 创建一个轻量级虚拟机,然后在虚拟机中安装 Podman,并开启 remote API,最后在本地通过 CLI 连接虚拟机中的 Podman。这和 macOS 中的 Docker 实现原理是一样的,只不过 Podman 是没有 Daemon 的,与 Docker 相比可以节省不少资源。

2. 安装 HyperKit

你可以自己下载源代码编译 HyperKit,但我不建议这么做,不同的 macOS 版本会遇到各种各样的错误。我这里推荐两种超级简单的方法:

  1. 直接通过安装 Docker 来获得 HyperKit,因为 Docker Desktop on Mac 就是基于 HyperKit 实现的,所以安装 Docker Desktop on Mac 就能够获得完整的 HyperKit 运行环境。整个过程会非常顺畅和简单。安装完 Docker 之后可以永远不用打开 Docker,直接使用 HyperKit 就好。或者你可以直接卸载 Docker,卸载之前先把 hyperkit 二进制文件备份出来,因为卸载 Docker 也会删掉 hyperkit 二进制文件。
  2. 直接通过安装 Multipass 来获得 HyperKit。Multipass 是 Canonical 公司(Ubuntu)开发的基于不同操作系统内建原生 Hypervisor 实现的工作站。由于 Windows(Hyper-V),macOS(hyperkit)和 Linux(KVM)都原生支持 hypervisor,这样通过 multipass shell 命令就能够在一个 shell 中实现创建运行 Ubuntu 虚拟机。在 macOS 平台,默认的后端是 hyperkit,需要 macOS Yosemite (10.10.3) 以上版本并且需要安装在 2010 以后生产的 Mac 设备。安装方法很简单:
$ brew cask install multipass 

安装好了之后可以在 /Library/Application Support/com.canonical.multipass/bin/ 目录下找到 hyperkit 二进制文件。

3. 创建虚拟机

你可以直接通过 hyperkit 来创建虚拟机,但参数比较复杂,有兴趣的自己研究吧。我推荐直接通过 multipass 来创建,命令特别简单:

$ multipass launch -c 2 -d 10G -m 2G -n podman 
  • -n : 指定启动实例名字
  • -c : 分配 CPU 数量
  • -d : 设置磁盘容量
  • -m : 设置内存容量

第一次启动虚拟机的时候会去拉取镜像,国内网速可能会很慢。

查看已经启动的虚拟机:

$ multipass list Name State IPv4 Image podman Running 192.168.64.2 Ubuntu 20.04 LTS 

进入虚拟机:

$ multipass shell podman Welcome to Ubuntu 20.04.1 LTS (GNU/Linux 5.4.0-52-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage System information as of Sun Nov 8 19:30:29 CST 2020 System load: 0.0 Processes: 119 Usage of /: 13.4% of 11.46GB Users logged in: 0 Memory usage: 11% IPv4 address for enp0s2: 192.168.64.2 Swap usage: 0% 0 updates can be installed immediately. 0 of these updates are security updates. Last login: Sun Nov 8 17:38:31 2020 from 192.168.64.1 ubuntu@podman:~$

4. 安装 Podman

在虚拟机中安装 Podman:

ubuntu@podman:~$ . /etc/os-release ubuntu@podman:~$ echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/ /" | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list ubuntu@podman:~$ curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/Release.key | sudo apt-key add - ubuntu@podman:~$ sudo apt-get update ubuntu@podman:~$ sudo apt-get -y upgrade ubuntu@podman:~$ sudo apt-get -y install podman 

5. 建立 Podman Socket

Podman 依赖于 systemd 的 socket activation 特性。假设 Daemon B 依赖于 Daemon A,那么它就必须等到 Daemon A 完成启动后才能启动。socket activation的思想就是:Daemon B 启动时其实并不需要 Daemon A 真正运行起来,它只需要 Daemon A 建立的 socket 处于 listen 状态就 OK 了。而这个 socket 不必由 Daemon A 建立,而是由 systemd 在系统初始化时就建立。当 Daemon B 发起启动时发起连接,systemd 再将 Daemon A 启动,当 Daemon A 启动后,再将 socket 归还给 Daemon A。

Podman 会通过 podman.socket 先创建一个处于监听状态的 socket 文件 /run/podman/podman.sock,当有进程向该 socket 发起连接时,systemd 会启动同名的 service:podman.service,以接管该 socket。先看看 podman.socket 和 podman.service 长啥样:

ubuntu@podman:~$ sudo systemctl cat podman.socket # /lib/systemd/system/podman.socket [Unit] Description=Podman API Socket Documentation=man:podman-system-service(1) [Socket] ListenStream=%t/podman/podman.sock SocketMode=0660 [Install] WantedBy=sockets.target ubuntu@podman:~$ sudo systemctl cat podman.service # /lib/systemd/system/podman.service [Unit] Description=Podman API Service Requires=podman.socket After=podman.socket Documentation=man:podman-system-service(1) StartLimitIntervalSec=0 [Service] Type=notify KillMode=process ExecStart=/usr/bin/podman system service 

设置开机自启 podman.socket,并立即启动:

ubuntu@podman:~$ sudo systemctl enable podman.socket --now 

确认 socket 是否正处于监听状态:

ubuntu@podman:~$ podman --remote info host: arch: amd64 buildahVersion: 1.16.1 cgroupManager: systemd cgroupVersion: v1 conmon: package: 'conmon: /usr/libexec/podman/conmon' path: /usr/libexec/podman/conmon version: 'conmon version 2.0.20, commit: ' cpus: 2 ...

客户端 CLI 设置

接下来所有的设置,如不作特殊说明,都在 macOS 本地终端执行。

Podman 远程连接依赖 SSH,所以需要设置免密登录,先生成密钥文件:

$ ssh-keygen -t rsa # 一路回车到底 

然后将本地的公钥 ~/.ssh/id_rsa.pub 追加到虚拟机的 /root/.ssh/authorized_keys 文件中。

安装 Podman CLI:

$ brew install podman 

添加远程连接:

$ podman system connection add ubuntu --identity ~/.ssh/id_rsa ssh://root@192.168.64.2/run/podman/podman.sock 

查看已经建立的连接:

$ podman system connection list Name Identity URI podman* /Users/Ryan/.ssh/id_rsa ssh://root@192.168.64.2:22/run/podman/podman.sock 

由于这是第一个连接,所以被直接设置为默认连接(podman 后面加了 *)。

测试远程连接是否可用:

$ podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES $ podman pull nginx:alpine Trying to pull docker.io/library/nginx:alpine... Getting image source signatures Copying blob sha256:188c0c94c7c576fff0792aca7ec73d67a2f7f4cb3a6e53a84559337260b36964 Copying blob sha256:9dd8e8e549988a3e2c521f27f805b7a03d909d185bb01cdb4a4029e5a6702919 Copying blob sha256:85defa007a83f817a511310cca4aca6681b721d44dc9428265959d75 Copying blob sha256:f2dc20663cd74df8fea6d41d3cefe209979e8dbcceb4893ec9eadcc10bc14 Copying blob sha256:0ca2de669571a8bd36e41f03fffa98e53819be7575cb8cd1cb0705b845939 Copying config sha256:e5dcd7aa4b5e5d2df8152b9e58aba32005edd9b269816f5d8b7ced535743d16c Writing manifest to image destination Storing signatures e5dcd7aa4b5e5d2df8152b9e58aba32005edd9b269816f5d8b7ced535743d16c $ podman image ls REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/library/nginx alpine e5dcd7aa4b5e 2 days ago 23.3 MB 

现在我们就可以直接在本地用 podman 愉快地玩耍了!

如果你建立了多个连接,可用使用 --connection 参数指定远程连接,或者使用 podman system connection default <NAME> 来设置默认的远程连接。

最后,我们来看看 hyperkit 的内存占用:

物理内存只占用了 921M,如果你觉得这个内存占用很多,不妨去对比下 Docker Desktop 的内存占用。

目录

  1. HyperKit 介绍
  2. 2. 安装 HyperKit
  3. 3. 创建虚拟机
  4. 4. 安装 Podman
  5. 5. 建立 Podman Socket
  6. 客户端 CLI 设置
  • 💰 8折买阿里云服务器限时8折了解详情
  • 💰 8折买阿里云服务器限时8折购买
  • 🦞 5分钟部署阿里云小龙虾了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog

更多推荐文章

查看全部
  • Linux 系统调优:如何修改文件最大句柄数
  • C++ 实现 MATLAB ismember 函数原理与代码解析
  • 热门开源微服务框架与 Service Mesh 选型参考
  • 华为 OD 机试:小朋友分组最少调整次数 (Java)
  • 华为 OD 机试:二维伞雨滴效应的 BST 验证与实现
  • DIAMOND 基因序列快速比对工具使用及超算集群并行计算指南
  • Java 并发性能优化:如何避免伪共享
  • Linux 下 Java JAR 包后台运行与端口检查实战
  • 测试驱动开发(TDD)核心流程与 Java 实战
  • PyTorch JIT 与 TorchScript:实测推理性能提升 50%
  • MySQL Range 分区实战:解决千万级数据查询性能瓶颈
  • Linux 基础命令与文件操作实战笔记
  • 图对比学习综述(一):对比范式与优化目标
  • Shell 脚本中 date 命令常用技巧与实战
  • SpringBoot 集成 MyBatis-Plus Dynamic-Datasource 实现主从多数据源
  • 串的数据结构定义与 C 语言堆分配存储实现
  • PHP 接口开发:XML 数据的生成与解析实战
  • Office 区域限制导致 Copilot 无法使用的解决方案
  • LLaMA-Factory 大模型微调技术背景与流程
  • 汇川机器人软件 RobotLab 常规操作

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online