本文转自 bleem,原文:https://mritd.com/2022/06/08/happy-using-docker-on-macos/,版权归原作者所有。欢迎投稿,投稿请添加微信好友:cloud-native-yang

一、目标任务

首先要明确的是, 作为了一个每天在 Linux Server 上 rm -rf 的人来说, 如果想在 Mac 上使用 Docker, 最舒服的也是兼容所有 docker cli 命令行操作即可; 至于图形化的界面完全不需要, 我们并不指望图形化界面能比敲命令快到哪里去, 也不指望图形化界面变为主力; 所以本篇文章的核心目标:

  • 在 Mac 上使用完整的 docker cli 命令, 包括对基本的 -v 挂载支持

  • 可以支持 x86 的模拟, 可以为 x86 build 或者运行相关镜像

  • 在尽可能的情况下可以进行 CPU 架构切换, arm64 与 x86 最好都可以支持

二、工具选型

首先是我们最熟悉的 Docker Desktop, 安装包奇大无比, UI 卡成翔, 启动速度更不用提而且还时不时的卡死, 所以 Docker Desktop 是完全不考虑的; 那么剩下几种方案类型如下:

  • VM 虚拟机方案

  • Colima 方案

  • Lima 方案

先说结论: Lima YES! VM 虚拟机方案要花钱且难受, Colima 暂且不稳定. Lima 方案直接看第五节.

三、虚拟机方案

目前在 M1 上, 唯一可用或者说堪用的虚拟机当属 Parallels Desktop, 至于其他的 VBox、VMware 目前还不成熟; 如果纯  qemu 有点过于硬核(愿意自己封装脚本的当我没说); 对于 Parallels Desktop 来说, 我们需要购买开发版本的  License, 因为我们需要借助 prlctl 来实现一些自动化 , 一年好几百… 经过测试这种方案也有一定可行性:

  • 1、首先通过 PD 创建 Ubuntu 之类的虚拟机

  • 2、在虚拟机里安装好 Docker

  • 3、通过 cli 程序启动虚拟机, 并且将 ~ rw 挂载到虚拟机里

基于这个方案我个人尝试过, 曾经写过一个 PD[1] 的小工具来辅助完成挂载动作. 但是这种工具有一些明显的缺点:

  • 目前不支持 x86 的模拟, 可通过 binfmt 缓解, 但是不完善

  • 虚拟机要花钱且需要虚拟机 cli 支持完善

四、Colima 方案

Colima 号称是专门为了解决 Mac 平台容器化工具链的, 但是实际测试发现目前 Colima 还不算稳定, 有时可能会有一些小问题; 当然 Colima 最大的问题是: 可自定义化程度不高, 底层基于 Lima. Colima 具体的使用方式啥的这里暂不详细描述, 目前还不稳定不太推荐.

五、Lima 方案

Lima 目前是基于 QEMU 的自动化 VM 方案, 当前由于其出色设计, 借助 Cloud Init 可以在很多阶段帮助我们完成 hook;  所以不论是装个 Docker 还是 k8s, 亦或是弄个其他的东西都很方便; 而且很多方案比如 docker 官方都有相关样例,  我们可以直接照抄外加做点自定义.

5.1、Lima 安装

Lima 在 Mac 下安装相对简单, 以下命令将安装 master 分支版本.

$ brew install lima --HEAD

在正常情况下, 安装 Lima 会附带安装 QEMU, 如果本机已经安装 QEMU, 可能需要执行以下命令将 QEMU 升级到 7.0:

$ brew upgrade qemu

为了使用 docker, 还需要通过 brew 安装一下 docker cli:

$ brew install docker

5.2、Lima 使用

默认情况下 Lima 安装完成后会生成一个 lima 的快捷命令, 目前不太推荐使用, 原因是看起来方便一点但是没法控制太多参数, 所以仍然建议使用标准的 limactl 命令进行操作. limactl 使用方式如下:

Lima: Linux virtual machinesUsage:limactl [command]Examples:Start the default instance:$ limactl startOpen a shell:$ limaRun a container:$ lima nerdctl run -d --name nginx -p 8080:80 nginx:alpineStop the default instance:$ limactl stopSee also example YAMLs: /opt/homebrew/share/doc/lima/examplesAvailable Commands:completion    Generate the autocompletion script for the specified shellcopy          Copy files between host and guestdelete        Delete an instance of Lima.edit          Edit an instance of Limafactory-reset Factory reset an instance of Limahelp          Help about any commandinfo          Show diagnostic informationlist          List instances of Lima.prune         Prune garbage objectsshell         Execute shell in Limashow-ssh      Show the ssh command linestart         Start an instance of Limastop          Stop an instancesudoers       Generate /etc/sudoers.d/lima file for enabling vmnet.framework supportvalidate      Validate YAML filesFlags:--debug     debug mode-h, --help      help for limactl-v, --version   version for limactlUse "limactl [command] --help" for more information about a command.

