Contents

Mac 上不装 Docker Desktop,用 Colima 跑 Docker

一、前言

公司发的电脑,Docker Desktop 我一直没装。不是装不上,是不想碰授权这条线。

Docker Desktop 走 Docker Subscription Service Agreement 授权,免费范围是个人使用、教育、非商业开源,以及员工少于 250 人且年营收低于 1000 万美元的小型企业。麻烦的地方在于:这是台公司设备,我虽然只是自己用(跑跑自己的项目、学点东西),但"个人使用"和"公司使用"在办公电脑上本来就是个模糊地带。真按公司使用算,大企业就得买订阅、走采购流程,为这点事不值当。

机器内存也不宽裕(16 GiB),Docker Desktop 那套常驻 GUI 加后台进程的开销也不小。

所以需求很明确:

  1. 授权干净,个人在公司电脑上用不涉及任何授权问题
  2. 资源占用小,16 GiB 的机器得留够内存给 IDE 和浏览器
  3. 性能要好,构建和文件挂载不能拖后腿
  4. 原生兼容 docker 和 docker compose 命令,不想改脚本、改习惯

二、方案选型

几个候选方案放一起对比:

方案 授权 原生 docker/compose 资源占用 结论
Docker Desktop 个人免费,公司设备上归属模糊 是 重(GUI + 常驻进程) 有合规风险,排除
OrbStack 商业/公司使用需按人购买 是 很轻 同上,性能最好但有合规风险
Rancher Desktop Apache-2.0,免费 可切到 moby(dockerd) 中(Electron GUI) 可用,GUI 偏重
Podman Apache-2.0,免费 否,命令是 podman / podman compose 轻 免费但兼容性打折
Colima MIT,完全免费 是(跑的就是 dockerd) 轻(纯 CLI) 选它

1. Docker Desktop

默认答案,兼容性最好。授权上它其实给个人开了免费口子,但装在办公设备上归属说不清,没必要冒这个风险。

2. OrbStack

这几个里性能最强的,启动快、占用低,但它同样不是免费的。官方授权页写得很清楚:freelancer、商业或非营利实体、政府实体,或者与 OrbStack 相关的工作年收入超过 1 万美元,都必须按用户购买授权;装完只有 30 天 Pro 试用,试用结束降级为"个人使用"。所以在公司设备上它和 Docker Desktop 是同一个问题。

3. Rancher Desktop

SUSE 开源的(Apache-2.0),免费,功能也全,内置 k3s,运行时能在 moby(dockerd)和 containerd 之间切。代价是它是个 Electron 桌面应用,GUI 和常驻开销比纯 CLI 方案大,对 16 GiB 的机器不算友好。

4. Podman

完全免费,无守护进程、rootless,安全性也好。问题是它的命令叫 podman 而不是 docker,compose 也是 podman compose,背后还要另装 provider。虽然可以配 alias 或 socket 兼容层,但终究做不到原生兼容——平时看到的教程、文档、脚本里全是 docker xxx,我不想在这上面花精力。

5. Colima

刚好满足这几条需求:MIT 协议,个人怎么用都不涉及授权问题;纯 CLI,没有 GUI 常驻进程;而且它不是"模拟" docker——它就是在虚拟机里跑了一个真的 dockerd,把 socket 暴露给宿主机,所以 docker 和 docker compose 完全原生,一个命令都不用改。

三、Colima 简介

Colima 是 Containers on Lima 的缩写。它在 macOS 上借 Lima 起一个轻量 Linux 虚拟机,虚拟机里跑 dockerd,再把 Docker socket 暴露给宿主机的 docker 命令。

1
2
macOS 主机                          Colima 虚拟机
docker CLI / docker compose ─socket─▶ dockerd / 容器 / 镜像

除了 Docker,运行时还能选 containerd(配 nerdctl)或 incus,顺手也能起一套 k3s。

四、安装

1. 安装命令行工具

1
brew install colima docker docker-compose docker-buildx

四个包各管一摊:

  • colima:管理器,依赖 lima
  • docker:只装 CLI,不带 daemon,这正是关键
  • docker-compose:Compose v2
  • docker-buildx:构建插件,brew install docker 不会带上它,得单独装

2. 创建虚拟机

我创建时只用了这一条:

1
colima start --cpu 4 --memory 8 --disk 60

