選單
GSS 技術部落格
在這個園地裡我們將從技術、專案管理、客戶對談面和大家分享我們多年的經驗,希望大家不管是喜歡或是有意見,都可以回饋給我們,讓我們有機會和大家對話並一起成長!
若有任何問題請來信:gss_crm@gss.com.tw
2 分鐘閱讀時間 (307 個字)

每日小知識#5 - dockerfile

mockuuups-angle-view-of-microsoft-surface-laptop-mockup

不知道各位在團隊已經 Dockerize 一陣子以來,有沒有認真探究過 Dockerfile 究竟是在做什麼呢?
沒有也沒關係,今天就由本人來小小講解一下 Dockerfile 的奧妙之處吧。

如果已經忘記前一篇,或還沒試過 docker commit 的各位,先去玩一下體驗一下。

Dockerfile 說穿了其實就是 自動化 標準化 docker commit 在做的事。試想如果每一次針對 container 可讀寫的那一層做了什麼事都要 手動 下一次 docker commit 那會有多麻煩。

就如同初學 java 的時候我們總會經過以下的步驟:

  1. 撰寫程式碼
  2. 透過 javac 將原始碼編譯成 bytecode
  3. 設定 MANIFEST 定義程式進入點的 main 在哪
  4. 透過 java -jar 編譯出 executable jar

撰寫 Dockerfile 的時候其實也有 類似的步驟 :

  1. 建立一個名為 Dockerfile 的檔案 (不用副檔名)
  2. 選好你的 base image 並放在 FROM 那一列
  3. 透過 COPY/RUN/ENV/ARG … 等逐步建立最後想要的 image layers
  4. 定義 ENTRYPOINT AND/OR CMD 傳入預設的參數,作為 container 建立時的程式進入點。
  5. 透過 docker build -t ooo xxx 建立 image

以上其實有三個重點:

  1. 前面的小知識有提過,每一條指令都會產一個暫時的 container,把該做的事做了之後產出一個 image layer。既然如此,那些安裝某些套件或是工具或執行某些指令(e.g. 調整時區)的指令最好是用 && 串在一起,否則你的 image 結果就會是非常多層的 layer,就官方文件的說明這會造成一些問題(除了佔很大的空間之外)
  2. image name + tag,也就是上述 5. 中的 ooo,這個部份最好是能夠統一,且 tag 也符合當下版控的 release(e.g. api-gateway:k8s-0.0.1)
  3. Build context,也就是上述 5. 中的 xxx,這個部份盡量透過 .dockerignore 將不必要的檔案排除掉,否則指定路徑下所有的檔案都會被掃到 cache,整個 build 過程就會變得很慢很冗長,就有點失去微服務輕薄短小的特性了。

一個 Spring boot Application 的 Dockerfile 範例如下:

FROM openjdk:8-jdk-alpine

ENV GOSU_VERSION 1.12
RUN set -eux; \
	\
	apk add --no-cache --virtual .gosu-deps \
		ca-certificates \
		dpkg \
		gnupg \
	; \
	\
	dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \
	wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \
	wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \
	\
	# verify the signature
	export GNUPGHOME="$(mktemp -d)"; \
	gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \
	gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \
	command -v gpgconf && gpgconf --kill all || :; \
	rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \
	\
	# clean up fetch dependencies
	apk del --no-network .gosu-deps; \
	\
	chmod +x /usr/local/bin/gosu; \
	# verify that the binary works
	gosu --version; \
	gosu nobody true

ARG JAR_NAME=app.jar

ARG HOME_DIR=/home/java-app

# Setting timezone
ENV TZ=Asia/Taipei

ENV JAR_PATH=$HOME_DIR/$JAR_NAME

RUN apk --update add tzdata && \
    cp /usr/share/zoneinfo/Asia/Taipei /etc/localtime && \
    apk del tzdata && \
    rm -rf /var/cache/apk/*

RUN set -eux && \
    addgroup --gid 9999 java-app && \
    adduser -S -u 9999 -g java-app -h $HOME_DIR -s /bin/sh -D java-app && \
    chown -R java-app:java-app $HOME_DIR

COPY --chown=java-app:java-app ./target/*-SNAPSHOT.jar $JAR_PATH

COPY ./entrypoint.sh entrypoint.sh

RUN chmod +x entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"] 

針對 Dockerfile 還有更多興趣的人可以參考官方的 best practice

React Context
每日小知識#4 - Docker Image

相關文章

 

評論

尚無評論
已經注冊了? 這裡登入
Guest
2024/05/15, 週三

Captcha 圖像