溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Docker鏡像怎么做到一次構(gòu)建,到處運(yùn)行

發(fā)布時(shí)間:2021-12-13 16:14:12 來源:億速云 閱讀:160 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹“Docker鏡像怎么做到一次構(gòu)建,到處運(yùn)行”,在日常操作中,相信很多人在Docker鏡像怎么做到一次構(gòu)建,到處運(yùn)行問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Docker鏡像怎么做到一次構(gòu)建,到處運(yùn)行”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

方法 1:直接在目標(biāo)硬件上構(gòu)建

如果我們可以訪問目標(biāo)架構(gòu)硬件,同時(shí)操作系統(tǒng)上有我們所需的所有構(gòu)建數(shù)據(jù),那么就可以直接在硬件上編譯應(yīng)用程序。

例如,對我們特定場景下構(gòu)建多架構(gòu) Docker 鏡像,可以在樹莓派上安裝 Docker 運(yùn)行時(shí)環(huán)境,然后和在開發(fā)機(jī)上一樣,直接在上面通過應(yīng)用程序的  Dockerfile 構(gòu)建鏡像。該方法是可行的,因?yàn)闃漭傻墓俜讲僮飨到y(tǒng) Raspbian 支持本地安裝 Docker。

但是,如果我們沒法辦法方便的訪問目標(biāo)硬件呢?我們可以在開發(fā)機(jī)器上直接構(gòu)建非本地架構(gòu)的應(yīng)用程序嗎?

方法 2:模擬目標(biāo)硬件

還記得和 16  位任天堂游戲機(jī)一起的快樂時(shí)光嗎?當(dāng)時(shí)我只是一個(gè)小孩子,但是當(dāng)我長大一點(diǎn)之后,我發(fā)現(xiàn)對諸如《超級瑪麗》和《時(shí)空之輪》等經(jīng)典游戲非常懷念。不過我沒有機(jī)會(huì)擁有一臺(tái)超級任天堂游戲機(jī),但是多虧了像  ZSNES 這樣的模擬器,讓我能回到過去,在 32 位個(gè)人電腦上體驗(yàn)這些經(jīng)典游戲帶來的樂趣。

通過模擬器,我們不僅能夠玩電子游戲,還能夠構(gòu)建非本地二進(jìn)制文件。當(dāng)然這里不是使用 ZSNES,而是使用更加強(qiáng)大更靈活的模擬器:QEMU。QEMU  是一個(gè)自由且開源的模擬器,支持許多通用架構(gòu),包括:ARM、Power-PC 和 RISC-V。通過運(yùn)行一個(gè)全功能模擬器,我們可以啟動(dòng)一個(gè)可以運(yùn)行 Linux  操作系統(tǒng)的通用 ARM 虛擬機(jī),然后在虛擬機(jī)中設(shè)置開發(fā)環(huán)境,編譯應(yīng)用程序。

但是,如果仔細(xì)思考下,一個(gè)全功能虛擬機(jī)有一些浪費(fèi)資源。在該模式下,QEMU 會(huì)模擬整個(gè)系統(tǒng),包括諸如定時(shí)器、內(nèi)存控制器、SPI 和 I2C  總線控制器等硬件。但是大部分情況下,我們編譯應(yīng)用程序不會(huì)關(guān)心以上所提到的硬件特性。還能更好么?

方法 3:通過 binfmt_misc 模擬目標(biāo)架構(gòu)的用戶空間

在 Linux 系統(tǒng)上,QEMU 有另外一種操作模式,可以通過用戶模式模擬器來運(yùn)行非本地架構(gòu)的二進(jìn)制程序。該模式下,QEMU 會(huì)跳過方法 2  中描述的對整個(gè)目標(biāo)系統(tǒng)硬件的模擬,取而代之的是通過 binfmt_misc 在 Linux  內(nèi)核注冊一個(gè)二進(jìn)制格式處理程序,將陌生二進(jìn)制代碼攔截并轉(zhuǎn)換后再執(zhí)行,同時(shí)將系統(tǒng)調(diào)用按需從目標(biāo)系統(tǒng)轉(zhuǎn)換成當(dāng)前系統(tǒng)。最終對于用戶來說,他們會(huì)發(fā)現(xiàn)可以在本機(jī)運(yùn)行這些異構(gòu)二進(jìn)制程序。