跑完之后,Colima 会把解析后的完整配置写进 ~/.colima/default/colima.yaml。我这份是:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
cpu: 4
memory: 8
disk: 60
arch: aarch64
runtime: docker
hostname: colima
vmType: vz
mountType: virtiofs
portForwarder: ssh
rosetta: false
binfmt: true
nestedVirtualization: false
mountInotify: false
autoActivate: true
rootDisk: 20
sshConfig: true
sshPort: 0
mounts: []
provision: null
kubernetes:
  enabled: false
network:
  mode: shared
  address: false
  interface: en0
  gatewayAddress: 192.168.5.2   # Colima 默认值,虚拟机内部网段的网关

跟默认值对比,真正被我改掉的只有三项:

配置项 默认 我设的
cpu 2 4
memory 2 8
disk 100 60

其余全是默认值。vmType: vz(Apple 的虚拟化框架)、mountType: virtiofs(最快的挂载驱动)、binfmt: true(能直接跑 amd64 镜像)在 Apple Silicon + macOS 13 以上本来就是默认,所以命令行里不用写。

有个细节要提醒:我这份配置里 disk 写的是 60,但进虚拟机看实际设备是 100 GiB:

1
2
3
4
5
6
7
8
$ colima ssh -- lsblk
NAME    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
vda     253:0    0   20G  0 disk
├─vda1  253:1    0   19G  0 part /
├─vda15 253:15   0   99M  0 part /boot/efi
└─vda16 259:0    0  923M  0 part /boot
vdb     253:16   0  100G  0 disk
└─vdb1  253:17   0  100G  0 part /var/lib/docker

因为磁盘只支持扩容、不支持缩容——--disk 如果是在虚拟机建好之后才补上的,它不会真的把盘改小。所以磁盘大小最好创建时一次定好,或者干脆别省,直接用默认的 100。

3. 资源参数

  • CPU:默认 2 核偏少,给 4 核,编译和并行跑容器都从容。
  • 内存:默认 2 GiB 基本不够用,跑两个容器就开始吃紧,我给了 8 GiB。16 GiB 的机器这么分走一半后,宿主机还剩 8 GiB,同时开 IDE 和浏览器会有点紧;如果觉得吃力,退回 6 GiB 也够跑一般项目。
  • 磁盘:默认 100 GiB,我设了 60。磁盘只能调大不能调小,官方注释写得很明确(value can only be increased after virtual machine has been created),所以一开始宁可给宽一点。

4. 编辑配置

有些配置没法用命令行参数表达,比如 dockerd 的 daemon 配置、provision 脚本。这种情况用:

1
colima start --edit

它会打开 yaml,改完保存再启动。也可以直接编辑 ~/.colima/default/colima.yaml,下次 start 生效。

5. 验证

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ colima list
PROFILE    STATUS     ARCH       CPUS    MEMORY    DISK     RUNTIME    ADDRESS
default    Running    aarch64    4       8GiB      60GiB    docker

$ colima status
INFO[0000] colima is running using macOS Virtualization.Framework
INFO[0000] arch: aarch64
INFO[0000] runtime: docker
INFO[0000] mountType: virtiofs
INFO[0000] docker socket: unix:///Users/<用户名>/.colima/default/docker.sock

进虚拟机看资源占用:

1
2
3
4
5
6
7
$ colima ssh -- free -h
               total        used        free      shared  buff/cache   available
Mem:           7.7Gi       1.2Gi       615Mi       804Ki       6.1Gi       6.5Gi

$ colima ssh -- df -h /var/lib/docker
Filesystem      Size  Used Avail Use% Mounted on
/dev/vdb1        98G  7.2G   86G   8% /var/lib/docker

free 里的 7.7Gi 就是配置的 8 GiB 减掉内核占用后的数。宿主机目录通过 virtiofs 挂进去,虚拟机里能直接看到:

1
2
$ colima ssh -- mount | grep virtiofs
lima-xxxxxxxx on /Users/<用户名> type virtiofs (rw,relatime)

docker 侧的信息:

1
2
$ docker info --format '{{.ServerVersion}} | {{.Driver}} | cgroup{{.CgroupVersion}} | {{.NCPU}}CPU | {{.MemTotal}}'
29.5.2 | overlayfs | cgroup2 | 4CPU | 8307167232

客户端 29.8.0、服务端 29.5.2,版本不完全一致是正常的。

五、Compose 命令

装完 docker run 是好的,但 docker compose(带空格那个)会直接报错:

1
2
3
$ docker compose version
docker: unknown command: docker compose
Run 'docker --help' for more information

