Docker不再是唯一的選擇

2020-11-24 51CTO

Docker並不是唯一的容器化工具,可能還有更好的選擇……

在容器的早期時代(其實更像是4年前),Docker是容器遊戲中唯一的玩家。但現在情況已經不一樣了,Docker不再是唯一的一個,而只是其中一個容器引擎而已。Docker允許我們構建、運行、拉、推或檢查容器鏡像,然而對於每一項任務,都有其他的替代工具,甚至可能比Docker做得還要好。所以,讓我們探索一下,然後再卸載(只是可能),直至完全忘記Docker……

那,為什麼不再用Docker了?

如果你已經使用Docker很長時間了,估計要真正說服你去考慮其他工具,得先提供些依據。

首先,Docker是一個單體工具。它嘗試去涵蓋所有的功能,通常這並不是最佳實踐。大多數情況下,我們都是只選擇一種專門的工具,它只做一件事,並且做得非常好,非常精。

如果害怕切換到不同的工具集是因為將不得不學習使用不同的CLI、API或者說不同的概念,那麼這不會是一個問題。本文中展示的任何工具都可以是完全無縫的,因為它們(包括Docker)都遵循OCI (Open Container Initiative)下的相同規範。它們包含了容器運行時、容器分發和容器鏡像的規範,其中涵蓋了使用容器所需的所有特性。

有了OCI,你可以選擇一套最符合你需求的工具,同時你仍然可以享受跟Docker一樣使用相同的API和CLI命令。

所以,如果你願意嘗試新的工具,那麼讓我們比較一下Docker和它的競爭對手的優缺點和特性,看看是否有必要考慮放棄Docker,使用一些新的閃亮的工具。

容器引擎

在比較Docker和其他工具時,我們需要將其分解為組件,首先我們先討論一下容器引擎。Container Engine是一種工具,它為處理鏡像和容器提供用戶界面,這樣就不必處理SECCOMP規則或SELinux策略之類的事情。它的工作還包括從遠程倉庫提取鏡像並將其擴展到磁碟。它看起來也是運行容器,但實際上它的工作是創建容器清單和帶有鏡像層的目錄。然後它將它們傳遞到容器運行時,如runC或Crun(稍後我們將討論這一點)。

目前已經有許多容器引擎,但Docker最突出的競爭對手是由紅帽開發的Podman。與Docker不同,Podman不需要Daemon來運行,也不需要root特權,這是Docker長期以來一直關注的問題。基於它的名字,Podman不僅可以運行容器,還可以運行pods。如果你不熟悉pods的概念,其實,簡單的概括就是,Pod是Kubernetes的最小計算單元。它由一個或多個容器(主容器和執行支持任務的Sidecar)組成,這使得Podman用戶以後更容易將他們的工作負載遷移到Kubernetes。因此,作為一個簡單的演示,這是如何在一個Pod中運行兩個容器:

  1. ~ $ podman pod create  
  2. ~ $ podman pod list 
  3.  
  4.  
  5. POD ID         NAME    STATUS    CREATED         # OF CONTAINERS   INFRA ID 
  6. 211eaecd307b   mypod   Running   2 minutes ago   1                 a901868616a5 
  7.  
  8.  
  9. ~ $ podman run -d  
  10. ~ $ podman run -d  
  11. ~ $ podman ps -a  
  12.  
  13.  
  14. CONTAINER ID  IMAGE                           COMMAND               CREATED        STATUS            PORTS  NAMES               POD           POD NAME 
  15. 3b27d9eaa35c  docker.io/library/nginx:latest  nginx -g daemon o...  2 seconds ago  Up 1 second ago          brave_ritchie       211eaecd307b  mypod 
  16. d638ac011412  docker.io/library/nginx:latest  nginx -g daemon o...  5 minutes ago  Up 5 minutes ago         cool_albattani      211eaecd307b  mypod 
  17. a901868616a5  k8s.gcr.io/pause:3.2                                  6 minutes ago  Up 5 

最後,Podman提供了與Docker完全相同的CLI命令,因此只需執行alias docker = podman並裝作什麼都沒有改變。