通過用戶態(tài)模擬器和 QEMU,我們可以通過輕量級虛擬化(chroot 或者容器)來安裝其他 Linux  發(fā)行版,并像在本地一樣編譯我們需要的異構(gòu)二進(jìn)制程序。

下面我們會(huì)看到這將會(huì)是構(gòu)建多架構(gòu) Docker 鏡像的可選方式。

方法 4:使用交叉編譯器

最后,我們還有一種在嵌入式系統(tǒng)社區(qū)標(biāo)準(zhǔn)的做法:交叉編譯。

交叉編譯器是一個(gè)特殊的編譯器,它運(yùn)行在主機(jī)架構(gòu)上,但是可以為不同的目標(biāo)架構(gòu)生成的二進(jìn)制程序。例如,我們可以有一個(gè) amd64 架構(gòu)的 C++  交叉編譯器,目標(biāo)架構(gòu)是一個(gè) aarch74(64 位  ARM)的嵌入式設(shè)備(例如一個(gè)智能手機(jī)或者其他東西)?;谶@種方式的一個(gè)現(xiàn)實(shí)中的例子是,世界上數(shù)十億安卓設(shè)備都使用這種方式來構(gòu)建軟件。

從性能上考慮,這種方式有和直接在目標(biāo)硬件上構(gòu)建(方法 1)相同的效率,因?yàn)樗鼪]有運(yùn)行在模擬器上。但是交叉編譯的變數(shù)取決于使用的編程語言,如果是 Go  語言就非常方便。

搞糊涂了嗎?對于 Docker 鏡像來說會(huì)更復(fù)雜……

注意前面提到的所有編譯方式都只是生成單一的應(yīng)用程序二進(jìn)制文件。對于現(xiàn)代容器來說,當(dāng)我們引入 Docker  鏡像的時(shí)候,不僅僅是關(guān)于構(gòu)建單獨(dú)的二進(jìn)制文件,而是構(gòu)建一整個(gè)異構(gòu)容器鏡像!這比之前說的要更加麻煩。

如果所有這些聽上去很痛苦,不要難過,因?yàn)闃?gòu)建非本地平臺(tái)二進(jìn)制程序本來就很痛苦。在此之上增加 Docker 帶來的復(fù)雜度,看起來應(yīng)該留給專家來處理。

感謝最新版本 Docker 運(yùn)行時(shí)環(huán)境帶來的實(shí)驗(yàn)性擴(kuò)展,構(gòu)建多架構(gòu)鏡像現(xiàn)在比以前方便多了。

構(gòu)建多架構(gòu) Docker 鏡像

為了能夠更方便的構(gòu)建多架構(gòu) Docker 鏡像,我們可以使用最近發(fā)布的 Docker 擴(kuò)展:buildx。buildx 是下一代標(biāo)準(zhǔn) docker  build 命令的前端,既我們熟悉的用于構(gòu)建 Docker 鏡像的命令。通過借助 BuildKit 的所有功能,buildx 擴(kuò)展了表中 docker  build 命令的功能,成為 Docker 構(gòu)建系統(tǒng)的新后端。

讓我們花幾分鐘看下如何使用 buildx 來構(gòu)建多架構(gòu)鏡像。

步驟 1:開啟 buildx

要使用 buildx,首先要確認(rèn)我們的 Docker 運(yùn)行時(shí)環(huán)境已經(jīng)是最新版本 19.03。新版本中,buildx 事實(shí)上已經(jīng)默認(rèn)和 Docker  捆綁在一起,但是需要通過設(shè)置環(huán)境變量 DOCKER_CLI_EXPERIMENTAL 來開啟。讓我們在當(dāng)前命令行會(huì)話中開啟:

$ export DOCKER_CLI_EXPERIMENTAL=enabled

通過檢查版本來驗(yàn)證目前我們已經(jīng)可以使用 buildx:

$ docker buildx version github.com/docker/buildx v0.3.1-tp-docker 6db68d029599c6710a32aa7adcba8e5a344795a7

可選步驟:從源碼構(gòu)建

