摆脱 Docker Desktop 即将到来的收费

最近本人在 Mac OS X 下安装的 Docker Desktop 经常蹦出要升级的窗口,Skip this update PRO 不能用,Install & Restart  也总是失败,所以每次只能 SNOOZE。原来觉得事有蹊跷,后来才知道这或许与近日吵得沸沸扬扬的 Docker Desktop 收费计划有关。Docker Desktop 是专门为 Windows 和 Mac OS X 定制的,Mac OS X 和 Windows  都是开发人员用的平台。Linux 下可以不用 Docker Desktop,Linux 下 Docker 之间甚至一层窗户纸都没有,实际部署的 Docker 服务也是运行在 Linux 下的。

墙里边微信正在谋划着对聊天记录的云存储收年费,外边是 Docker 在向大公司和开发人员下手,这难道是美国加州版的共同富裕?

查看一下当前 Docker Subscription Service Agreement, 将来可不被收费的对象包括个人用户,教育行业和非商业的开源项目,小企业不收费的门槛是雇员少于 250 并且年收入少于 1 千万美金。还给出一个开始有效日为 2021 年 8 月 31 日,再加一个慷慨的最后宽限日期为  2022 年 1 月 31 日,这其间大家自愿。

对于一个公司人数不少,且日常使用公司配发 Mac 笔记本的开发人员,只能等着被收费了,除非不计法律的风险。

不过,也别急着发慌,还是有替换方案,这里是 Docker Desktop 收费,Docker 仍然是免费的。这儿有两个 Docker Desktop 的替代方案:

  1. hyperkit + minikube
  2. Podman

原文见 Replacing Docker Desktop with hyperkit + minikube

未雨绸缪,况且本人几乎不用 Docker Desktop 提供的 UI, 更不愿用 Docker Desktop 提供的  Kubernetes。先在 Mac 下尝试一番没有 Docker Desktop 的日子,第一步把 Docker Desktop 痛痛快快的卸载掉,这时候连 docker 命令都没有了。

方案 一: hyperkit + minikube

首先要依次安装 docker cli,hyperkit, 和 minikube

安装 Docker CLI

$ brew install docker
$ brew install docker-compose     # 有必要的话把它装了

这时候应该就能执行 dockerdocker-compose 这两个命令了, 但是 docker ps 等命令还无法执行, 因为还没有 DOCKER_HOST, 用 docker --version 看下版本还是可以的。

如果还不见 docker, 可以尝试下面的命令

$ brew install docker-toolbox

安装 hyperkit 和 minikube 前启动

$ brew install hyperkit
$ brew install minikube
$ minikube start

Minikube 实际上是启动了一个 Kubernetes 集群,这里是本人写的一篇 几种简单安装 Kubernetes 集群的方法, 其中就介绍到了如何用 Minikube 来体验 Kubernetes。

这里的 minikube 默认使用的 driver 是 hyperkit,相当于是 minikube start --driver=hyperkit, 也可以指定 virtualbox,命令为 minikube start --driver=virtualbox, 或通过 minikube config set driver virtualbox 来修改。minikube 推荐使用 hyperkit, 坚持使用 virtualbox 的话就可不用安装 hyperkit, 而需安装 virtualbox。使用 virtualbox 为 driver 就会看到在 VirtualBox 中会创建一个虚拟机,

Minikube 启动后可用 Kubernetes 的命令 kubectl get service 查看它所有启动的服务。假如提示 kubectl 命令找不到的话,即用下方命令安装它

$ brew install kubernetes-cli 

执行 docker 相关命令

即将到来的有小激动人心的时刻,现在立马执行像  docker ps 的命令会出现不能连接 Docker daemon 的错误

Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

需先执行下面一条命令

eval $(minikube docker-env)

它其实是帮我们设置了四个环境变量,直接执行 minikube docker-env 就能看到它的输出

$ minikube docker-env
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.64.2:2376"
export DOCKER_CERT_PATH="/Users/yanbin/.minikube/certs"
export MINIKUBE_ACTIVE_DOCKERD="minikube"
# To point your shell to minikube's docker-daemon, run:
# eval $(minikube -p minikube docker-env)

至此,我们就能做我们之前用  docker 做的所有事情了,像

docker build .
docker ps
docker push
等等

如果在每一个会话中都需要上面的环境变量,那么就把 eval $(minikube docker-env) 加到相应 shell 的初始化配置文件中去,如  Zsh 的  .zshrc 文件。

Minikube 的配置

这种方式又仿佛让我们回到了没有 Docker Desktop 之前用 boot2docker 的时代,回看之前 2014 年时写的 Mac 下通过 boot2docker 来使用 Docker 的日志 Mac OS X 下安装使用 Docker,都是被逼的, 轮回来得太快。

前面看到的 DOCKER_HOST 是 192.168.64.2 这个主机,实际上 Docker 要做的事情都是它干的,docker 命令不过是个皮。我们一路下来,显示 192.168.64.2 就是 Minikube 启动的一个虚拟机,minikube ssh 就能进到里面去