除了Docker和Podman之外,還有其他的容器引擎,但我個人認為它們都是沒什麼出路的技術,或者都不太適合本地開發和使用。但是,要全面了解,至少要看一下其中的內容:

  • LXD——LXC (Linux Containers)是一個容器管理器(守護進程)。該工具提供了運行系統容器的能力,這些系統容器提供了更類似於VM的容器環境。它位於非常狹窄的空間,沒什麼用戶,所以除非你有非常具體的實例,否則最好還是使用Docker或Podman。
  • CRI-O——當你Google什麼是CRI-O你可能會發現它被描述為容器引擎。不過,實際上它只是容器運行時。其實它既不是引擎,也不適合「正常」使用。我的意思是,它是專門為Kubernetes運行時(CRI)而構建的,而不是為最終用戶使用的。
  • Rkt——rkt(「火箭」)是由CoreOS開發的容器引擎。這裡提到這個項目只是為了完整性,因為這個項目已經結束,開發也停止了——所以也就沒必要再使用了。

構建鏡像

對於容器引擎來說,一般都只選擇Docker。但是,當涉及到構建鏡像時,選擇的餘地還是比較多的。

首先,介紹一下Buildah。Buildah是紅帽開發的另一個工具,它與Podman配合使用相當合適。如果已經安裝了Podman,你可能會注意到podman build子命令,它實際上只是偽裝的Buildah,因為它的二進位文件已經包含在Podman裡。

至於它的特性,它遵循了與Podman相同的路線——無守護程序和無根的,並遵循OCI的鏡像標準,所以它能保證所構建的鏡像和Docker構建的是一樣的。它還能夠從Dockerfile或更恰當的命名Containerfile來構建鏡像,Dockerfile和Containerfile都是相同的,只是命名的區別。除此之外,Buildah還對鏡像層提供了更精細的控制,允許在單層中提交更多變更。唯一的例外是(在我看來)與Docker的區別是,由Buildah構建的鏡像是基於用戶的,因此用戶可以只列出自己構建的鏡像。

那麼,考慮到Buildah已經包含在Podman CLI中,大家可能會問,為什麼還要使用單獨的Buildah CLI?Buildah CLI是podman build中包含的命令的超集,所以基本不需要單獨接觸Buildah CLI,但是通過使用它,你可能還會發現一些額外有用的特性(有關podman build和buildah之間的差異的細節,請參閱這個文章)。

現在,我們來看看一個演示:

  1. ~ $ buildah bud -f Dockerfile . 
  2.  
  3. ~ $ buildah from alpine:latest  # Create starting container - equivalent to "FROM alpine:latest" 
  4. Getting image source signatures 
  5. Copying blob df20fa9351a1 done   
  6. Copying config a24bb40132 done   
  7. Writing manifest to image destination 
  8. Storing signatures 
  9. alpine-working-container  # Name of the temporary container 
  10. ~ $ buildah run alpine-working-container  
  11. fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/APKINDEX.tar.gz 
  12. fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/community/x86_64/APKINDEX.tar.gz 
  13. ... 
  14.  
  15. ~ $ buildah commit alpine-working-container my-final-image  # Create final image 
  16. Getting image source signatures 
  17. Copying blob 50644c29ef5a skipped: already exists   
  18. Copying blob 362b9ae56246 done   
  19. Copying config 1ff90ec2e2 done   
  20. Writing manifest to image destination 
  21. Storing signatures 
  22. 1ff90ec2e26e7c0a6b45b2c62901956d0eda138fa6093d8cbb29a88f6b95124c 
  23.  
  24. ~ # buildah images 
  25. REPOSITORY               TAG     IMAGE ID      CREATED         SIZE 
  26. localhost/my-final-image latest  1ff90ec2e26e  22 seconds ago  51.4 MB 

從上面的腳本可以看到,我們可以只用buildah bud構建鏡像,bud代表使用Dockerfile構建,但是你還可以使用更多Buildahs的腳本:from,run和copy,這些命令對應命令Dockerfile的(FROM image,RUN…,COPY…)。

下一個是谷歌的Kaniko。Kaniko也是從Dockerfile構建容器鏡像,跟Buildah類似,也不需要守護進程。與Buildah的主要區別在於,Kaniko更專注於在Kubernetes中構建鏡像。