如果要使用最新版本的 buildx,或者在當(dāng)前環(huán)境下設(shè)置 DOCKER_CLI_EXPERIMENTAL 環(huán)境變量不生效(例如我發(fā)現(xiàn)在 Arch  Linux 系統(tǒng)中設(shè)置無效),我們可以從源碼構(gòu)建 buildx:

$ export DOCKER_BUILDKIT=1 $ docker build --platform=local -o . git://github.com/docker/buildx $ mkdir -p ~/.docker/cli-plugins && mv buildx ~/.docker/cli-plugins/docker-buildx

步驟 2:開啟 binfmt_misc 來運(yùn)行非本地架構(gòu) Docker 鏡像

如果讀者使用的是 Mac 或者 Windows 版本 Docker 桌面版,可以跳過這個(gè)步驟,因?yàn)?binfmt_misc 默認(rèn)開啟。

如果使用是 Linux 系統(tǒng),需要設(shè)置 binfmt_misc。在大部分發(fā)行版中,這個(gè)操作非常簡單,但是現(xiàn)在可以通過運(yùn)行一個(gè)特權(quán) Docker  容器來更方便的設(shè)置:

$ docker run --rm --privileged docker/binfmt:66f9012c56a8316f9244ffd7622d7c21c1f6f28d

通過檢查 QEMU 處理程序來驗(yàn)證 binfmt_misc 設(shè)置是否正確:

$ ls -al /proc/sys/fs/binfmt_misc/ total 0 drwxr-xr-x 2 root root 0 Nov 12 09:19 . dr-xr-xr-x 1 root root 0 Nov 12 09:16 .. -rw-r--r-- 1 root root 0 Nov 12 09:25 qemu-aarch74 -rw-r--r-- 1 root root 0 Nov 12 09:25 qemu-arm -rw-r--r-- 1 root root 0 Nov 12 09:25 qemu-ppc64le -rw-r--r-- 1 root root 0 Nov 12 09:25 qemu-s390x --w------- 1 root root 0 Nov 12 09:19 register -rw-r--r-- 1 root root 0 Nov 12 09:19 status

然后,驗(yàn)證下指定架構(gòu)處理程序已經(jīng)啟用,例如:

$ cat /proc/sys/fs/binfmt_misc/qemu-aarch74 enabled interpreter /usr/bin/qemu-aarch74 flags: OCF offset 0 magic 7f454c460201010000000000000000000200b7 mask ffffffffffffff00fffffffffffffffffeffff

步驟 3:將默認(rèn) Docker 鏡像構(gòu)建器切換成多架構(gòu)構(gòu)建器

默認(rèn)情況下,Docker 會(huì)使用舊的構(gòu)建器,不支持多架構(gòu)構(gòu)建。

為了創(chuàng)建一個(gè)新的支持多架構(gòu)的構(gòu)建器,運(yùn)行:

$ docker buildx create --use --name mybuilder

驗(yàn)證新的構(gòu)建器已經(jīng)生效:

$ docker buildx ls NAME/NODE    DRIVER/ENDPOINT             STATUS   PLATFORMS mybuilder *  docker-container   mybuilder0 unix:///var/run/docker.sock inactive default      docker   default    default                     running  linux/amd64, linux/arm64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6

搞定?,F(xiàn)在 Docker 會(huì)使用新的構(gòu)建器,支持構(gòu)建多架構(gòu)鏡像。

步驟 4:構(gòu)建多架構(gòu)鏡像

好了,現(xiàn)在我們終于可以開始構(gòu)建一個(gè)多架構(gòu)鏡像了。為了演示這個(gè)功能,我們需要一個(gè)示例應(yīng)用。

讓我們創(chuàng)建一個(gè)簡單的 Go 應(yīng)用程序,輸出當(dāng)前運(yùn)行環(huán)境的架構(gòu)信息:

$ cat hello.go package main  import (         "fmt"         "runtime" )  func main() {         fmt.Printf("Hello, %s!\n", runtime.GOARCH) }

讓我們創(chuàng)建一個(gè) Dockerfile 來容器化這個(gè)應(yīng)用

$ cat Dockerfile FROM golang:alpine AS builder RUN mkdir /app ADD . /app/ WORKDIR /app RUN go build -o hello .  FROM alpine RUN mkdir /app WORKDIR /app COPY --from=builder /app/hello . CMD ["./hello"]

