Dockerfile規範與技巧

說在前面

Dockerfile入門門檻不高,能夠參照 官方文檔,很快就能上手寫出一個能夠構建出鏡像的Dockerfilelinux

繼續深究,會發現Dockerfile實際上是有一些講究的,今天要分享的是Dockerfile裏的一些規範與技巧。git

咱們以docker build爲引子一一道來golang

docker build

docker build命令從Dockerfile文件和上下文環境context中構建imagedocker

  • 構建的上下文環境context是一個指定位置的路徑path或者URL下的一系列文件
  • 路徑path是本地文件系統中的一個目錄。URL是一個Git倉庫的位置。
  • 構建的上下文環境context會被遞歸的處理,一個路徑path包含其下的全部子路徑
  • URL包含對應的倉庫以及全部的子模塊

一個簡單的構建命令使用當前的目錄做爲上下文環境contextbash

docker build .
複製代碼

Dockerfile 路徑

Dockerfile默認放在代碼的根路徑,且不帶後綴名工具

.dockerignore

代碼的根路徑必須有.dockerignore文件,且.dockerignore文件內容中必須忽略.git目錄,範例以下:ui

# comment
.git
*/temp*
*/*/temp*
temp?
*.md
!README.md
複製代碼
Rule Behavior
# comment 註釋
/temp 如 /somedir/temporary.txt
//temp* 如 /somedir/subdir/temporary.txt
temp? 如 tempa、tempb
*.md !README.md 除了README.md以外的全部md文件

更多規則可參考 Docker官方文檔spa

Dockerfile 技巧

在代碼根目錄放置Dockerfile後,經過docker build -f Dockerfile .能夠構建鏡像,鏡像中須要包含這次的構建產物,因此須要在Dockerfile中增長編譯打包步驟,此步驟只是爲了作編譯打包使用,勢必不能影響最終鏡像構建的分層,因此Dockerfile須要採用多個 FROM 指令的方式。code

  • 多個From指令的意義:

多個FROM指令並非爲了生成多根的層關係,最後生成的鏡像,仍以最後一條FROM爲準,以前的FROM會被拋棄,那麼以前的FROM又有什麼意義呢?server

每一條FROM指令都是一個構建階段,多條FROM就是多階段構建,雖然最後生成的鏡像只能是最後一個階段的結果,可是,可以將前置階段中的文件拷貝到後邊的階段中,這就是多階段構建的最大意義。

最大的使用場景是將編譯環境和運行環境分離,好比,以前咱們須要構建一個Go語言程序,那麼就須要用到go命令等編譯環境,咱們的Dockerfile多是這樣的:

# Go語言環境基礎鏡像
FROM golang:1.10.3

# 將源碼拷貝到鏡像中
COPY server.go /build/ 
# 指定工做目錄
WORKDIR /build 
# 編譯鏡像時,運行 go build 編譯生成 server 程序
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOARM=6 go build -ldflags '-w -s' -o server 
# 指定容器運行時入口程序 server
ENTRYPOINT ["/build/server"] 複製代碼

基礎鏡像golang:1.10.3是很是龐大的,由於其中包含了全部的Go語言編譯工具和庫,而運行時候咱們僅僅須要編譯後的server程序就好了,不須要編譯時的編譯工具,最後生成的大致積鏡像就是一種浪費。

新的解決方案,編譯階段與運行階段直接在一個Dockerfile就能夠解決:

# 編譯階段
FROM golang:1.10.3

COPY server.go /build/ 
WORKDIR /build 
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOARM=6 go build -ldflags '-w -s' -o server 
# 運行階段
FROM scratch

# 從編譯階段的中拷貝編譯結果到當前鏡像中
COPY --from=0 /build/server / 
ENTRYPOINT ["/server"] 複製代碼

這個Dockerfile玄妙之處就在於COPY指令的--from=0參數,從前邊的階段中拷貝文件到當前階段中,多個FROM語句時,0表明第一個階段。除了使用數字,還能夠給階段命名,好比:

# 編譯階段 命名爲 builder
FROM golang:1.10.3 as builder

# ... 省略

# 運行階段
FROM scratch

# 從編譯階段的中拷貝編譯結果到當前鏡像中
COPY --from=builder /build/server / 複製代碼
相關文章
相關標籤/搜索