原因是 brew 装的 docker-compose 是 Docker CLI 的插件,它被放在 Homebrew 自己的插件目录里($(brew --prefix)/lib/docker/cli-plugins),而 Docker CLI 默认不会去那里找。

1. 直接用 docker-compose

1
2
$ docker-compose version
Docker Compose version 5.5.1

就是命令名多了个连字符,别的没差别。我比对过两者的 md5——brew 在插件目录里放的那个 docker-compose,本身就是指向 bin/docker-compose 的软链,同一个二进制、同一个版本:

1
2
3
4
$ md5 -q /opt/homebrew/Cellar/docker-compose/5.5.1/bin/docker-compose
dccdcf38cd7fff7f229d3a1748b74126
$ md5 -q /opt/homebrew/Cellar/docker-compose/5.5.1/lib/docker/cli-plugins/docker-compose
dccdcf38cd7fff7f229d3a1748b74126

所以它不是"旧版 Compose v1",就是正牌的 Compose v2:

  • 功能完全一致,up / down / build / logs 一个不少
  • 配置文件也完全通用,docker-compose.yaml、docker-compose.yml、compose.yaml、compose.yml 都能识别,内容格式一模一样
  • 现有脚本只要把 docker compose xxx 改成 docker-compose xxx 就能跑

不配任何东西就能用,我一开始就是这么用的。

2. 注册为 CLI 插件

如果你更习惯带空格的写法,或者手上的脚本、文档里都是 docker compose,把它注册成插件就行。两种方式我都实测过,都能生效。

方式一是告诉 Docker CLI 去 Homebrew 的插件目录找(Homebrew 官方推荐):

1
2
3
4
5
6
7
{
	"auths": {},
	"currentContext": "colima",
	"cliPluginsExtraDirs": [
		"/opt/homebrew/lib/docker/cli-plugins"
	]
}

注意是往已有的 ~/.docker/config.json 里加一个字段,别整个覆盖。Apple Silicon 的 brew 前缀是 /opt/homebrew,Intel 机器是 /usr/local,用 brew --prefix 确认一下。

方式二是软链到用户级插件目录:

1
2
mkdir -p ~/.docker/cli-plugins
ln -sfn /opt/homebrew/opt/docker-compose/bin/docker-compose ~/.docker/cli-plugins/docker-compose

改完验证:

1
2
$ docker compose version
Docker Compose version 5.5.1

这一步不是必须的。不做也能用 docker-compose 正常干活,功能没有任何差别,我平时就是直接用 docker-compose。

六、私有镜像仓库

公司内网一般都有自建的 registry。这里分两种情况,都要改 colima.yaml——Colima 没有对应的命令行参数。

有个前提要先知道:colima.yaml 里的 docker 段会原样映射成虚拟机内的 /etc/docker/daemon.json,所以 dockerd 层面的配置都写在这儿。

1. HTTP 明文仓库

内网私服图省事只开了 HTTP,docker 默认会拒绝(它要求 HTTPS),得显式声明这是"不安全仓库"。

编辑 ~/.colima/default/colima.yaml:

1
2
3
docker:
  insecure-registries:
    - registry.example.com:5000

写 域名:端口 或 IP:端口,端口不能省。colima.yaml 自带的注释里给的也是同样的示例。

改完重启生效:

1
colima restart

验证有两种方式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$ docker info | grep -A3 "Insecure Registries"
 Insecure Registries:
  registry.example.com:5000
  127.0.0.0/8

# 或者直接看虚拟机里的实际配置
$ colima ssh -- sudo cat /etc/docker/daemon.json
{
  "insecure-registries": [
    "registry.example.com:5000"
  ]
}

之后拉取和登录就正常了:

1
2
docker pull registry.example.com:5000/library/nginx:alpine
docker login registry.example.com:5000

2. 自签证书的 HTTPS 仓库

如果私服上了 TLS,但证书是自签的,docker pull 会报:

1
x509: certificate signed by unknown authority

这种情况不要拿 insecure-registries 绕过去,那等于放弃证书校验。正确做法是把 CA 装进虚拟机。

按 Docker 官方文档,Linux 上的 dockerd 会从 /etc/docker/certs.d/<仓库地址>/ 读自定义 CA:目录名就是仓库的 host:port,里面的 *.crt 会被当作根证书。

1
2
3
/etc/docker/certs.d/
└── registry.example.com:5000
    └── ca.crt          # 签发该仓库证书的根 CA(PEM)