5.3、Lima 配置文件

Lima 通过读取一个 yaml 配置描述文件来决定如何创建一个虚拟机, 该文件基本结构如下:

# 定义每个平台架构需要使用的启动镜像
images:
- location: "https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-amd64.img"arch: "x86_64"
- location: "https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-arm64.img"arch: "aarch64"# 定义虚拟机需要使用哪个架构启动(对应上面的镜像)
arch: "x86_64"# CPU 数量
cpus: 4# 内存大小
memory: "16G"# 磁盘大小
disk: "100G"# 虚拟机与 macOS 宿主机挂载时使用的挂载技术
# 目前推荐 9p, 可换成 sshfs, 但是 sshfs 会有权限问题
mountType: 9p# 定义虚拟机和 macOS 宿主机有哪些目录可以共享
mounts:
- location: "~"# 定义虚拟机对这个目录是否可写writable: true9p:# 对于可写的共享目录, cache 推荐类型为 mmap, 不写好像默认 fscachecache: "mmap"
- location: "/tmp/lima"writable: true9p:cache: "mmap"
# containerd is managed by Docker, not by Lima, so the values are set to false here.
containerd:system: falseuser: false# cloud-init hook 定义
provision:
# 定义以什么权限在虚拟机内执行脚本
- mode: system# This script defines the host.docker.internal hostname when hostResolver is disabled.# It is also needed for lima 0.8.2 and earlier, which does not support hostResolver.hosts.# Names defined in /etc/hosts inside the VM are not resolved inside containers when# using the hostResolver; use hostResolver.hosts instead (requires lima 0.8.3 or later).script: |#!/bin/shsed -i 's/host.lima.internal.*/host.lima.internal host.docker.internal/' /etc/hosts
- mode: systemscript: |#!/bin/bashset -eux -o pipefailif command -v docker >/dev/null 2>&1; thendocker run --platform=linux/amd64 --privileged --rm tonistiigi/binfmt --install allexit 0elseexport DEBIAN_FRONTEND=noninteractivecurl -fsSL https://get.docker.com | shdocker run --platform=linux/amd64 --privileged --rm tonistiigi/binfmt --install all# NOTE: you may remove the lines below, if you prefer to use rootful docker, not rootlesssystemctl disable --now dockerapt-get install -y uidmap dbus-user-sessionfi
- mode: userscript: |#!/bin/bashset -eux -o pipefailsystemctl --user start dbusdockerd-rootless-setuptool.sh installdocker context use rootless
probes:
- script: |#!/bin/bashset -eux -o pipefailif ! timeout 30s bash -c "until command -v docker >/dev/null 2>&1; do sleep 3; done"; thenecho >&2 "docker is not installed yet"exit 1fiif ! timeout 30s bash -c "until pgrep rootlesskit; do sleep 3; done"; thenecho >&2 "rootlesskit (used by rootless docker) is not running"exit 1fihint: See "/var/log/cloud-init-output.log". in the guest
hostResolver:# hostResolver.hosts requires lima 0.8.3 or later. Names defined here will also# resolve inside containers, and not just inside the VM itself.hosts:host.docker.internal: host.lima.internal
portForwards:
- guestSocket: "/run/user/{{.UID}}/docker.sock"hostSocket: "{{.Dir}}/sock/docker.sock"
# 自己定义的启动后消息输出
message: |To run `docker` on the host (assumes docker-cli is installed), run the following commands:------docker context create amd64 --docker "host=unix://{{.Dir}}/sock/docker.sock"docker context use amd64------

5.4、启动 VM

limactl 命令提供了一个 start 子命令用于启动一个虚拟机, 子命令接受一个参数, 这个参数形式不同会产生不同的行为:

  • 如果参数为一个文件路径, 则假定文件为一个 lima 虚拟机的 yaml 配置, 读取并启动

  • 如果参数是单纯字符串, 首先尝试从已存在的虚拟机中查找名字相同的, 找到则立即启动

  • 如果参数是单纯字符串, 且未找到已存在同名的虚拟机, 则尝试通过内置模版来创建一个新的虚拟机

