<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          下一代Docker鏡像構(gòu)建神器 BuildKit

          共 9931字,需瀏覽 20分鐘

           ·

          2021-05-06 23:49

          來源:https://os.51cto.com/art/202104/660131.htm

          Docker通過讀取Dockerfile中的指令自動構(gòu)建鏡像,Dockerfile是一個文本文件,其中依次包含構(gòu)建給定鏡像所需的所有命令。

          上面的解釋摘自Docker的官方文檔并總結(jié)了Dockerfile的用途。Dockerfile的使用非常重要,因為它是我們的藍圖,是我們添加到Docker鏡像中的層的記錄。

          本文,我們將學(xué)習(xí)如何利用BuildKit功能,這是Docker v18.09上引入的一組增強功能。集成BuildKit將為我們提供更好的性能,存儲管理和安全性。

          本文目標(biāo)

          • 減少構(gòu)建時間;

          • 縮小鏡像尺寸;

          • 獲得可維護性;

          • 獲得可重復(fù)性;

          • 了解多階段Dockerfile;

          • 了解BuildKit功能。

          先決條件

          • Docker概念知識

          • 已安裝Docker(當(dāng)前使用v19.03)

          • 一個Java應(yīng)用程序(在本文中,我使用了一個Jenkins Maven示例應(yīng)用程序)

          讓我們開始吧!

          簡單的Dockerfile示例

          以下是一個包含Java應(yīng)用程序的未優(yōu)化Dockerfile的示例。我們將逐步進行一些優(yōu)化。

          FROM debian
          COPY . /app
          RUN apt-get update
          RUN apt-get -y install openjdk-11-jdk ssh emacs
          CMD [“java”, “-jar”, “/app/target/my-app-1.0-SNAPSHOT.jar”]

          在這里,我們可能會問自己:構(gòu)建需要多長時間?為了回答這個問題,讓我們在本地開發(fā)環(huán)境上創(chuàng)建該Dockerfile,并讓Docker構(gòu)建鏡像。

          # enter your Java app folder
          cd simple-java-maven-app-master
          # create a Dockerfile
          vim Dockerfile
          # write content, save and exit
          docker pull debian:latest # pull the source image
          time docker build --no-cache -t docker-class . # overwrite previous layers
          # notice the build time
          0,21s user 0,23s system 0% cpu 1:55,17 total

          此時,我們的構(gòu)建需要1m55s。

          如果我們僅啟用BuildKit而沒有其他更改,會有什么不同嗎?

          啟用BuildKit

          BuildKit可以通過兩種方法啟用:

          在調(diào)用Docker build命令時設(shè)置DOCKER_BUILDKIT = 1環(huán)境變量,例如:

          time DOCKER_BUILDKIT=1 docker build --no-cache -t docker-class

          將Docker BuildKit設(shè)置為默認(rèn)開啟,需要在/etc/docker/daemon.json進行如下設(shè)置,然后重啟:

          "features": { "buildkit"true } }

          BuildKit最初的效果

          DOCKER_BUILDKIT=1 docker build --no-cache -t docker-class .
          0,54s user 0,93s system 1% cpu 1:43,00 total

          此時,我們的構(gòu)建需要1m43s。在相同的硬件上,構(gòu)建花費的時間比以前少了約12秒。這意味著構(gòu)建幾乎無需費力即可節(jié)約10%左右的時間。

          現(xiàn)在讓我們看看是否可以采取一些額外的步驟來進一步改善。

          從最小到最頻繁變化的順序

          因為順序?qū)τ诰彺婧苤匾晕覀儗OPY命令移到更靠近Dockerfile末尾的位置。

          FROM debian
          RUN apt-get update
          RUN apt-get -y install openjdk-11-jdk ssh emacs
          RUN COPY . /app
          CMD [“java”, “-jar”, “/app/target/my-app-1.0-SNAPSHOT.jar”]

          避免使用“COPY .”

          選擇更具體的COPY參數(shù),以避免緩存中斷。僅復(fù)制所需內(nèi)容。

          FROM debian
          RUN apt-get update
          RUN apt-get -y install openjdk-11-jdk ssh vim
          COPY target/my-app-1.0-SNAPSHOT.jar /app
          CMD [“java”, “-jar”, “/app/my-app-1.0-SNAPSHOT.jar”]

          apt-get update 和install命令一起使用

          這樣可以防止使用過時的程序包緩存。

          FROM debian
          RUN apt-get update && \
              apt-get -y install openjdk-11-jdk ssh vim
          COPY target/my-app-1.0-SNAPSHOT.jar /app
          CMD [“java”, “-jar”, “/app/my-app-1.0-SNAPSHOT.jar”]

          刪除不必要的依賴

          在開始時,不要安裝調(diào)試和編輯工具,以后可以在需要時安裝它們。

          FROM debian
          RUN apt-get update && \
              apt-get -y install --no-install-recommends \
              openjdk-11-jdk
          COPY target/my-app-1.0-SNAPSHOT.jar /app
          CMD [“java”, “-jar”, “/app/my-app-1.0-SNAPSHOT.jar”]

          刪除程序包管理器緩存

          你的鏡像不需要此緩存數(shù)據(jù)。借此機會釋放一些空間。

          FROM debian
          RUN apt-get update && \
              apt-get -y install --no-install-recommends \
              openjdk-11-jdk && \
              rm -rf /var/lib/apt/lists/*
          COPY target/my-app-1.0-SNAPSHOT.jar /app
          CMD [“java”, “-jar”, “/app/my-app-1.0-SNAPSHOT.jar”]

          盡可能使用官方鏡像

          使用官方鏡像有很多理由,例如減少鏡像維護時間和減小鏡像尺寸,以及預(yù)先配置鏡像以供容器使用。

          FROM openjdk
          COPY target/my-app-1.0-SNAPSHOT.jar /app
          CMD [“java”, “-jar”, “/app/my-app-1.0-SNAPSHOT.jar”]

          使用特定標(biāo)簽

          請勿使用latest標(biāo)簽。

          FROM openjdk:8
          COPY target/my-app-1.0-SNAPSHOT.jar /app
          CMD [“java”, “-jar”, “/app/my-app-1.0-SNAPSHOT.jar”]

          尋找最小的鏡像

          以下是openjdk鏡像列表。選擇最適合自己的最輕的那個鏡像。

          REPOSITORY TAG標(biāo)簽 SIZE大小
          openjdk 8 634MB
          openjdk 8-jre 443MB
          openjdk 8-jre-slim 204MB
          openjdk 8-jre-alpine 83MB

          在一致的環(huán)境中從源構(gòu)建

          如果你不需要整個JDK,則可以使用Maven Docker鏡像作為構(gòu)建基礎(chǔ)。

          FROM maven:3.6-jdk-8-alpine
          WORKDIR /app
          COPY pom.xml .
          COPY src ./src
          RUN mvn -e -B package
          CMD [“java”, “-jar”, “/app/my-app-1.0-SNAPSHOT.jar”]

          在單獨的步驟中獲取依賴項

          可以緩存–用于獲取依賴項的Dockerfile命令。緩存此步驟將加快構(gòu)建速度。

          FROM maven:3.6-jdk-8-alpine
          WORKDIR /app
          COPY pom.xml .
          RUN mvn -e -B dependency:resolve
          COPY src ./src
          RUN mvn -e -B package
          CMD [“java”, “-jar”, “/app/my-app-1.0-SNAPSHOT.jar”]

          多階段構(gòu)建:刪除構(gòu)建依賴項

          為什么要使用多階段構(gòu)建?

          • 將構(gòu)建與運行時環(huán)境分開

          • DRY方式


            • 具有開發(fā),測試等環(huán)境的不同詳細信息
          • 線性化依賴關(guān)系

          • 具有特定于平臺的階段

          FROM maven:3.6-jdk-8-alpine AS builder
          WORKDIR /app
          COPY pom.xml .
          RUN mvn -e -B dependency:resolve
          COPY src ./src
          RUN mvn -e -B package

          FROM openjdk:8-jre-alpine
          COPY --from=builder /app/target/my-app-1.0-SNAPSHOT.jar /
          CMD [“java”, “-jar”, “/my-app-1.0-SNAPSHOT.jar”]

          如果你此時構(gòu)建我們的應(yīng)用程序,

          time DOCKER_BUILDKIT=1 docker build --no-cache -t docker-class .
          0,41s user 0,54s system 2% cpu 35,656 total

          你會注意到我們的應(yīng)用程序構(gòu)建需要大約35.66秒的時間。這是一個令人愉快的進步。

          下面,我們將介紹其他場景的功能。

          多階段構(gòu)建:不同的鏡像風(fēng)格

          下面的Dockerfile顯示了基于Debian和基于Alpine的鏡像的不同階段。

          FROM maven:3.6-jdk-8-alpine AS builder

          FROM openjdk:8-jre-jessie AS release-jessie
          COPY --from=builder /app/target/my-app-1.0-SNAPSHOT.jar /
          CMD [“java”, “-jar”, “/my-app-1.0-SNAPSHOT.jar”]

          FROM openjdk:8-jre-alpine AS release-alpine
          COPY --from=builder /app/target/my-app-1.0-SNAPSHOT.jar /
          CMD [“java”, “-jar”, “/my-app-1.0-SNAPSHOT.jar”]

          要構(gòu)建特定的鏡像,我們可以使用–target參數(shù):

          time docker build --no-cache --target release-jessie .

          不同的鏡像風(fēng)格(DRY /全局ARG)

          ARG flavor=alpine
          FROM maven:3.6-jdk-8-alpine AS builder

          FROM openjdk:8-jre-$flavor AS release
          COPY --from=builder /app/target/my-app-1.0-SNAPSHOT.jar /
          CMD [“java”, “-jar”, “/my-app-1.0-SNAPSHOT.jar”]

          ARG命令可以指定要構(gòu)建的鏡像。在上面的例子中,我們指定alpine為默認(rèn)的鏡像,但我們也可以在docker build命令中,通過–build-arg flavor=參數(shù)指定鏡像。

          time docker build --no-cache --target release --build-arg flavor=jessie .

          并發(fā)

          并發(fā)在構(gòu)建Docker鏡像時很重要,因為它會充分利用可用的CPU線程。在線性Dockerfile中,所有階段均按順序執(zhí)行。通過多階段構(gòu)建,我們可以讓較小的依賴階段準(zhǔn)備就緒,以供主階段使用它們。

          BuildKit甚至帶來了另一個性能上的好處。如果在以后的構(gòu)建中不使用該階段,則在結(jié)束時將直接跳過這些階段,而不是對其進行處理和丟棄。

          下面是一個示例Dockerfile,其中網(wǎng)站的資產(chǎn)是在一個assets階段中構(gòu)建的:

          FROM maven:3.6-jdk-8-alpine AS builder

          FROM tiborvass/whalesay AS assets
          RUN whalesay “Hello DockerCon!” > out/assets.html

          FROM openjdk:8-jre-alpine AS release
          COPY --from=builder /app/my-app-1.0-SNAPSHOT.jar /
          COPY --from=assets /out /assets
          CMD [“java”, “-jar”, “/my-app-1.0-SNAPSHOT.jar”]

          這是另一個Dockerfile,其中分別編譯了C和C ++庫,并在builder以后使用該階段。

          FROM maven:3.6-jdk-8-alpine AS builder-base


          FROM gcc:8-alpine AS builder-someClib

          RUN git clone … ./configure --prefix=/out && make && make install

          FROM g++:8-alpine AS builder-some CPPlib

          RUN git clone … && cmake …

          FROM builder-base AS builder
          COPY --from=builder-someClib /out /
          COPY --from=builder-someCpplib /out /

          BuildKit應(yīng)用程序緩存

          BuildKit具有程序包管理器緩存的特殊功能。以下是一些緩存文件夾位置的示例:

          包管理器 路徑

          apt /var/lib/apt/lists
          go ~/.cache/go-build
          go-modules $GOPATH/pkg/mod
          npm ~/.npm
          pip ~/.cache/pip

          我們可以將此Dockerfile與上面介紹的在一致的環(huán)境中從源代碼構(gòu)建中介紹的Dockerfile進行比較。這個較早的Dockerfile沒有特殊的緩存處理。我們可以使用–mount=type=cache來做到這一點。

          FROM maven:3.6-jdk-8-alpine AS builder
          WORKDIR /app
          RUN --mount=target=. --mount=type=cache,target /root/.m2 \
              && mvn package -DoutputDirectory=/

          FROM openjdk:8-jre-alpine
          COPY --from=builder /app/target/my-app-1.0-SNAPSHOT.jar /
          CMD [“java”, “-jar”, “/my-app-1.0-SNAPSHOT.jar”]

          BuildKit的安全功能

          BuildKit具有安全功能,下面的示例中,我們使用了–mount=type=secret隱藏了一些機密文件,例如~/.aws/credentials。

          FROM <baseimage>
          RUN …
          RUN --mount=type=secret,id=aws,target=/root/.aws/credentials,required \
          ./fetch-assets-from-s3.sh
          RUN ./build-scripts.sh

          要構(gòu)建此Dockerfile,需要使用–secret參數(shù):

          docker build --secret id=aws,src=~/.aws/credentials

          還有為了提高安全性,避免使用諸如COPY ./keys/private.pem /root .ssh/private.pem之類的命令,我們可以使用BuildKit中的ssh解決此問題:

          FROM alpine
          RUN apk add --no-cache openssh-client
          RUN mkdir -p -m 0700 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
          ARG REPO_REF=19ba7bcd9976ef8a9bd086187df19ba7bcd997f2
          RUN --mount=type=ssh,required git clone [email protected]:org/repo /work && cd /work && git checkout -b $REPO_REF

          要構(gòu)建此Dockerfile,你需要在ssh-agent中加載到你的SSH私鑰。

          eval $(ssh-agent)
          ssh-add ~/.ssh/id_rsa # this is the SSH key default location
          docker build --ssh=default .

          結(jié)論

          本文,我們介紹了使用Docker BuildKit優(yōu)化Dockerfile,并因此加快了鏡像構(gòu)建時間。這些速度的提高,可以幫助我們提高效率和節(jié)省計算能力。


          - END -

          公眾號后臺回復(fù)「加群」加入一線高級工程師技術(shù)交流群,一起交流進步。

           推薦閱讀 

          小團隊如何從零搭建一個自動化運維體系? 
          讓運維簡單高效,輕松搞定運維管理平臺 
          不管你是開發(fā)還是運維,微服務(wù)這些你得知道!
          Kubernetes YAML 學(xué)習(xí),提升編寫能力
          通過Nginx來實現(xiàn)禁止國外IP訪問網(wǎng)站
          2021年的DevOps趨勢預(yù)測
          Kubernetes+Helm+Jenkins 自動化發(fā)布項目
          搭建一套完整的企業(yè)級 K8s 高可用集群(v1.20,kubeadm方式)
          搭建一套完整的企業(yè)級 K8s 高可用集群(v1.20,二進制方式)



          點亮,服務(wù)器三年不宕機

          瀏覽 83
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  粉嫩小泬BBBB免费看WWWW | 美日韩三级片在线观看 | 黄色三级电影网站 | 美女被操免费网站 | 俺去在线一区 |