根据目前(2022/02)最新的 Docker Subscription Service Agreement,Docker Desktop 只对小于 250 员工且年收入不到 1 千万美元的公司,个人用户,教育用途和非商业开源项目,提供免费使用。
对于 Mac 和 Windows 用户来说,如果不能使用 Docker Desktop,还是有非常多的可替代方案。比如 Podman, colima 甚至 docker-machine。而我个人在比较早期的时候,一直是通过 docker machine 的方式在 Mac 上使用 docker。后来发现 docker machine 不再维护,镜像不再更新。转向使用 Docker Desktop。现在公司因为不在 Docker Desktop 免费使用用户范围内。这里简单记录一下,自己在 Mac 上使用 docker 的方案。
简单分为三大块
- 虚拟机安装
- 共享文件
- 连通网络
虚拟机安装
在非 linux 系统上运行容器服务,本质上都是通过运行一个 linux 虚拟机来实现的。免费常用的虚拟机软件 VirtualBox 可以很好的胜任这个工作。既然我们的目的是通过虚拟机来运行 dockerd 服务。这里选择一个小巧精简的系统 Alpine Linux,它的虚拟系统优化版本只有 54.5 MB。
VirtualBox 可以在官网下载安装包。除了安装 VirtualBox 本身,还需要安装它的扩展包,在后面的文件共享时依赖于此。同样可以从官网下载到。
还可以通过 brew 安装:
1 | $ brew install virtualbox |
安装好 VirtualBox 后,新建虚拟机,选择创建一个命名为 “docker” 的 64-bit Linux 系统,1 GB 内存。20 GB 动态分配磁盘。创建好以后。在“Tools” - “Network” 中创建一张虚拟网卡。
在 docker 虚拟机的网络设置中,启用 “Adapter 2”,网络类型选择 “Host-only Adapter”,下面会自动选上我们前面创建好的虚拟网卡。这里稍微解释一下,默认 “Adapter 1” 是 NAT 网络,用来访问外网。这个 IP 在我们的电脑上访问不通。所以新增一个主机网络,用于在电脑上访问这台虚拟机。
再在存储中将我们下好的 Alpine 镜像分配到空的片盘中。就可以开始启动我们的虚拟机了。
虚拟机启动后,进入安装系统。使用 root 免密登录。输入 setup-alpine
开始安装系统。
1 | $ setup-alpine |
安装完成,在存储设置中将安装镜像移除。重新启动 docker 虚拟机。使用 root 用户登录。现将我们电脑的 ssh 公钥添加到 /root/.ssh/authorized_keys
文件中。
1 | mkdir .ssh |
通过 ifconfg 查看 eth1 IP 地址,现在可以在电脑上通过 ssh 登录到虚拟机中了。
登录后,可以开始安装 docker。开启社区仓库地址。取消 /etc/apk/repositories
文件第三行的注释
1 | cat /etc/apk/repositories |
在 mac 上可以配置 DOCKER_HOST,可以直接访问虚拟机中的 docker 服务。(需要先在 mac 上安装 docker 命令工具 brew install docker
)
1 | export DOCKER_HOST=ssh://root@192.168.56.103 |
文件共享
可以直接使用 VirtualBox 提供的文件共享功能。需要先在虚拟机中安装 VirtualBox 扩展驱动。
1 | apk add virtualbox-guest-additions |
在虚拟机配置的共享目录设置中把 /Users 目录配置为永久共享路径。挂载点设置为 Users。将挂载信息配置到虚拟机的 /etc/fstab
文件中。
1 | # 添加如下行 |
通过 mount 命令挂在并查看是否挂在成功。
1 | mkdir /Users |
连通网络
我们可以通过虚拟机转发所有发往容器网络的包。安装好 docker 以后,默认 ipv4 的转发功能已经开启。
1 | cat /proc/sys/net/ipv4/ip_forward |
在虚拟机中配置 iptables 允许 eth1 发往 172.16.0.0/12 网段的包。
1 | iptables -A FORWARD -i eth1 -d 172.16.0.0/12 -j ACCEPT |
可以把这个规则配置添加到 dockerd 启动的配置文件中。dockerd 启动完成后,自动配置该规则。在 /etc/init.d/docker 文件中,增加以下内容:
1 | start_post() { |
另外还需要在 mac 主机上添加一个路由规则,将发往 172.16/12 网段的包,发往 192.168.56.103 (虚拟机 eth1 IP)网关。
1 | $ sudo route add -net 172.16/12 192.168.56.103 |
启动一个 nginx 服务验证,可以在 mac 上直接通过容器 ip 访问 nginx 服务了。
1 | $ docker run --rm --name nginx -i -d nginx |
最后我自定义了两个命令别名,快速启动和关闭 docker 虚拟机。在启动的时候增加路由表信息,关闭时候删除路由表信息。
1 | alias dds='VBoxManage list runningvms' # 查看正常运行的虚拟机 |
结尾
到此,我们有了一个简单的替代 Docker Desktop 方案。当然直接使用 Podman 或 colima 也可以满足大多数使用场景。不过在网络上笔者往前探索了一步。而无论 Podman, colima 还是笔者的方案。都有存在一个问题。就是共享的文件,无法修改权限和 owner。而在某些场景下,通过 bind 目录的方式共享的目录,可能在容器内部,因为 owner 或权限无法修改也无法读写。Docker Desktop 使用自己的 gRPC fuse 方案避免了这个问题。