Kaniko使用gcr.io/ Kaniko -project/executor作為鏡像運行。這對於Kubernetes來說是行得通的,但是對於本地構建來說不是很方便,並且在某種程度上違背了它的初衷,因為我們得先使用Docker來運行Kaniko鏡像,然後再去構建鏡像。也就是說,如果正在為Kubernetes集群中構建鏡像的工具進行選型(例如在CI/CD Pipeline中),那麼Kaniko可能是一個不錯的選擇,因為它是無守護程序的,而且(可能)更安全。

從我個人的經驗來看——我在Kubernetes/OpenShift集群中使用了Kaniko和Buildah來構建鏡像,我認為兩者都能很好地完成任務,但在使用Kaniko時,我看到了一些將鏡像導入倉庫時的,會有隨機構建崩潰和失敗的情況。

第三個競爭者是Buildkit,也可以稱為下一代的Docker build。它是Moby項目的一部分。在Docker裡可以使用DOCKER_BUILDKIT=1 Docker build…作為實驗特性進行啟用。那麼,它的核心價值到底有哪些?它引入了許多改進和炫酷的特性,包括並行構建、跳過未使用的階段、更好的增量構建和無根構建。然而另一方面,它仍然需要運行守護進程(buildkitd)才能運行。所以,如果你不想擺脫Docker,但是想要一些新的特性和更好的改進,那麼使用Buildkit可能是最好的選擇。

和前面一樣,這裡我們也還有一些「光鮮亮麗的產品」,它們也都有非常具體的場景,雖然並不是我們的首選:

  • Source-To-Image(S2I)是一個不需要Dockerfile直接從原始碼構建鏡像的工具包。這個工具在簡單的、預期的場景和工作流中運行的很好,但是如果有太多的定製,或者該項目沒有預期的布局,你很快就會覺得這個工具很煩人和笨拙。如果你對Docker還不是很有信心,或者如果在OpenShift集群上構建鏡像,那麼你可以嘗試考慮一下使用S2I,因為使用S2I構建是一個內置特性。
  • Jib是谷歌的另一個工具,專門用於構建Java鏡像。它包括Maven和Gradle插件,可以輕鬆地構建鏡像,而不會干擾Dockerfile。
  • 最後一個但並不是不重要的是Bazel,它是谷歌的另一款工具。它不僅用於構建容器鏡像,而且是一個完整的構建系統。如果你只是想構建一個鏡像,那麼鑽研Bazel可能有點過頭,但絕對是一個很好的學習體驗,所以如果你想嘗試,rules_docker絕對是一個很好的起點。

容器運行時

最後一個大塊兒是容器運行時,它負責運行容器。容器運行時是整個容器生命周期/棧的一部分,除非你對速度、安全性等有一些非常具體的要求,否則一般是不需要對其進行幹擾。所以,如果讀者看到這裡已經厭倦,那麼可以跳過這一部分。如果不是,那麼有關容器運行時的選擇,如下:

runC是基於OCI容器運行時規範創建的,且最流行的容器運行時。Docker(通過containerd)、Podman和crio使用它,所以幾乎所有東西都依賴於LXD。它幾乎是所有產品/工具的默認首選項,所以即使你在閱讀本文後放棄Docker,但你仍然會用到runC。

runC的另一款替代方產品為Crun,名稱類似(容易混淆)。這是Red Hat開發的工具,完全用C編寫(runC是用Go編寫的)。這使得它比runC更快,內存效率更高。考慮到它也是OCI兼容的運行時。所以,如果你想做個測試,切換起來很容易。儘管它現在還不是很流行,但在RHEL 8.3技術預覽版中,它將作為一個替代OCI運行時,同時,考慮到它是紅帽的產品,我們可能最終會看到它會成為Podman或CRI-O的默認首選項。

說到CRI-O。前面我說過,CRI-O實際上不是一個容器引擎,而是容器運行時。這是因為CRI-O不包括比如推送鏡像這樣的特性,而這正是容器引擎的特性。作為運行時的CRI-O在內部使用runC運行容器。通常情況下不需要在單機嘗試這個工具,因為它被構建為用於Kubernetes節點上的運行時,可以看到它被描述為「Kubernetes需要的所有運行時,僅此而已」。因此,除非你正在設置Kubernetes集群(或OpenShift集群——CRI-O已經是默認首選項了),否則不大可能會接觸到這個。

本節的最後一個內容是containerd,它是CNCF的一個畢業的項目。它是一個守護進程,充當各種容器運行時和作業系統的API。在後臺,它依賴於runC,是Docker引擎的默認運行時。谷歌Kubernetes引擎(GKE)和IBM Kubernetes服務(IKS)也在使用。它是Kubernetes容器運行時接口的一個部署(與CRI-O相同),因此它是Kubernetes集群運行時的一個很好的備選項。

鏡像檢測與分發

容器棧的最後一部分是鏡像的檢測與分發。這有效地替代了docker inspect,還(可選地)增加了遠程鏡像倉庫之間複製/映射鏡像的能力。

這裡唯一要提到的可以完成這些任務的工具是Skopeo。它由紅帽公司開發,是Buildah,Podman和CRI-O的配套工具。除了我們都從Docker中知道的基本的skopeo inspect之外,Skopeo還能夠使用skopeo copy複製鏡像,它允許你在遠程鏡像倉庫之間映射鏡像,而無需先將它們拉到本地倉庫。如果你使用本地倉庫,此功能也可以作為pull/push。

另外,我還想提一下Dive,這是一個檢查、探測和分析鏡像的工具。它對用戶更友好一些,提供了更可讀的輸出,可以更深入地探測鏡像,並分析和衡量其效率。它也適合在CI管道中使用,它可以測量你的鏡像是否「足夠高效」,或者換句話說——它是否浪費了太多空間。

結論

本文的目的並不是要說服大家完全拋棄Docker,而是向大家展示構建、運行、管理和分發容器及其鏡像的整個場景和所有選項。包括Docker在內的每一種工具都有其優缺點,評估哪一組工具最適合你的工作流和場景才是最重要的,真心希望本文能在這方面幫助到你。

【編輯推薦】

【責任編輯:

未麗燕

TEL:(010)68476606】

點讚 0