后缀要留意:.crt 才会被当成 CA 根证书,写成 .cert 会被误判为客户端证书然后报错。

虚拟机里的文件改了不持久,重建就没了,所以用 provision 脚本——它在每次启动时执行,因此要写成幂等的:

1
2
3
4
5
6
7
provision:
  - mode: system
    script: |
      set -e
      mkdir -p /etc/docker/certs.d/registry.example.com:5000
      cp /Users/<你的用户名>/certs/ca.crt \
         /etc/docker/certs.d/registry.example.com:5000/ca.crt      

$HOME 默认已经挂进虚拟机了,把 ca.crt 放在宿主机家目录(比如 ~/certs/ca.crt),脚本里引用挂载后的路径即可。改完 colima restart。

顺带一提:Docker Desktop 的文档明确要求不要在虚拟机里配 /etc/docker/certs.d,而要用宿主机的 ~/.docker/certs.d。Colima 不一样——它虚拟机里跑的是标准 Linux dockerd,所以 /etc/docker/certs.d/ 才是正确位置。

3. 注意事项

  • insecure-registries 只是让 docker 跳过 TLS 校验,不等于免认证,该 docker login 还是要登录。
  • 登录凭据存在宿主机的 ~/.docker/config.json 里,不在虚拟机内。
  • 如果是公司统一的内部 CA(而不是单台自签),用 provision 把 CA 装进去,比逐个加 insecure 干净得多。
  • 换成 containerd 运行时(--runtime containerd)时配置方式不同,要写 containerd 的 hosts.toml,这里不展开。

七、日常操作

1. 起停与状态

1
2
3
4
5
colima start
colima stop
colima restart
colima status
colima list        # 别名 ls

2. 调整资源

只能先停再改:

1
2
colima stop
colima start --cpu 6 --memory 12

CPU 和内存随便调,磁盘只能往上加。

3. 挂载目录

默认会把 $HOME 和 /tmp/colima 挂进去,容器里能直接访问你的代码目录。要额外挂别的:

1
colima start --mount ~/work:w     # :w 表示可写

我平时用默认的挂载就够。

4. 端口与网络

容器映射到宿主机的端口默认就能访问,不用额外配。要让虚拟机在局域网里有独立 IP:

1
colima start --network-address

国内网络可能需要指定 DNS:

1
colima start --dns 223.5.5.5 --dns 1.1.1.1

5. 多套环境隔离

想同时跑两套互不干扰的环境,用 profile:

1
2
3
4
colima start --profile dev  --cpu 2 --memory 4
colima start --profile test --runtime containerd
colima list
colima stop --profile dev

每个 profile 是独立的虚拟机和 socket。

6. 切换 containerd 运行时

1
2
3
colima start --runtime containerd
colima nerdctl install
nerdctl run hello-world

7. 启用 k3s

1
2
3
brew install kubectl
colima start --kubernetes
kubectl get nodes

管理命令:colima kubernetes start|stop|reset|delete。

8. 进入虚拟机

1
2
colima ssh
colima ssh -- htop     # 直接执行命令

9. 彻底删除

--data 连镜像和容器一起清,--force 跳过确认:

1
colima delete --data --force

两个参数一起用要谨慎,删掉就恢复不了。

八、常见问题

1. docker compose 提示 unknown command

直接用 docker-compose 就行,两者是同一个二进制;想用带空格的写法,按上面注册插件。

2. Cannot connect to the Docker daemon

多半是虚拟机没起来,或者 context 跑偏:

1
2
colima status
docker context use colima

3. 启动时报虚拟化相关错误

换个 VM 类型试试:

1
2
colima start --vm-type vz      # Apple Silicon 默认,最快
colima start --vm-type qemu    # 兼容性更好,慢一些

4. 挂载的文件在容器里不更新

开一下 inotify:

1
colima start --mount-inotify

九、卸载

1
2
3
colima stop
colima delete -f
brew uninstall colima docker docker-compose docker-buildx

十、小结

换成 Colima 之后,docker 命令照旧,compose 用 docker-compose(或者按上面的方式注册一下,让 docker compose 也能用),授权上的顾虑没了,机器上也少了一个常驻的 GUI 应用。

纯 CLI、没有 GUI、配置就是一份 YAML。16 GiB 的机器给 8 GiB 内存、4 核 CPU,自己跑跑容器完全够用。