? ? Docker的目標(biāo)是 “Build, Ship, and Run Any App, Anywhere” 决帖。但是我們?cè)趯?shí)際環(huán)境中會(huì)發(fā)現(xiàn)現(xiàn)在的服務(wù)器除了Intel x86架構(gòu)的還有ARM墩朦,也有OpenPOWER(ppc64le).Docker Image是容器運(yùn)行的基礎(chǔ)吮螺,它是依賴于操作系統(tǒng)的。比如說我們不能把一個(gè)tomcat的ppc64le/linux架構(gòu)的Docker鏡像運(yùn)行在amd64/linux 架構(gòu)的環(huán)境中,否則你會(huì)遇到 “exec format error”尊残。早期Docker鏡像存儲(chǔ)的設(shè)計(jì)沒有充分考慮到鏡像Multi architecture的支持,而是簡(jiǎn)單的使用鏡像存儲(chǔ)庫(kù)的前綴來區(qū)分相同應(yīng)用的不同平臺(tái)淤堵,并建議開發(fā)者將不同平臺(tái)的鏡像應(yīng)該push到相對(duì)應(yīng)的Docker hub的鏡像倉(cāng)庫(kù)中寝衫。
? ? 從Docker registry v2.3和Docker 1.10 開始,Docker hub就可以pull multi architecture Docker鏡像了.Docker社區(qū)重新定義了 v2.2 Image specification format(PR #1068)并在 Implement schema2 manifest formats(PR #1281)實(shí)現(xiàn)了Multi architecture Docker鏡像功能拐邪。這個(gè)功能能夠讓我們?cè)诓煌珻PU架構(gòu)的主機(jī)上慰毅,運(yùn)行相同的docker pull 命令就可以直接獲得符合當(dāng)前主機(jī)CPU架構(gòu)的鏡像。比如在不同CPU架構(gòu)的主機(jī)上運(yùn)行?docker run -it --rm busybox arch 這個(gè)命令扎阶,我們能自動(dòng)獲取到不同架構(gòu)的busybox的docker 鏡像汹胃。除了busybox鏡像,httpd,nginx, tomcat和etcd等主流開源應(yīng)用都有了Multi architecture Docker鏡像支持东臀。在Docker Hub里只要鏡像有顯示支持不同架構(gòu)的標(biāo)簽就是Multi architecture Docker鏡像着饥。
? ? Docker 通過使用 manifest lists 技術(shù)來實(shí)現(xiàn)Multi architecture Docker鏡像。什么是image manifest list呢惰赋?一個(gè)image manifest list 包含指向已經(jīng)存在鏡像的manifest對(duì)象列表(圖一)宰掉。
圖一
一個(gè)image manifest list包含已經(jīng)存在鏡像的manifest對(duì)象的平臺(tái)特性(CPU arch和OS類型)特征(圖二)
圖二
當(dāng)我們運(yùn)行docker pull拉取鏡像的時(shí)候,如果registry響應(yīng) docker pull 命令不是 image manifest里的, Docker 檢查manifest list 然后 pull該平臺(tái)對(duì)應(yīng)的 list entry然后再運(yùn)行赁濒。distribution protocol 是后向兼容的,? manifest lists 只服務(wù)于指明了支持 Accept header的客戶端贵扰。對(duì)于不支持 manifest lists的客戶端, registries 將會(huì)返回給 x86-64 Linux image manifest. Manifest lists 通過 Docker Content Trust 支持全部特征,確保 multi-platform image 內(nèi)容被加密驗(yàn)證和檢驗(yàn)流部。
? ? ?制作一個(gè)multi architecture Docker鏡像最重要的是定義image的manifest list戚绕。下面演示分別使用兩種工具定義manifest list
1 . Enhanced Docker CLI
這是加強(qiáng)版的Docker CLI,他的code base 是基于社區(qū)的Docker CLI,并且marge了 Docker官方的Add manifest command這個(gè)pull request枝冀,它很好的集成了現(xiàn)有的Docker CLI, 并且增加了docker manifest的sub command 支持舞丛。
a. 構(gòu)建myapp的x86_64鏡像,并且push到Docker hub上
docker build -t huxl/myapp-x86_64:v1
b. 構(gòu)建myapp的ppc64le鏡像果漾,并且push到Docker hub上
docker build -t huxl/myapp-ppc64le:v1
c. 創(chuàng)建指向myappp的x86_64和ppc64le的鏡像的manifests list對(duì)象并將它push到docker hub
./docker manifest create huxl/myapp:v1 huxl/myapp-x86_64:v1 huxl/myapp-ppc64le:v1
./docker manifest annotate huxl/myapp:v1 huxl/myapp-x86_64:v1 --os linux --arch amd64
./docker manifest annotate huxl/myapp:v1 huxl/myapp-ppc64le:v1 --os linux --arch ppc64le
./docker manifest push huxl/myapp:v1
2. Manifest-tool
這是一個(gè)獨(dú)立的小工具球切,它也實(shí)現(xiàn)了v2.2 Image specification format,并且支持查看绒障,創(chuàng)建和push manifests list 對(duì)象到Docker registry吨凑,并且更加方便易用,因?yàn)樗梢允褂脃aml文件定義image manifest list對(duì)象。
a. 創(chuàng)建一個(gè)yaml文件用來表述支持multi architecture的鏡像myapp:v1
? ? ? ? ?image: huxl/myapp:v1
? ? ? ? ? ? ? manifests:
? ? ? ? ? ? ? ? ? image: huxl/myapp-ppc64le:v1
? ? ? ? ? ? ? ? ? ?platform:
? ? ? ? ? ? ? ? ? ? ? ?architecture: ppc64le
? ? ? ? ? ? ? ? ? ? ? ? ?os: linux
? ? ? ? ? ? ? ? ? ? image: huxl/myapp-x86_64:v1
? ? ? ? ? ? ? ? ? ? platform:
? ? ? ? ? ? ? ? ? ? ? ? architecture: amd64
? ? ? ? ? ? ? ? ? ? ? ? os: linux
b. push myapp.yaml到docker hub
./manifest-tool push from-spec myapp.yaml
Note:我們可以使用命令docker manifest inspect huxl/myapp:v1 或者 manifest-tool inspect huxl/mycool-app:v1看到這個(gè)multi architecture Docker鏡像的manifest list鸵钝,這里就不在贅述了糙臼。
總結(jié)
1Push multi architecture Docker鏡像到Docker registry并不會(huì)push image的layers,它只會(huì)push一個(gè)引用,這個(gè)引用指向了已經(jīng)存在的多個(gè)Docker鏡像恩商;
2只有multi architecture Docker鏡像的創(chuàng)建者才需要知道這個(gè)引用背后指向具體的Docker鏡像变逃,而對(duì)最終的用戶是透明的,最終用戶只需要知道鏡像的名字和tag就足夠了怠堪;
3有了multi architecture Docker鏡像支持揽乱,我們?cè)僖膊挥迷谀_本里面判斷OS的類型和CPU的arch而去pull相應(yīng)的鏡像,提高CICD代碼的簡(jiǎn)潔和優(yōu)雅粟矿;
4Image manifest list是極好的兼容性設(shè)計(jì)凰棉,它不但支持multi architecture Docker鏡像,而且不會(huì)影響已經(jīng)在的simple architecture Docker鏡像的使用方式, 用戶不用做二選一的艱難的決定陌粹。
參考?