對於dockerfile而言,何爲完美? 我認爲應該知足如下三點:linux
話說不說,直接上拿走可用的Dockerfile。golang
FROM golang:1.13.5-alpine3.10 AS builder
WORKDIR /build RUN adduser -u 10001 -D app-runner
ENV GOPROXY https://goproxy.cn
COPY go.mod . COPY go.sum . RUN go mod download
COPY . . RUN CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -a -o your-application .
FROM alpine:3.10 AS final
WORKDIR /app COPY --from=builder /build/your-application /app/ #COPY --from=builder /build/config /app/config
COPY --from=builder /etc/passwd /etc/passwd COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
USER app-runner
ENTRYPOINT ["/app/your-application"] 複製代碼
首先,這個dockerfile分爲builder和final兩部分。docker
builder選擇了golang:1.13.5-alpine3.10
做爲編譯的基礎鏡像,相比於golang:1.13
, 一方面是由於它體積更小,另外一方面是我發現golang:1.13
的編譯結果,在alpine:3.10
中會報not found
的錯誤,雖然說有人提供了其它的解決方案,可是能直接避免,爲啥不避免呢。shell
RUN adduser -u 10001 -D app-runner
複製代碼
接着是建立了一個app-runner
的用戶, -D
表示無密碼。緩存
此用戶的信息是是須要拷到final中,做爲應用程序的啓動用戶。這是爲了不使用container中的默認用戶root
,那但是有安全漏洞的,詳細解釋,能夠參考這篇medium上的文章Processes In Containers Should Not Run As Root安全
再下面的四行,bash
ENV GOPROXY https://goproxy.cn
COPY go.mod .
COPY go.sum .
RUN go mod download
複製代碼
是配置了國內的代理,安裝依賴包了。這裏用go mod download
的好處是下次構建鏡像文件時,當go.mod
和go.sum
沒有改變時,它是有緩存的,能夠避免重複下載依賴包,加快構建。app
builder的最後,就是把當前目錄的文件拷過去,編譯代碼了。ui
COPY . .
RUN CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -a -o your-application .
複製代碼
final選擇了alpine:3.10
,一方面是體積小,只有5m;另外一方面也是和構建鏡像的alpine版本保持一致。spa
接下來幾行沒啥說的,就是把構建結果、配置文件(有的話)和用戶的相關文件拷過去。
下面的這步必定不要忘記了,
USER app-runner
複製代碼
沒有它,container啓動時就是用root用戶啓動了!!! 若是被攻擊了,那黑客但是就有root權限了(不要問我爲啥會被攻擊)。
最後,設置一個ENTRYPOINT
,完事!
若是你程序的啓動過程比較複雜,或者是要在啓動時根據環境變量的值作不一樣的操做,那仍是寫個shell文件吧。