进到该虚拟机,我们列出相关的信息,CPU 2 个,内存 4 G。该虚拟机的 CPU 和内存可以进行配置

$ minikube config set cpus 2
$ minikube config set memory 2048

需要在 minikube stop|start 后重新生效,还能在 minikube start 时指定配置参数

$ minikube start --memory=8192 --cpus=4 --disk-size=50g

更多的 minikube 命令用 minikube --help 查看,比如 minikube ip 直接查看到该虚拟机的 IP 地址。

$ minikube dashboard --url

上面命令让我们直接在浏览器中打开一个 Kubernetes Dashboard,想在其中看什么 Kubernetes 的信息都方便,绝对可以把 Docker Desktop 内置的 Kubernetes 比下去。

可能的一个问题,Mac 连了 VPN 之后 minikube 启动会有问题, 既然在无 VPN 情况下启动了 minikube, 一旦连接上了 VPN 后,还是不能用,原因是启动 minikube 的 bridge 的网络在连上 VPN 后不通。具体点讲就是连接了 VPN 之后,VPN 把到原本应该经过 xboxnetX 网络进到虚拟机(如 192.168.99.101) 的路由换成了走 VNP 的网络设备(如 utun2),而且用 route 还删不掉,在 Cisco AnyConnect 中把  All local (LAN) access when using VPN (if configured) 勾选上也不行。

方案二:Podman

我们看到目前 Docker CLI 还是用 Apache 2.0 授权的,可自由使用,万一这也被 Docker 的后台公司看上商机了呢?不用慌张,我们还有一个后招,那就是 Docker CLI 的替代品 Podman。要是将来 Podman 也参于围剿,那会更热闹了。

在 Mac OS 下 Podman 的安装(无论什么都可以 brew 一下)

$ brew install podman

安装的 Podman 当前版本 为 3.3.1.

Podman 可独自挑大梁,它提供了兼容 Docker CLI 的 podman,以及 Mac OS 与 Docker 容器间的媒介虚拟机。在用 podman 之前需用 machine 命令创建并启动那个虚拟机

$ podman machine init
$ podman machine start

既然是一个 Linux 虚拟机就能 ssh 进去探个究竟,下面是那几个命令一并的输出信息

上面的信息告诉我们 podman 初始化并启动了一个  Qemu 的 fecora-coreos 虚拟机,一个 CPU, 内存为 2Gb。

如果我们需要调整该虚拟机的 CPU 和内存,在 podman machine init 时,可指定 --cpus, --memory  参数,用 podman machine init --help 查看帮助信息

$ podman machine init --help
Initialize a virtual machine
Description:
    initialize a virtual machine
Usage:
    podman machine init [options] [NAME]
Examples:
podman machine init myvm
Options:
        --cpus uint                          Number of CPUs. The default is 1. (default 1)
        --disk-size uint                  Disk size in GB (default 10)
        --ignition-path string       Path to ignition file
        --image-path string          Path to qcow image
        -m, --memory uint            Memory (in MB) (default 2048)

或用 podman info, podman system info 也能查看到 podman 系统的信息。

podman 可替代 Docker CLI, 所以先前的 docker build, docker ps 之类的命令可以用 podman buildpodman ps 等,因此我们可创建一个别名

$ alias docker=podman

现在来试一下 podman pull busybox 试图拉取一个镜像

$ podman pull busybox
Error: failed to parse "X-Registry-Auth" header for /v3.3.1/libpod/images/pull?alltags=false&arch=&authfile=&os=&password=&policy=always&quiet=false&reference=busybox&username=&variant=: error storing credentials in temporary auth file (server: "https://index.docker.io/v1/", user: ""): key https://index.docker.io/v1/ contains http[s]:// prefix

原因是之前的 Docker Desktop 创建了 ~/.docker/config.json 文件,不能被 podman 所用,把它删除了(参考:podman: Error: failed to parse "X-Registry-Auth" header),再试就没问题了。

如果一切顺利的话就可以用 podman 来替代 docker 去构建镜像等操作了。

可是在我的本地仍然是 podman build . 构建不了,也许是因为原来安装过 Docker Desktop, hyperkit, 和 minikube 的缘故,也可能是当前 podman  的 bug。

接着来构建一个镜像,Dockerfile 内容写成

或是

执行

$ podman --log-level=debug build .

会看到两种类型的错误

Error: failed Request: Unable to copy tar file from request body /v3.3.1/libpod/build?dockerfile=%5B%22Dockerfile%22%5D&forcerm=1&isolation=1&jobs=1&layers=1&networkmode=0&nsoptions=%5B%7B%22Name%22%3A%22user%22%2C%22Host%22%3Atrue%2C%22Path%22%3A%22%22%7D%2C%7B%22Name%22%3A%22network%22%2C%22Host%22%3Atrue%2C%22Path%22%3A%22%22%7D%5D&outputformat=application%2Fvnd.oci.image.manifest.v1%2Bjson&pullpolicy=missing&rm=1&shmsize=67108864&t=

或是

Error: mkdir /var/tmp/libpod_builder721137603: no space left on device

