昨天我們介紹了怎麼使用 Docker Client 並使用他人建立的 Image 再本地部署服務,而今天我們會將一個 Java 的 API 服務打包成 Container Image,並推送到 Container Registry。
將 Java 原始碼 cloen 到本地端
git clone https://github.com/YihongGao/iThome_30Day_2023.git
cd iThome_30Day_2023
git switch -c D4
切換到 demo 專案下
cd projects/demo
將 Java 原始碼編譯並打包成 JAR file
JAR file 是一種 Java 部署和分發的常用文件格式,通常就是一個服務或函式庫,再這裡 JAR file 的內容就是要打包近 Container Image 的 API 服務。
./mvnw clean package
ls target/demo.jar
當要打包的服務(JAR)準備好之後,我們需要一個叫 Dockerfile 的檔案,來定義建構 Container Image 的過程。
這邊直接看我預先寫好的 Dockerfile 內容,檔案就在 projects/demo 目錄下
# 使用 OpenJDK 17 作為基本映像
FROM openjdk:17
# 在容器中創建一個目錄以存放應用程序 JAR 文件
WORKDIR /app
# 複製本地的 JAR 文件到容器中
COPY target/demo.jar /app/application.jar
# 定義容器啟動命令,運行 JAR 文件
CMD ["java", "-jar", "application.jar"]
# 暴露 8080 端口
EXPOSE 8080
我們依序看 Dockerfile 中每一行做了些什麼事情
FROM openjdk:17
代表我選擇使用 openjdk:17
這個 Image 來當作我的 Base Image,因為 JAR file 的運行環境需要有 JRE 這函式庫,而 openjdk:17
符合我的服務運行的需求。
簡單來說 Base Image 你可以依據你的服務依賴的函式庫來選擇 Base Image,如果你的服務是使用 node.js,你可能會選擇 node:lts
當作 Base Image。
WORKDIR /app
使用 /app
目錄作為當前的工作目錄,確保後續的指令都在 /app
下進行,提升可讀性與維護性,/app
能替換成你想要的目錄名稱。
COPY target/demo.jar /app/application.jar
將我們先前打包好的 JAR file 複製到 Container 內,所以執行到這步驟時,Container 的內容就已經包含了 Base Image + JAR file。
因為我們使用了 WORKDIR
指定當前目錄為 /app
,且透過 COPY
將本地 JAR file 複製到 /app
並使用新檔案名稱 application.jar
,所以容器中至少有以下目錄結構
/
└── app <-- [當前目錄]
└── application.jar
EXPOSE 8080
定義此容器可以將 8080 PORT 映射到主機上,後續 docker run 時才能用-p 參數進行轉發
CMD ["java", "-jar", "application.jar"]
定義容器啟動時執行的指令,以這個案例來說等同
java -jar application.jar
我們來試著透過 Docker Client 建立 Container Image
確定你的終端機 projects/demo
的目錄下
執行 docker build
docker build -t demo-image:v1 .
指令中
-t demo-image:v1
代表我希望該 Container Image 的名稱為 demo-image,且 tag 為 v1。當未來這服務有更新時,能使用同一個名稱,調整 tag 為 v2,方便區分不同版本的 Container Image。
運行結果:
上傳 Container Registry 之前,先在本地運行做個簡單的測試。
# 使用 demo-image:v1 來建立 Container instance
docker run -p 8080:8080 demo-image:v1
# 呼叫 API
curl localhost:8080
運行結果
收到 API 服務返回 "Hello, welcome to use the container." 的訊息,代表建構成功。
這邊為了讀者自行實作方便,範例為上傳至免費的 DockerHub
此範例我用
demo-image
當 repository 名稱
docker login
docker tag demo-image:v1 ${你的 docker 帳號}/${你的repository名稱}:v1
docker push ${你的 docker 帳號}/${你的repository名稱}:v1
運行結果:今天我們使用了 Dockerfile 來定義如何建置 Container Image,並透過 Docker client 建立了自己的 Container Image,而該 Container 的內容包含了以下內容
這就達到了 一致的環境、依賴性管理 的好處,透過交付 Container 來部署服務,不需太擔心運行的環境差異。
最後也透過 docker tag
與 docker push
,將 Image 推送到 Container Registry,讓遠端伺服器或其他人能透過 docker pull
取得該 image。
注意:若你的 Container 不想給外人取得,DockerHub Repository 務必選擇 private