以上面我自己定义的 docker 配置文件为例, 我们直接启动这个配置既可以创建一个 docker 虚拟机:

$ limactl start ./docker-amd64.yaml

启动后会提示是否编辑然后再启动, 这是为了使用同一个配置来启动多个 vm 使用的, 所以不编辑直接启动即可:

稍等片刻后虚拟机将启动成功:

启动完成后, 执行最下面打印出的两条命令, 即可在宿主机上完整的使用 docker. 其本质上利用 docker context 功能, 然后通过将虚拟机中的 sock 文件挂载到宿主机, 并配置 docker context 来实现无缝使用 docker 命令.

5.5、虚拟机调整

某些情况下, 我们需要定制一些 VM 里的配置, 在定制时主要需要调整配置文件的 provision 部分; 在该部分中, 如果 mode 被定义为 system 则会以 root 用户执行相关命令, 否则以普通用户来执行命令. 需要注意的是, 我们定义的脚本需要具有幂等性, 因为脚本在每次都会执行一次, 所以一般对于可能造成数据擦除动作的命令都要写好判断逻辑, 避免重复执行.

关于文件挂载, 这里推荐使用 9p 类型, 未来 lima 将完全切换到该挂载方式; 同时经过测试目前仅有 9p 挂载模式下, 本地目录 rw 映射到虚拟机时不会出现权限问题, sshfs 方式挂载如果遇到 chown 之类的命令会造成权限错误, 可能导致容器启动失败(例如 mysql).

在测试虚拟机配置过程中, 可以直接使用 limactl delete -f xxxx 来强制删除目标虚拟机, 然后重新启动即可; 虚拟机名称默认与 yaml 文件名相同, 可使用 limactl ls 命令查看.

5.6、多平台兼容

在上面我的 docker 配置样例中, 每次虚拟机启动完成后会自动安装 binfmt:

$ docker run --platform=linux/amd64 --privileged --rm tonistiigi/binfmt --install all

这样能保证无论 Lima 虚拟机原始架构是什么, 都能运行其他平台的 docker 镜像; 典型的例如某些 openjdk8 镜像只有 amd64 的版本, 但是在 lima 虚拟机为 aarch64 的情况下仍然可以使用.

除了这种 “速度较快” 的跨架构运行方式, lima 还支持直接在 VM 中定义架构, 这样在 qemu 启动时则会直接从 VM 系统层模拟目标架构; 这种方式的好处是对目标架构兼容性很好, 但是运行速度会更慢. 调整 VM 架构只需要修改 arch 配置即可(注意, 目标架构的镜像一定要配置好):

# 定义每个平台架构需要使用的启动镜像
images:
- location: "https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-amd64.img"arch: "x86_64"
- location: "https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-arm64.img"arch: "aarch64"# 定义本虚拟机需要使用哪个架构启动(对应会使用上面目标架构的镜像)
arch: "aarch64"

六、总结

目前整体来看, Docker Desktop 在 mac 上基本上是很难用的, Colima 现在还不太成熟, 适合轻度使用 docker 的用户;  而重度使用 docker 并且有定制化需求的用户还是推荐 Lima 虚拟机; 同时 Lima 也支持很多操作系统, 官方有大量的样例模版[2](包括 k8s、k3s、podman 等), 非常适合重度容器使用者.

引用链接

[1]

PD: https://github.com/mritd/pd/blob/010101042308ecbad805cffebb93973b55db4ff2/helper/prlctl_wrapper.go#L332

[2]

样例模版: https://github.com/lima-vm/lima/tree/master/examples

你可能还喜欢

点击下方图片即可阅读

理解 Kubernetes 中的 NUMA 架构

2022-06-08

让 M1 芯片的 MacBook Pro 同时支持两个 4k 显示器

2022-06-07

K8s 的核心是 API 而非容器:从理论到 CRD 实践

2022-06-06

使用自动化工作流聚合信息,实现个人数字生活的信息聚合

2022-06-01

云原生是一种信仰 

