在上一章提到了用docker來建立服務所需的資料庫,但是服務還是得在本機build然後在本機建立,
既然都使用docker了,那麼是否也能把服務建立成image,透過docker建立起來呢?
在這種情況下,可以透過Dockerfile設定好要如何建立服務的image,再靠docker指令可以建立好服務的image了。
在編寫Dockerfile的時候,需要在內部定義好build這個服務所需要的資訊,下面是這次的範例:
FROM golang:1.14.8-alpine3.11 AS builder
LABEL maintainer="jim"
ENV GO111MODULE=on
ADD ./ /go/src/webserver
RUN cd /go/src/webserver && go build -mod vendor
首先,要先定義build服務的image,由於我們要先將服務build起來,
一開始FROM是指定要使用的IMAGE,
在這邊會先用golang1.14.8的版本來當作服務的建立image(builder)
LABEL則是設定image的資訊,像是作者的email或版本等等,
原本還有一個叫做維護者(MAINTAINER)的指令,但是建議向範例一樣用LABEL去標記維護者,
ENV則是設定環境變數,這邊由於是使用go mod建立,因此要先將GO111MODULE設為on,
ADD 是將./ 也就是本機當前目錄加入到image的目錄(/go/src/webserver),
RUN 則是會執行指令,以範例來說,就是切換到目錄(/go/src/webserver),然後下go build指令,
在這邊因為使用了go mod所以有特別指定mod vendor,
這樣子用來建立服務的部分就完成了,但是要讓服務啟動還需要另外的步驟,
因此再來要介紹運行服務用的部分。
運行image的部分如下,在此先說明,上下兩個請設定在同一個Dockerfile內,不然無法正確運作:
# final stage
FROM alpine:3.11.6
RUN mkdir -p app
COPY --from=builder /go/src/webserver/webserver ./
RUN apk add --no-cache tzdata
CMD ["./webserver "]
由於我們已經將服務build好了,接下來就可以選擇較為小型的image作為運行用image,
前面兩行的FROM跟RUN已經說明過了,這邊就不再特別說明,
第三行的COPY,是將剛剛builder內建立好的執行檔複製到運行用的image內,
這也是為什麼上面提到這兩段必須放在同一個Dockerfile內,不然前面定義的builder這邊就無法辨識了,
第四行的RUN則是如果go內有用到timezone,就需要那個tzdata,不然會有問題,
最後的CMD則是寫說建立好容器後要運行的指令。
寫好Dockerfile後,要建立起image,只需要下
docker build -t webserver .
這樣就可以建立起名為webserver的image了,如果Dockerfile放在別的路徑,則最後的.就要換成該路徑。