相關焦點

  • 微服務部署到docker中
    右鍵選擇項目,選擇「添加」->「Docker支持...」4. 選擇Docker的目標OS5.可以看到項目根目錄下新增一個名為Dockerfile的文件6.通過Xftp將項目從Windows下的磁碟位置拷貝到Linux的root目錄下二、Linux下通過Docker構建應用1.通過Xshell連接上Linux虛擬機,進入到項目目錄下,然後通過docker
  • Docker & Singularity
    自從微軟更新了WSL2(雖然我一直在用WSL),但是發現docker只能在WSL2下使用,又是被需求更新。於是上網查了下window 家庭版的更新方法。打個補丁就好(可以參考該連結https://www.jianshu.com/p/a20c2d58eaac)。
  • CoreOS實踐指南(七):Docker容器管理服務
    現在看來,CoreOS已經不是唯一預裝了Docker的作業系統了,但它是第一個,也是目前做得最成功的一個。RedHat和Canonical(Ubuntu的母公司)隨其後也分別推出了自己的預裝Docker的系統發行版,但知悉者寥寥,並沒有做成氣候。
  • SpringBoot+GitLab+Docker+Jenkins實現持續集成下
    該框架使用了特定的方式來進行配置,從而使開發人員不再需要定義樣板化的配置。通過這種方式,Spring Boot致力於在蓬勃發展的快速應用開發領域(rapid application development)成為領導者。接下來我們來編寫一個最簡單的SpringBoot入門項目。<?
  • 雲計算核心技術Docker教程: Docker 容器連接
    下面我們來實現通過埠連接到一個 docker 容器。我們創建了一個 python 應用的容器。命令如下:# docker run -d -P training/webapp python app.py另外,我們可以指定容器綁定的網絡地址,比如綁定 127.0.0.1。
  • 將Docker與pipeline一起使用
    /dockerfiles/test") testImage.inside { sh 'make test' }}test-image根據位於的Dockerfile 構建./dockerfiles/test/Dockerfile。通過將其他參數 添加到方法的第二個參數中,可以將其他參數傳遞給 docker buildbuild()。
  • 【最新版】Docker實戰總結
    安裝使用 a) 搜索並下載鏡像 b) 單機方式運行 c) 訪問http://localhost:9000 首次登陸需要註冊用戶,給admin用戶設置密碼,然後單機版選擇local連接即可。
  • Docker是什麼?有什麼用途?及理論知識詳細說明
    運維生成環境中:docker化。 了解docker三個重要概念 image鏡像 docker鏡像就是一個只讀模板,比如,一個鏡像可以包含一個完整的centos,裡面僅安裝apache或用戶的其他應用,鏡像可以用來創建docker容器,另外docker提供了一個很簡單的機制來創建鏡像或者更新現有的鏡像,用戶甚至可以直接從其他人那裡下周一個已經做好的鏡像來直接使用 container
  • 雲計算核心技術Docker教程:Docker Compose的restart和rm命令詳解
    Docker-Compose restart命令可以重新啟動所有已停止並正在運行的服務,Docker-Compose rm命令可以刪除已經停止的容器,如果服務在運行,需要先docker-compose stop 停止容器。
  • 雲計算核心技術Docker教程:利用Dockerfile來創建鏡像
    在docker使用過程中,我們可以從已經創建的容器中更新鏡像,並且commit提交這個鏡像來創建新的鏡像,使用docker commit 來擴展一個鏡像比較簡單,但是不方便在一個團隊中分享此時我們可以使用 Dockerfile 指令來創建一個新的鏡像。
  • 雲計算核心技術Docker教程:Docker Compose的pull和push命令詳解
    Docker-Compose pull命令可以拉取docker-compose.yml或者docker-stack.yml文件中定義的服務關聯的鏡像,Docker-Compose push命令可以將服務鏡像推送到registry/repository中。
  • Docker 引擎概述
    Docker Engine 實際上是一個客戶端伺服器(client-server)應用:一個在伺服器上長期運行的被稱為 dockerd 的進程。一個指定結構的 APIs,這個 API 被用來與 Docker 守護進程進行通信。
  • Docker 創建你自己的橋接網絡
    下面的例子顯示了如何創建一個橋接網絡: $ docker network create -d bridge my_bridge 參數 -d 用於告訴 Docker 在新的網絡中使用 橋接(bridge) 驅動。
  • 使用Jenkins、Docker 構建部署 Serverless 應用
    和 docker 命令掛載到容器中,啟動 jenkins 命令如下: 注意:由於容器內 Jenkins 服務是由 jenkins 用戶啟動的,它無法訪問 /var/run/docker.sock,因此我們需要更改這個文件的權限。
  • 雲計算核心技術Docker教程:Compose使用
    2.使用 docker-compose.yml 定義構成應用程式的服務,這樣它們可以在隔離環境中一起運行。3.最後,執行 docker-compose up 命令來啟動並運行整個應用程式。運行以下命令以下載 Docker Compose 的當前穩定版本:$ sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
  • Docker v1.13.0 正式版發布,應用容器引擎
    可通過 docker plugin rm 命令卸載插件。Top 10 新增功能正式支持服務棧: docker stack正式支持插件:docker plugin添加在 Swarm 集群環境下對密碼、密鑰管理的 secret 管理服務:docker secret增加 docker system 命令
  • 大白話讓你更懂Docker
    倉庫 為了更好的理解,先講大家講個小故事 小A同學想要造一棟別墅,他重金請來了高級設計師,高級建造師,等各種高級工人,熱火朝天曆時二個月房子建成了,半年後,小A同學由於工作調動需要換到另一個城市,他只好在另一個城市花了重金又打造了一棟別墅 小A有一個朋友小B,跟小A是同樣的場景,唯一不同的是
  • Docker邁入雲(DockerHub)+端(Docker引擎)時代
    Docker深受網際網路巨頭髮PaaS創業公司青睞,國內的百度在大規模實踐Docker,Google 的 Compute Engine 也支持 docker 在其之上運行,Redhat也積極地在RHEL中集成對Docker的支持。
  • Docker專用基礎Linux發行版選擇
    隨著容器雲和Docker技術的發展,容器基礎鏡像OS和運行容器的宿主機OS的選擇都成了一個問題。有很多Linux發行商和雲運營商也發布了專門的容器發行版,與傳統發行版作業系統相比,這些Linux可能更安全,更簡練,發行版有一我們列出業界流行的幾種發行版,希望能幫助大家甄選最適合自己的發行版。
  • Docker 容器 9 類 48 個常見故障的處理和使用規範 | 周末送資料
    Docker是一種相對使用較簡單的容器,我們可以通過以下幾種方式獲取信息:1、通過docker run執行命令,或許返回信息2、通過docker logs 去獲取日誌,做有針對性的篩選3、通過systemctl status docker查看docker服務狀態4、通過journalctl -u docker.service