Dockerfile基礎指令

## 一、Dockerfile簡介

Dockfile是一種被Docker程序解釋的腳本,Dockerfile由一條一條的指令組成,每條指令對應Linux下面的一條命令,Docker程序將這些Dockerfile指令翻譯真正的Linux命令;Dockerfile有自己書寫格式和支持的命令,Docker程序解決這些命令間的依賴關係,類似於Makefile,Docker程序將讀取Dockerfile,根據指令生成定製的image。

Dockerfile的指令是忽略大小寫的,建議使用大寫,使用#作為註釋,每一行只支持一條指令,每條指令可以攜帶多個參數。

Dockerfile 是一個文本文件,其內包含了一條條的指令(Instruction),每一條指令構建一層, 因此每一條指令的內容,就是描述該層應當如何構建。

## 二、dockerfile指令詳解

**1. FROM**

功能為指定基礎鏡像,並且必須是第一條指令。

除了選擇現有鏡像為基礎鏡像外,Docker 還存在一個特殊的鏡像,名為scratch。這個鏡像 是虛擬的概念,並不實際存在,它表示一個空白的鏡像。

如果你以scratch為基礎鏡像的話,意味著你不以任何鏡像為基礎,接下來所寫的指令將作為鏡像第一層開始構建。

不以任何系統為基礎,直接將可執行文件複製進鏡像的做法並不罕見,比如swarm、coreos/etcd 。對於Linux 下靜態編譯的程序來說,並不需要有操作系統提供運行時支持,所需的一切庫都已經在可執行文件裡了,因此直接 FROM scratch 會讓鏡像體積更加小 巧。使用Go語言開發的應用很多會使用這種方式來製作鏡像,這也是為什麼有人認為 Go 是特別適合容器微服務架構的語言的原因之一。

**2. MAINTAINER**

格式為 MAINTAINER <name>,指定維護者信息。/<name>

**3. RUN**

用來執行命令行命令

- shell格式:RUN ,就像直接在命令行中輸入的命令一樣

- exec格式:RUN ["可執行文件", "參數1", "參數2"],這更像是函數調用中的格式

使用 && 符連接多個命令; \\ 符進行換行。

為防止鏡像臃腫,一定要確保每一層只添加真正需要添加的東西,任何無關的東西都應該清理掉(編譯構建所需要的軟件,所有下載、展開的文件,apt緩存文件等)。

**4. CMD**

- shell格式:CMD

- exec 格式:CMD ["可執行文件", "參數1", "參數2"...]

- 參數列表格式:CMD ["參數1", "參數2"...],提供給 ENTRYPOINT 的默認參數

指定啟動容器時執行的命令,每個 Dockerfile 只能有一條 CMD 命令。如果指定了多條命令,只有最後一條會被執行。

如果用戶啟動容器時候指定了運行的命令,則會覆蓋掉 CMD 指定的命令。

Docker不是虛擬機,容器中的應用都應該以前臺執行,而不是像虛擬機、物理機裡面那樣,用upstart/systemd去啟動後臺服務,容器內沒有後臺服務的概念。

CMD service nginx start ,如果這樣寫會出現容器執行後立即退出了,這主要是因為沒搞明白前臺和後臺的概念,沒有區分容器和虛擬機的差異,對於容器而言,其啟動程序就是容器應用進程,容器就是為了主進程而存在的,主進程退出,容器就失去了存在的意義,進而退出,其他輔助進程不是他關心的內容。 上述命令可以理解為 CMD[ "sh", "-c", "service nginx start"] ,因此主進程是sh ,sh結束,主進程退出,自然容器也會退出。正確的做法是 CMD [ "nginx", "-g", "daemon off;" ]

**5. ENTRYPOINT**

兩種格式:

- ENTRYPOINT ["executable", "param1", "param2"]

- ENTRYPOINT command param1 param2(shell中執行)

配置容器啟動後執行的命令,ENTRYPOINT 在運行時也可以替代,不過比CMD要略顯繁瑣,需要通過docker run的參數 -entrypoint來指定。

**當指定了ENTRYPOINT後,CMD的含義就發生了改變:**

如果CMD中不是完整的命令,則將CMD的內容作為參數傳給ENTRYPOINT指令,換句話說實際執行時,將變為 ENTRYPOINT CMD。

如果我們在Dockerfile種同時寫了ENTRYPOINT和CMD,並且CMD是一個完整的指令,那麼它們兩個會互相覆蓋,誰在最後誰生效。

每個 Dockerfile 中只能有一個 ENTRYPOINT,當指定多個時,只有最後一個起效。

**6. EXPOSE**

- EXPOSE [...]

