如何在Mac上使用Docker
一、目標任務
首先要明確的是, 作為了一個每天在 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 的小工具來輔助完成掛載動作. 但是這種工具有一些明顯的缺點:
- 目前不支援 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 machines
Usage:
limactl [command]
Examples:
Start the default instance:
$ limactl start
Open a shell:
$ lima
Run a container:
$ lima nerdctl run -d --name nginx -p 8080:80 nginx:alpine
Stop the default instance:
$ limactl stop
See also example YAMLs: /opt/homebrew/share/doc/lima/examples
Available Commands:
completion Generate the autocompletion script for the specified shell
copy Copy files between host and guest
delete Delete an instance of Lima.
edit Edit an instance of Lima
factory-reset Factory reset an instance of Lima
help Help about any command
info Show diagnostic information
list List instances of Lima.
prune Prune garbage objects
shell Execute shell in Lima
show-ssh Show the ssh command line
start Start an instance of Lima
stop Stop an instance
sudoers Generate /etc/sudoers.d/lima file for enabling vmnet.framework support
validate Validate YAML files
Flags:
--debug debug mode
-h, --help help for limactl
-v, --version version for limactl
Use "limactl [command] --help" for more information about a command.Copy
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: true
9p:
# 對於可寫的共享目錄, cache 推薦型別為 mmap, 不寫好像預設 fscache
cache: "mmap"
- location: "/tmp/lima"
writable: true
9p:
cache: "mmap"
# containerd is managed by Docker, not by Lima, so the values are set to false here.
containerd:
system: false
user: 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/sh
sed -i 's/host.lima.internal.*/host.lima.internal host.docker.internal/' /etc/hosts
- mode: system
script: |
#!/bin/bash
set -eux -o pipefail
if command -v docker >/dev/null 2>&1; then
docker run --platform=linux/amd64 --privileged --rm tonistiigi/binfmt --install all
exit 0
else
export DEBIAN_FRONTEND=noninteractive
curl -fsSL | sh
docker 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 rootless
systemctl disable --now docker
apt-get install -y uidmap dbus-user-session
fi
- mode: user
script: |
#!/bin/bash
set -eux -o pipefail
systemctl --user start dbus
dockerd-rootless-setuptool.sh install
docker context use rootless
probes:
- script: |
#!/bin/bash
set -eux -o pipefail
if ! timeout 30s bash -c "until command -v docker >/dev/null 2>&1; do sleep 3; done"; then
echo >&2 "docker is not installed yet"
exit 1
fi
if ! timeout 30s bash -c "until pgrep rootlesskit; do sleep 3; done"; then
echo >&2 "rootlesskit (used by rootless docker) is not running"
exit 1
fi
hint: 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
------
Copy
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"Copy
六、總結
目前整體來看, Docker Desktop 在 mac 上基本上是很難用的, Colima 現在還不太成熟, 適合輕度使用 docker 的使用者; 而重度使用 docker 並且有定製化需求的使用者還是推薦 Lima 虛擬機器; 同時 Lima 也支援很多作業系統, 官方有大量的樣例模版(包括 k8s、k3s、podman 等), 非常適合重度容器使用者。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70023145/viewspace-2925023/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Mac上Docker的使用MacDocker
- 如何在Mac上使用“接力”功能?Mac
- 如何在 Ubuntu 上使用 Grafana 監控 DockerUbuntuGrafanaDocker
- 如何在Mac上使用表情符號Mac符號
- 如何在 Mac 上使用 Ctrl + Alt + Delete?Macdelete
- 如何在Mac上使用螢幕共享Mac
- 如何在Windows上安裝DockerWindowsDocker
- 如何在Windows上編譯Docker?Windows編譯Docker
- 如何在Mac上使用預覽刪除影像背景?Mac
- Mac新手使用技巧——如何在Mac上優化儲存空間Mac優化
- 如何在 CentOS 7 上安裝 DockerCentOSDocker
- 如何在蘋果Mac上關閉螢幕使用時間?蘋果Mac
- 如何在mac電腦上建立使用者群組?Mac
- 如何在 Mac 鎖定螢幕上使用擬我表情Mac
- PDF Expert使用教程:如何在Mac上使用PDF Expert編輯PDFMac
- Mac新手使用技巧——如何在Mac上開啟和關閉螢幕使用時間Mac
- 如何在 Mac上插入特殊字元Mac字元
- 在mac上安裝DockerMacDocker
- 如何在Docker容器中使用ArthasDocker
- 如何在 Mac 上配置 KubernetesMac
- 如何在Mac上重置列印系統?Mac
- 如何在Mac上重建Spotlight索引Mac索引
- 如何在Mac上OCR PDF教程安利~Mac
- 如何在 Mac 上錄製螢幕Mac
- 如何在蘋果Mac上開啟AirDrop?蘋果MacAI
- 如何在Windows上遠端控制MacWindowsMac
- 如何在PC上安裝Mac OSMac
- 如何在Mac上重置MySQL根密碼MacMySql密碼
- 如何在Mac上訪問任務控制Mac
- win系統如何在mac上執行Mac
- 如何在Mac 上設定虛擬 VPNMac
- 如何在蘋果Mac上刪除APFS卷?蘋果Mac
- Photo Booth教程|如何在Mac上使用 Photo Booth 拍照或錄製影片?bootMac
- 如何在Mac上使用預覽對PDF進行電子簽名Mac
- 如何在 docker for win 上搭建 Laravel 開發環境DockerLaravel開發環境
- 如何在ubuntu[linux] 上用docker安裝SqlserverUbuntuLinuxDockerSQLServer
- 如何在Mac上釋放記憶體?Mac清除RAM教程Mac記憶體
- 如何在mac蘋果電腦上長截圖Mac蘋果