如何在 Mac 上愉快地使用 Docker相关推荐

  1. 如何在 Mac 上愉快的使用 Docker

    公众号关注 「奇妙的 Linux 世界」 设为「星标」,每天带你玩转 Linux ! 一.目标任务 首先要明确的是, 作为了一个每天在 Linux Server 上 rm -rf 的人来说, 如果想在 ...

  2. 如何在Mac上的IntelliJ IDEA中增加IDE内存限制?

    本文翻译自:How to increase IDE memory limit in IntelliJ IDEA on Mac? I'm using IDEA 12 Leda on Mountain L ...

  3. shell 统计一个词出现的概率_如何在Mac上设置系统范围的字数统计服务

    在本文中,我们将向您展示如何创建系统范围的服务,使您能够在TextEdit,Safari,Mail或Mac上的任何可让您突出显示文本的应用程序中立即获得字数统计和字符计数.如果您经常发现自己粘贴到空白 ...

  4. python下载安装教程mac-教程|如何在mac上为Python安装XGBoost!

    原标题:教程|如何在mac上为Python安装XGBoost! 摘要:XGBoost是一个开发非常快速和准确的梯度增强模型的库,它在Kaggle数据科学竞赛中被大量的kaggle选手选用,其中包括两个 ...

  5. 【转】如何在Mac上卸载Java及安装Java

    如何在 Mac 上卸载 Java? 本文适用于: 平台: Macintosh OS X Java 版本: 7.0, 8.0 使用终端卸载 Oracle Java 注:要卸载 Java,必须具有管理员权 ...

  6. vc 只有顶级窗口可以弹出窗口_如何在Mac上允许弹出窗口

    通常,我们尝试避免弹出窗口,但是有时您需要让它们通过.下面这样做的方法. 由于浏览器阻止了弹出窗口,您是否在macOS上遇到网站问题?幸运的是,您可以在计算机上的主要浏览器(例如Safari,Chro ...

  7. win10显示隐藏文件_如何在Mac上显示隐藏文件?苹果mac显示隐藏文件夹方法

    与任何操作系统一样,macOS会将重要文件隐藏起来,以防止意外删除它们并因此而损坏系统.但是,在某些情况下,您可能需要在Mac上显示隐藏文件,例如,浏览" 库"文件夹并清除旧日志, ...

  8. uniapp光标自动定义到文本框_如何在Mac上的照片应用中创建自定义日历

    我花了很多时间为我最好的朋友考虑一份甜蜜的礼物.当我陷入沉思时,我想到了在Mac上使用"照片"应用制作自定义日历的想法.告诉你什么:我的朋友真的很喜欢个性化的日历,上面装饰着令人难 ...

  9. python numpy库安装 mac_教程|如何在mac上为Python安装XGBoost!

    原标题:教程|如何在mac上为Python安装XGBoost! 摘要:XGBoost是一个开发非常快速和准确的梯度增强模型的库,它在Kaggle数据科学竞赛中被大量的kaggle选手选用,其中包括两个 ...

最新文章

  1. java双等号和equals_Java中的 equals和双等号,你懂吗?
  2. Kubernetes — 网络流量模型
  3. JAVA 的读取Excel方法_纯Java的方式读取excel2007
  4. Redis的基本操作以及info命令
  5. jenkins 启动_通过http请求启动jenkins任务
  6. Big Endian 和 Little Endian 详解
  7. z-index ios失效
  8. js统计字符串中大写字母与小写字母的总个数
  9. 【技巧】使用微信进行简单的拼接长图
  10. 如何实现水平垂直居中?
  11. 计算机硬件仿真软件,仿真软件
  12. Packet Tracer命令大全
  13. linux版本有密钥吗,windows7密钥是什么意思又一Linux版本登陆微软Win10
  14. LeetCode刷题之python解法(持续更新)
  15. FPGA+DSP编码过程
  16. Python实现分布式服务器部署维护
  17. jquery 做一个小的倒计时效果
  18. 关于LInux安装KubeSphere说明
  19. 设计图形抽象类java_Java基础——抽象类
  20. C语言 复数四则运算

热门文章

  1. 谷歌Android手机遭受恶意软件侵犯
  2. w ndows默认截图工具,还在找截图工具吗?最新的Windows 10自带各种截图神技 | 都叫兽软件...
  3. kafka查询offset生产者offset计算消费offset计算
  4. 交代码后各种稀奇古怪的字母
  5. 服务器常用端口号总结
  6. 西欧文字入oracle,sql中的西欧字符到土耳其语(Western European Characterset to Turkish in sql)...
  7. 开发人员必备google插件
  8. 【持续更新】别人总结好的图图图图
  9. 计算机怎么硬盘重做系统,用硬盘如何直接在电脑上重装系统
  10. 【方向盘】工具提效:Sublime Text 4的常用快捷键合集