本文我們將探討如何使用預裝程序創建并分發 AArch64 容器。
創建容器
首先需要建立一個 Dockerfile。由于創建容器的目的是為小程序提供一個快速且占用資源最小的環境,因此選擇 Alpine Linux 作為容器運行時。Alpine Linux 是一個小型的容器基礎鏡像(8MB),在容器開發中很受歡迎。初始的 Dockerfile 非常小,在獲取容器鏡像后,將“fizzbuzz”可執行文件從預存的構建環境第一部分復制到容器中,并將可執行文件設置為容器的入口點(當容器運行時將自動運行可執行文件):
FROM alpine:latest
WORKDIR /root/
COPY ./fizzbuzz ./
ENTRYPOINT [“./fizzbuzz”]
本次演示以 Podman 為例,其命令行與 Docker 的原理類似:
[dneary@fedora fizzbuzz-c]$ podman build -f ./Dockerfile -t fizzbuzz:1
STEP 1/4: FROM alpine:latest
STEP 2/4: WORKDIR /root/
--> Using cache
a6bfe2eb0767b7966a2e25e3f1fdd638b5a74aaf8abf2abd12f54a8f20fdf9be
--> a6bfe2eb076
STEP 3/4: COPY ./fizzbuzz ./
--> 772088bc011
STEP 4/4: ENTRYPOINT ["./fizzbuzz"]
COMMIT fizzbuzz:1
--> 4afe789ccb9
Successfully tagged localhost/fizzbuzz:1
4afe789ccb91e3ce11907a81f0b0ebbe559b65b10d9e50ff86da8a610670434d
以上步驟看似可成功運行,但當運行容器時:
[dneary@fedora fizzbuzz-c]$ podman run fizzbuzz:1
{"msg":"exec container process (missing dynamic library?) `/root//./fizzbuzz`:
No such file or directory","level":"error","time":"2022-07-11T2334.000019606Z"}
顯然,運行失敗了,但失敗是容器開發的必經之路。
問題在于:構建在 Fedora 主機上的二進制文件被編譯后要動態鏈接到 glibc,而 Alpine Linux 基于 Busybox 并采用 musl 的小型 libc,旨在用于桌面和服務器之外的嵌入式環境。當我們在 Alpine 中運行二進制文件時,無法找到其所需的庫,于是便出現以上錯誤。
對于以上問題,有幾個選項可以進行修正:
1. 在主機上靜態鏈接二進制文件并復制一個嵌入了靜態版本 glibc 的全包二進制文件;
2. 給 Alpine 添加一個兼容層,讓它運行時動態鏈接到 glibc 的二進制文件;
3. 最后一項則為最優選:在 Alpine Linux 容器中構建應用程序。新 Docker 文件在 Alpine 上安裝“build-base”,并復制 C 文件和 Makefile,在容器內編譯 fizzbuzz。
FROM alpine:latest
WORKDIR /build/
# Install C compiler and Make
RUN apk --no-cache add build-base
COPY fizzbuzz.c Makefile ./
RUN make clean && make all
ENTRYPOINT ["./fizzbuzz"]
該方法相當簡單且有效。當我們建立一個新的容器并使用 Podman 運行它時,熟悉的 FizzBuzz 輸出便呈現出來。然而,當運行“podman images fizzbuzz”時,出現了以下問題:
內存優化
由于我們安裝了 GNUMake 以及整個 C 和 C++ 開發堆棧,輕量型小容器從不到 6MB 急劇擴大到了 192MB。那么是否存在一種方法將新構建的可執行文件復制回較小的鏡像?
答案是肯定的:使用“多階段構建”容器來返回到容器的上一層,并從構建環境中復制文件。使用“builder”標記構建的環境,然后將可執行文件復制到原始容器。這也使得 Dockerfile 的復雜性略有增加。
FROM alpine:latest AS builder
WORKDIR /build/
# Install C compiler and Make
RUN apk --no-cache add build-base
COPY fizzbuzz.c Makefile ./
RUN make clean && make all
FROM alpine:latest AS app
WORKDIR /root/
# Add our executable from the builder container
COPY --from=builder /build/fizzbuzz ./
ENTRYPOINT ["./fizzbuzz"]
不過鏡像大小問題可以很好地得到解決:遷移到多階段構建后,容器鏡像恢復到可管理的 5.84MB:
接下來準備在 GitHub 中構建自定義運行程序。我們將使用預安裝在 GitHub “ubuntu-latest” 虛擬環境上的 Docker 堆棧,并在 OCI 上的自托管 AlmaLinux 實例上使用 Podman。
將 Dockerfile 添加到存儲庫后,選擇“添加新工作流”,GitHub Actions 將推薦“構建 Docker 容器”操作:
我們自己的 Docker 鏡像工作流程如下所示。因為在每個運行器上使用的工具鏈不同,所以新的工作流程文件中存在較多重復。遺憾的是,沒有一種簡單的方法來創建一個 build matrix,從而實現在共享其余操作的同時,還能指示不同主機使用哪個容器運行時和 Builder。
name: Docker Image CI
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
x86-fizzbuzz-container:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build the Docker image
run: docker build . --file Dockerfile --tag fizzbuzz:latest –-tag fizzbuzz:${{ github.sha }}
- name: Run the Docker image
run: docker run fizzbuzz
aarch64-fizzbuzz-container:
runs-on: [self-hosted, linux, ARM64]
steps:
- uses: actions/checkout@v3
- name: Build the Docker image with Buildah
uses: redhat-actions/buildah-build@v2
with:
image: fizzbuzz
tags: latest ${{ github.sha }}
containerfiles: |
./Dockerfile
- name: Run the Docker image
run: podman run fizzbuzz
在運行器上安裝 Podman 和 Buildah 工具后,每一次推送項目到 GitHub 后,我們終于可以在本地構建容器并在兩個不同的操作系統上運行。隨后還可以采取一些后續措施來進行完善,比如:
在構建前將項目源目錄安裝到容器中;
運行一組“冒煙測試”驗證最后一次提交未產生任何破壞;
構建容器后自動上傳到容器注冊表;
潛在地構建一個跨硬件架構容器。
不過,本文不會就構建 CI pipeline 進行介紹,我們將在今后的文章中針對基于 Ampere 處理器構建持續集成和持續交付(CI/CD)系統進行介紹。
非常感謝 Podman 社區,GitHub 貢獻的大量操作文檔,以及來自 Twitter 的優秀容器開發者對初學者問題的解答幫助。Ampere 持續挖掘開發社區的創造力,并將其與我們世界一流的處理器相結合。
審核編輯:湯梓紅
-
Linux
+關注
關注
87文章
11304瀏覽量
209484 -
容器
+關注
關注
0文章
495瀏覽量
22061 -
aarch64
+關注
關注
0文章
7瀏覽量
5029
原文標題:創芯課堂 | 通過 Ampere? Altra? 和 GitHub Actions 構建并測試 AArch64 容器
文章出處:【微信號:AmpereComputing,微信公眾號:安晟培半導體】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論