功能為暴漏容器運行時的監聽端口給外部,但是EXPOSE並不會使容器訪問主機的端口,如果想使得容器與主機的端口有映射關係,必須在容器啟動的時候加上 -P參數。

-P:大寫P為自動映射,會將EXPOSE暴露出來的端口隨機映射到宿主機的端口上,如果沒有暴露端口,就不會有映射。

-p:小寫p為手動映射,需要自己指定宿主機的端口和容器的端口,形式為:

-p宿主機端口:容器端口

(1)無論有沒有暴露端口、自動映射或者手動映射,宿主機都可以通過容器ip+port(port隨容器內部服務監聽端口改變而改變)端口訪問服務;

(2)要通過宿主機ip+端口的方式訪問服務,宿主機的端口必須與容器端口有映射關係;

(3)如果沒有暴露端口,-P自動映射不會映射任何端口,-p可以指定宿主機端口和容器端口形成映射。

**7. ENV**

1. ENV

2. ENV = ...

兩者的區別就是第一種是一次設置一個,第二種是一次設置多個

下列指令可以支持環境變量展開:

**ADD、COPY 、ENV、EXPOSE 、LABEL 、USER 、WORKDIR 、VOLUME 、STOPSIGNAL、ONBU ILD**

**使用環境變量方式: $環境變量**

**8. COPY**

將從構建上下文目錄中的文件或者目錄複製到新的一層的鏡像內的位置。

可以是容器內的絕對路徑,也可以是相對於工作目錄的相對路徑(工作目錄可以用WORKDIR指令來指定)。目標路徑不需要事先創建,如果目錄不存在會在複製文件前先行創建缺失目錄。

此外,還需要注意一點,使用COPY指令,源文件的各種元數據都會保留。比如讀、寫、執 行權限、文件變更時間等。這個特性對於鏡像定製很有用。特別是構建相關文件都在使用Git 進行管理的時候。

- COPY:...

- COPY: ["",... ""]

```sh

COPY src1 \\

src2 \\

WORKDIR/

```

執行上述操作會發現將src1 src2 下的文件全部複製到WORKDIR下,並沒有複製目錄src1 src2,官方對於COPY解釋是:

>Note: The directory itself is not copied, just its contents.

即:COPY指令拷貝一個文件夾只會拷貝文件夾的內容。

上述指令可以這樣寫:

```sh

COPY src1 \\

src2 \\

WORKDIR/src

```

這樣將COPY的文件,放在了新創建的src目錄下。

**9. ADD**

ADD指令和COPY的格式和性質基本一致,不過可以是一個URL,同時如果源文件是一個壓縮文件,ADD會自動執行解壓縮。

因此在COPY 和ADD指令中選擇的時候,可以遵循這樣的原則,所有的文件複製均使用COPY指令,僅在需要自動解壓縮的場合使用ADD 。

**10. VOLUME**

- VOLUME ["", ""...]

容器運行時應該儘量保持容器存儲層不發生寫操作,對於數據庫類需要保存 動態數據的應用,其數據庫文件應該保存於卷(volume)中。

為了防止運行時用戶忘記將動態文件所保存目錄掛載為卷,在 Dockerfile中,我們可以事先指定某些目錄掛載為匿名卷,這樣在運行時如果用戶不指定掛載,其應用也可以正常運行,不會向容器存儲層寫入大量數據。

**如何使用:**

在Dockerfile中定義匿名卷,運行容器時,使用參數 **-v 宿主機目錄:匿名卷** 進行掛載,實現了數據持久化。

**11. WORKDIR**

- WORKDIR

使用WORKDIR指令可以來指定工作目錄(或者稱為當前目錄),以後各層的當前目錄就被改為指定的目錄,如該目錄不存在,WORKDIR 會幫你建立目錄。

可以使用多個 WORKDIR 指令,後續命令如果參數是相對路徑,則會基於之前命令指定的路徑。

```sh

WORKDIR /a

WORKDIR b

WORKDIR c

RUN pwd

則最終路徑為 /a/b/c。

```

**12. USER**

- USER

USER是改變之後層的執行RUN ,CMD以及ENTRYPOINT這類命令的身份。USER只是幫助你切換到指定用戶而已,這個用戶必須是事先建立好的,否則無法切換。

**13. ONBUILD**

- ONBUILD

ONBUILD是一個特殊的指令,它後面跟的是其它指令,比如RUN ,COPY等,而這些指令,在當前鏡像構建時並不會被執行。只有當以當前鏡像為基礎鏡像,去構建下一級鏡像的時候才會被執行。

Dockerfile中的其它指令都是為了定製當前鏡像而準備的,唯有ONBUILD是為了幫助別人定製自己而準備的。


分享到:


相關文章: