iT邦幫忙

2021 iThome 鐵人賽

DAY 4
0
Software Development

一個新鮮人如何完轉Spring boot與DevOps從0到101系列 第 4

建構 Spring boot 容器 Image

要將自己開發的應用程式容器化,想必需要製作自己的 Image。製作 Image 也是一種藝術,我們要如何讓自己的應用程式製造的 Image 能有更小的資源來使用。

我們都知道 Dockerfile 是建構 image 的檔案。

下面這張圖是 Dockerfile 可以使用的關鍵字

我覺得 cmdENTRYPOINT 這兩個可以理解一下,我有時會搞混哈。在 Dockerfile 中,只能有一個 ENTRYPOINT 或 CMD 指令,如果有多個ENTRYPOINT 或 CMD 指令則以最後一個為準。

  • ENTRYPOINT
    • 往往用於設置容器啟動後的第一個命令,這對一個容器來說往往是固定的。
    • 執行 docker run 如果帶有其他命令參數,不會覆蓋 ENTRYPOINT 指令
    • docker run 的 --entrypoint 可以覆蓋 Dockerfile 中ENTRYPOINT 設置的命令。
  • CMD
    • 往往用於設置容器啟動的第一個命令的默認參數,這對一個容器來說可以是變化的。docker run 往往用於給出替換 CMD 的臨時參數。
    • docker run 如果帶有其他命令參數,將會覆蓋 CMD 指令。
    • 如果在 Dockerfile 中,還有 ENTRYPOINT 指令,則 CMD 指令中的命令將作為 ENTRYPOINT 指令中的命令的參數。

下面是建立一個 Nginx Image 的 Dockerfile 範例

FROM ubuntu:14.04

RUN apt-get update && apt-get install -y nginx

COPY . /var/www/html/

EXPOSE 80

#ENTRYPOINT ["nginx"]
CMD ["nginx", "-g", "daemon off;"]

有了 Dockerfile 後我們就可以建構 Image 了,使用 docker build -t {ImageName}:{tag01} . 建構

使用 docker images 查看建構的 image

REPOSITORY                                          TAG                 IMAGE ID            CREATED             SIZE
nginx                                               v0                  55077273116a        20 minutes ago      222MB

Image 原則上應該越小越好,下面範例則是會把一些類似快取的東西或是歷史紀錄給拔掉

FROM ubuntu:14.04
RUN apt-get update && apt-get install -y nginx \
        && rm -rf /var/lib/apt/lists/*
COPY . /var/www/html/
EXPOSE 80
#ENTRYPOINT ["nginx"]
CMD ["nginx", "-g", "daemon off;"]

最後 Image 減少了一些大小。

REPOSITORY                                          TAG                 IMAGE ID            CREATED             SIZE
nginx                                               v0.1                d17658937ea9        2 minutes ago       209MB

接下來直接給一個建構 Spring boot 的範例,專案如果是用 gradle 建立,應當會使用 gradle 進行建構和測試,所以我們使用了 gradle 進行第一層的建構和測試,當這一個 gradle 建構和測試結果成功後會有一個應用程式的 jar 檔。

這邊我們用運了 multi-stage 方式進行建構,這會使得 CICD 過程更加簡易。後續要運行 Jar 檔的 Image 透過指令(--from)取得前面鍵建構所產生的檔案 (artifacts)。

FROM gradle:4.10.2-slim as builder
USER root
COPY . .
RUN gradle clean build

FROM  adoptopenjdk/openjdk8-openj9:jdk8u181-b13_openj9-0.9.0-slim
COPY --from=builder /home/gradle/build/libs/test-0.0.1-SNAPSHOT.jar /usr/local/test_workspace/test-0.0.1-SNAPSHOT.jar
RUN apt-get update && \
    apt-get install -y tzdata ttf-dejavu fontconfig && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/* && \
    mkdir /usr/local/logs
ENV LANG C.UTF-8
# Timezone 
ENV TZ=Asia/Taipei
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "test-0.0.1-SNAPSHOT.jar"]
  1. 透過 multi-stage 使得 CICD 的過程更加簡易
  2. FROM 的 Image 應當越小越好,也就是基本的環境應該只須包含需要的內容,這會使的 pull Image 速度更快,網路頻寬不會佔資源
  3. 在進行建構時應當將 RUN 關鍵字所安裝的物件,進行快取的清除,使 Image 變得更小
  4. 權限應當做一個設置避免使用 root 最高權限

有關權限設置的內容可參考此鏈結


上一篇
前後端分離
下一篇
幫服務建置佈署流程至 EC2
系列文
一個新鮮人如何完轉Spring boot與DevOps從0到10130

尚未有邦友留言

立即登入留言