手把手教你寫一個完美的Golang Dockerfile

引言

對於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.modgo.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文件吧。

相關文章
相關標籤/搜索