Dockerfile
入門門檻不高,能夠參照 官方文檔,很快就能上手寫出一個能夠構建出鏡像的Dockerfile
。linux
繼續深究,會發現Dockerfile
實際上是有一些講究的,今天要分享的是Dockerfile
裏的一些規範與技巧。git
咱們以
docker build
爲引子一一道來golang
docker build
命令從Dockerfile
文件和上下文環境context
中構建image
。docker
context
是一個指定位置的路徑path
或者URL
下的一系列文件path
是本地文件系統中的一個目錄。URL是一個Git倉庫的位置。context
會被遞歸的處理,一個路徑path
包含其下的全部子路徑URL
包含對應的倉庫以及全部的子模塊一個簡單的構建命令使用當前的目錄做爲上下文環境
context
bash
docker build .
複製代碼
Dockerfile
默認放在代碼的根路徑,且不帶後綴名工具
代碼的根路徑必須有.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
後,經過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 / 複製代碼