擺脫 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 

$ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 443/TCP 88m $ kubectl get pods --namespace kube-system kubectl NAME READY STATUS RESTARTS AGE coredns-78fcd69978-ghntt 1/1 Running 1 (77m ago) 88m etcd-minikube 1/1 Running 1 (77m ago) 88m kube-apiserver-minikube 1/1 Running 1 (3m4s ago) 89m kube-controller-manager-minikube 1/1 Running 1 (77m ago) 88m kube-proxy-7bsc2 1/1 Running 1 (77m ago) 88m kube-scheduler-minikube 1/1 Running 1 (3m4s ago) 88m storage-provisioner 1/1 Running 2 (2m17s ago) 88m

執行 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 就能進到裏面去

yanbin $ minikube ssh _ _ _ _ ( ) ( ) ___ ___ () ___ ()| |/') _ _ | |_ __ /' _ _| |/' _ \| || , < ( ) ( )| '_\ /'__\ | ( ) ( ) || || ( ) || || |\ | (_) || |_) )( ___/ (_) (_) (_)(_)(_) (_)(_)(_) (_)\___/'(_,__/'____) $ hostname minikube $ ifconfig | grep 192 inet addr:192.168.64.2 Bcast:192.168.64.255 Mask:255.255.255.0 $ cat /proc/cpuinfo | grep processor processor : 0 processor : 1 $ cat /proc/meminfo | grep MemTotal MemTotal: 3935188 kB

進到該虛擬機,我們列出相關的信息,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 machine init Downloading VM image: fedora-coreos-34.20210904.1.0-qemu.x86_64.qcow2.xz: done Extracting compressed file $ podman machine start INFO[0000] waiting for clients... INFO[0000] listening tcp://0.0.0.0:7777 INFO[0000] new connection from to /var/folders/hm/t_nnzqw55g17fqwhf2rgtx3r0000gp/T/podman/qemu_podman-machine-default.sock Waiting for VM ... qemu-system-x86_64: warning: host doesn't support requested feature: CPUID.80000001H:ECX.svm [bit 2] Downloads git:(:|) podman machine ssh Connecting to vm podman-machine-default. To close connection, use ~. or exit Fedora CoreOS 34.20210904.1.0 Tracker: https://github.com/coreos/fedora-coreos-tracker Discuss: https://discussion.fedoraproject.org/c/server/coreos/ [core@localhost ~]$ cat /proc/cpuinfo | grep processor processor : 0 [core@localhost ~]$ cat /proc/meminfo | grep MemTotal MemTotal: 2013528 kB

上面的信息告訴我們 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&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 內容寫成

FROM busybox

或是

FROM docker.io/busybox

執行

$ 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

.post_ad_footer { display: none; margin-left: auto; margin-right: auto; } @media(min-width: 800px) { .post_ad_footer { display: block !important; } }

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://yanbin.blog/replace-docker-desktop-with-hyperkit-minikube/#more-11697