podman machine ssh 进到虚拟机果然看到

[core@localhost ~]$ mkdir /var/tmp/libpod_builder721137603
mkdir: cannot create directory ‘/var/tmp/libpod_builder721137603’: No space left on device

删除了 ~/.config/containers  和 ~/.local/share/containers 也无济于事。

后来发现  No space left on device 是因为把 Dockerfile 放在了 ~/Downloads 目录中,在构建 Docker 镜像时把该目录中的所有文件都发向了 podman machine, 把  Dockerfile 挪出到一个新建目录中就行。

后来重启后,又瞎折腾了一翻,发现 podman build . 又能工作了,不知所以。

至于 Dockerfile 中的 FROM 要不是加上 docker.io 前缀,这是无所谓的,用 podman info 可查看 podman 搜寻 Docker 镜像的顺序是

registries:
  search:
  - registry.fedoraproject.org
  - registry.access.redhat.com
  - docker.io
  - quay.io

podman login docker.io 按提示输入用户名和密码就能创建 docker hub, 能往其中 push  自己的镜像。

AWS 的 ECR 登陆,用

$ aws ecr get-login-password --region us-east-1 | podman login --username AWS --password-stdin <1234567890>.dkr.ecr.us-east-1.amazonaws.com

也可以登陆成功,之后就能 podman pull <1234567890>.dkr.ecr.us-east-1.amazonaws.com/abc:latest,或者是 podman pull AWS ECR 上的 image 了.

方案三:原始的 Docker Machine

再不济我们还可以再回到重新,用 docker-machine 的办法

$ brew install docker-machine
$ docker-machine create --driver virtualbox default
$ eval $(docker-machine env)
$ docker ps

前面的 Minikube + hyperkit 和这里的 Docker Machine 最终都是用的 Docker Daemon, docker 命令连接到 Docker Machine 来操作的。则 podman 是 Daemonless 的,所以也就只有它不怕 VPN 连接的干扰。

我本人目前的使用的就是 docker-machine,创建的是 VirtualBox 虚拟机,具体步骤是

$ docker-machine create --driver virtualbox --engine-env DOCKER_TLS=no --engine-opt host=tcp://0.0.0.:2375 default
$ docker-machine stop
$ VBoxManage modifyvm "default" --natpf1 "docker,tcp,127.0.0.1,2375,,2375
$ docker-machine start
$ export DOCKER_HOST=tcp://localhost:2375
$ docker ps

通过本地的端口映射就不会受连接 VPN 之后路由的影响,同时在 docker-machine 里还能访问外面(包括 VPN 的资源)

如果在使用 AWS ECR 时出现类似下面的错误

$ aws ecr get-login-password --region us-east-1 | \
  docker login --username AWS --password-stdin 123456789077.dkr.ecr.us-east-1.amazonaws.com
Error saving credentials: error storing credentials - err: exec: "docker-credential-desktop": executable file not found in $PATH, out:
需要做的就是修改 ~/.docker/config.json,把其中的 credsStore 改成 credStore 就行了,现在什么都能解决了,IntelliJ IDEA 中如何要使用  Docker 的话,可配置用 TCP socket, Engine API URL: 中填上 tcp://localhost:2375

总结

其实在 Mac 下通过 minikube 来使用 docker 与 Docker Desktop 的方式是差不多的,用 Docker Desktop 来运行容器也是在它的一个虚拟机中运行,Docker Desktop 给出的虚拟机内存默认为 2 G, 需要更大内存来运行像 Java 容器同样需要修改 Docker Desktop 的配置。

最后重新罗列基本的命令

$ brew install docker
$ brew install hyperkit
$ brew install minikube
$ minikube start
$ eval $(minikube docker-env)
$ docker ......................

podman 一个 Docker Desktop 的完全替代方案,它管理自己的中间虚拟机,podman 命令可作为  docker 命令的别名使用。

用回 Docker Machine 也没问题,只有 podman 在连接了 VPN 后还能正常使用,而其他要配置 DOCKER_HOST 的方式会受到 VPN 连接的影响,需手工加 route, 或更难做。Docker Desktop 也没有这个 VPN 的问题。

最后还发现一个 Docker Desktop 的替代品 Lima, 见 Lima:Docker Desktop for Mac 的免费开源且自由的替代品,尝试了一下,没有前两种方式那么友好。再有 Canonical 的 MicroK8s, 没有 Docker Desktop 的日子会更热闹了。

本文链接 https://yanbin.blog/replace-docker-desktop-with-hyperkit-minikube/, 来自 隔叶黄莺 Yanbin Blog

[版权声明] Creative Commons License 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。

Subscribe
Notify of
guest

5 Comments
Inline Feedbacks
View all comments
trackback

[…] 摆脱 Docker Desktop 即将到来的收费 进一步找到符合自己需求的 Docker Desktop 替代品,前面试用过 hyperkit + […]

bbbush
2 years ago

研究下怎么用 RH 系的工具

jakehu
jakehu
2 years ago
Reply to  Yanbin

podman