這是一個(gè)多階段 Dockerfile,通過 Go 編譯器構(gòu)建我們的應(yīng)用程序,然后將構(gòu)建出來的二進(jìn)制程序使用 Alpine Linux  鏡像創(chuàng)建成最小鏡像。

現(xiàn)在,讓我們使用 buildx 來構(gòu)建一個(gè)支持 arm、arm64 和 amd64 架構(gòu)的多架構(gòu)鏡像,并一次性推送到 Docker Hub:

$ docker buildx build -t mirailabs/hello-arch --platform=linux/arm,linux/arm64,linux/amd64 . --push

是的,就是這樣?,F(xiàn)在 Docker Hub 上我們有了 支持 arm、arm64 和 amd64 架構(gòu)的多架構(gòu) Docker 鏡像。當(dāng)我們運(yùn)行  docker pull mirailabs/hello-arch 時(shí),Docker 會(huì)根據(jù)機(jī)器的架構(gòu)來獲取匹配的鏡像。

如果讀者要問 buildx 是如何實(shí)現(xiàn)這個(gè)魔法的?好吧,在命令的背后,buildx 使用 QEMU 和 binfmt_misc 創(chuàng)建了三個(gè) Docker  鏡像(arm、arm64 和 amd64 架構(gòu)每個(gè)創(chuàng)建一個(gè))。當(dāng)構(gòu)建完成后,Docker  會(huì)創(chuàng)建一個(gè)清單,其中包含這三個(gè)鏡像以及他們對應(yīng)的架構(gòu)。換句話說,“多架構(gòu)鏡像”實(shí)際上是一個(gè)清單,列舉了每個(gè)架構(gòu)對應(yīng)的鏡像。

步驟 5:測試多架構(gòu)鏡像

讓我們來快速測試下多架構(gòu)鏡像,以確保它們都能夠正常工作。由于我們已經(jīng)設(shè)置了 binfmt_misc,因此在開發(fā)機(jī)器上已經(jīng)能夠執(zhí)行任何架構(gòu)的鏡像了。

首先,列出每個(gè)鏡像的散列值:

$ docker buildx imagetools inspect mirailabs/hello-arch Name:      docker.io/mirailabs/hello-arch:latest MediaType: application/vnd.docker.distribution.manifest.list.v2+json Digest:    sha256:bbb246e520a23e41b0c6d38b933eece68a8407eede054994cff43c9575edce96  Manifests:   Name:      docker.io/mirailabs/hello-arch:latest@sha256:5fb57946152d26e64c8303aa4626fe503cd5742dc13a3fabc1a890adfc2683df   MediaType: application/vnd.docker.distribution.manifest.v2+json   Platform:  linux/arm/v7    Name:      docker.io/mirailabs/hello-arch:latest@sha256:cc6e91101828fa4e464f7eddec3fa7cdc73089560cfcfe4af16ccc61743ac02b   MediaType: application/vnd.docker.distribution.manifest.v2+json   Platform:  linux/arm64    Name:      docker.io/mirailabs/hello-arch:latest@sha256:cd0b32276cdd5af510fb1df5c410f766e273fe63afe3cec5ff7da3f80f27985d   MediaType: application/vnd.docker.distribution.manifest.v2+json   Platform:  linux/amd64

有了這些散列值的幫助,我們可以逐一運(yùn)行鏡像,并觀察其輸出:

$ docker run --rm docker.io/mirailabs/hello-arch:latest@sha256:5fb57946152d26e64c8303aa4626fe503cd5742dc13a3fabc1a890adfc2683df Hello, arm!  $ docker run --rm docker.io/mirailabs/hello-arch:latest@sha256:cc6e91101828fa4e464f7eddec3fa7cdc73089560cfcfe4af16ccc61743ac02b Hello, arm64!  $ docker run --rm docker.io/mirailabs/hello-arch:latest@sha256:cd0b32276cdd5af510fb1df5c410f766e273fe63afe3cec5ff7da3f80f27985d Hello, amd64!

到此,關(guān)于“Docker鏡像怎么做到一次構(gòu)建,到處運(yùn)行”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI