Dockerfile

 
3、Dockerfile 
 
dockerfile 是一個文本格式的配置文件, 用戶可使用 Dockerfile 來快速建立自定義的鏡像。
鏡像的定製實際上就是定製每一層所添加的配置、文件。若是咱們能夠把每一層修改、安裝、構建、操做的命令都寫入一個腳本,用這個腳原本構建、定製鏡像,那麼以前說起的沒法重複的問題、鏡像構建透明性的問題、體積的問題就都會解決。
所謂定製鏡像,那必定是以一個鏡像爲基礎,在其上進行定製。
 

 
指令:
 
包括 「配置指令" (配置鏡像信息)和 「操做指令" (具體執行操做)
 
配置指令:
 
ARG (定義建立鏡像過程當中使用的變量)
格式:ARG <參數名>[=<默認值>]
構建參數和 ENV 的效果同樣,都是設置環境變量。所不一樣的是,ARG 所設置的構建環境的環境變量,在未來容器運行時是不會存在這些環境變量的。
Dockerfile 中的 ARG 指令是定義參數名稱,以及定義其默認值。該默認值能夠在構建命令 docker build 中用  --build-arg <參數名>=<值> 來覆蓋。
 
 
FROM:(指定所建立鏡像的基礎鏡像,必備)*
格式:FROM <鏡像> [AS <別名>]
必須是第一條指令,若是一個Dockerfile中建立多個鏡像時,可使用多個FROM指令(每一個鏡像一次)。
除了選擇現有鏡像爲基礎鏡像外,Docker 還存在一個特殊的鏡像,名爲 scratch。這個鏡像是虛擬的概念,並不實際存在,它表示一個空白的鏡像。
若是你以 scratch 爲基礎鏡像的話,意味着你不以任何鏡像爲基礎,接下來所寫的指令將做爲鏡像第一層開始存在。
 
 
LABEL:(添加鏡像元數據標籤信息)
格式:LABEL <鍵>=<值> <鍵>=<值> ...
如:LABEL author="xxx"  date="xxx"
 
 
EXPOSE(聲明鏡像內服務監聽的端口)
格式: EXPOSE <端口1> [<端口2>/<協議>...]
EXPOSE 指令是聲明運行時容器提供服務端口,這只是一個聲明,在運行時並不會由於這個聲明應用就會開啓這個端口的服務(即不會自動完成端口映射)。
在 Dockerfile 中寫入這樣的聲明有兩個好處,一個是幫助鏡像使用者理解這個鏡像服務的守護端口,以方便配置映射;另外一個用處則是在運行時使用隨機端口映射時,也就是 docker run -P(大寫) 時,會自動隨機映射 EXPOSE 的端口。
要將 EXPOSE 和在運行時使用 -p <宿主端口>:<容器端口> 區分開來。-p,是映射宿主端口和容器端口,換句話說,就是將容器的對應端口服務公開給外界訪問,而 EXPOSE 僅僅是聲明容器打算使用什麼端口而已,並不會自動在宿主進行端口映射。
 
 
ENV(設置環境變量)
格式有兩種:
  • ENV <key> <value>
  • ENV <key1>=<value1> <key2>=<value2>...
不管是後面的其它指令,如 RUN,仍是運行時的應用,均可以直接使用這裏定義的環境變量。在鏡像啓動的容器中也會存在。指令指定的環境變量在運行時能夠被覆蓋掉, 如 docker run --env <key>=<value> built_image 。
注意當一條 ENV 指令中同時爲多個環境變量賦值而且值也是從環境變量讀取時, 會爲變量都賦值後再更新。
如:
ENV NODE_VERSION 7.2.0
RUN curl -SLO " https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz"
下列指令能夠支持環境變量展開: ADD、COPY、ENV、EXPOSE、LABEL、USER、WORKDIR、VOLUME、STOPSIGNAL、ONBUILD。
 
 
ENTRYPOINT(指定鏡像的默認入口命令)
格式有兩種:
  • ENTRYPOINT ["executable", "param1", "param2"]  exec調用執行;
  • ENTRYPOINT command param1 param2    shell中執行;
ENTRYPOINT 的目的和 CMD 同樣,都是在指定容器啓動程序及參數。
該入口命令令會在啓動容器時做爲根命令執行, 全部傳人值做爲該命令的參數。
每一個 Dockerfile 中只能有一個 ENTRYPOINT, 當指定多個時, 只有最後一個起效。
在運行時, 能夠被 --entrypoint 參數覆蓋掉, 如 docker run --entrypoint。
 
 
VOLUME(建立一個數據卷掛載點)
格式爲:
  • VOLUME ["<路徑1>", "<路徑2>"...]
  • VOLUME <路徑>
對於數據庫類須要保存動態數據的應用,其數據庫文件應該保存於卷中, 爲了防止運行時用戶忘記將動態文件所保存目錄掛載爲卷,在 Dockerfile 中,咱們能夠事先指定某些目錄掛載爲匿名卷,這樣在運行時若是用戶不指定掛載,其應用也能夠正常運行,不會向容器存儲層寫入大量數據。
 
 
USER(指定運行容器時的用戶名或UID)
格式:USER <用戶名>[:<用戶組>]
USER 指令和 WORKDIR 類似,都是改變環境狀態並影響之後的層。WORKDIR 是改變工做目錄,USER 則是改變以後層的執行 RUN, CMD 以及 ENTRYPOINT 這類命令的身份。
這個用戶必須是事先創建好的,不然沒法切換。
要臨時獲取管理員權限可使用 gosu 命令
 
 
WORKDIR (爲後續的RUN、CMD、ENTRYPOINT 指定配置工做目錄)
格式: WORKDIR <工做目錄路徑>
能夠來指定工做目錄(或者稱爲當前目錄),之後各層的當前目錄就被改成指定的目錄,如該目錄不存在,WORKDIR 會幫你創建目錄。
可使用多個 WORKDIR 指令,後續命令若是參數是相對路徑, 則會基於以前命令指定的路徑(合併路徑) 。爲了不出錯,推薦 WORKDIR 指令中只使用絕對路徑。
 
 
ONBUILD(指定當基於所生成鏡像建立子鏡像時,自動執行的操做指令)
格式:ONBUILD <其它指令>
ONBUILD 是一個特殊的指令,它後面跟的是其它指令, 而這些指令,在當前鏡像構建時並不會被執行。只有當以當前鏡像爲基礎鏡像,去構建下一級鏡像的時候纔會被執行。
Dockerfile 中的其它指令都是爲了定製當前鏡像而準備的,惟有 ONBUILD 是爲了幫助別人定製本身而準備的。
 
 
HEALTHCHECK(配置所啓動容器如何進行健康檢查)
格式:
  • HEALTHCHECK [選項] CMD <命令>:設置檢查容器健康情況的命令
  • HEALTHCHECK NONE:若是基礎鏡像有健康檢查指令,使用這行能夠屏蔽掉其健康檢查指令
HEALTHCHECK 指令是告訴 Docker 應該如何進行判斷容器的狀態是否正常。
 
 
STOPSIGNAL(指定所建立鏡像啓動的容器接收退出的信號值)
STOPSIGNAL signal
 
 
SHELL(指定其餘命令使用 shell 時的默認 shell 類型)
SHELL ["executable", "parameters"]
默認值爲 ["/bin/sh","-c"]
對於 windows 系統, Shell 路徑中使用了「\」做爲分隔符,建議在 Dockerfile 開頭添- 加# escap= ' 來指定轉義符
 
 
操做指令:
 
RUN(運行指定命令)
 
其格式有兩種:
一、shell 格式: RUN <命令>,就像直接在命令行中輸入的命令同樣。
二、exec 格式: RUN ["可執行文件", "參數1", "參數2"],這更像是函數調用中的格式。
每個 RUN 的行爲,就和手工創建鏡像的過程同樣:新創建一層,在其上執行這些命令,執行結束後,commit 這一層的修改,構成新的鏡像。
Dockerfile 中每個指令都會創建一層,每個 RUN 都是啓動一個容器、執行命令、而後提交存儲層文件變動。
鏡像是多層存儲,每一層的東西並不會在下一層被刪除,會一直跟隨着鏡像。 鏡像構建時,必定要確保每一層只添加真正須要添加的東西,任何無關的東西都應該清理掉。
Union FS 是有最大層數限制的,好比 AUFS,曾經是最大不得超過 42 層,如今是不得超過 127 層。
Dockerfile 支持 Shell 類的行尾添加 \ 的命令換行方式,以及行首 # 進行註釋的格式。
 
 
CMD(指定啓動容器時默認執行的命令)
CMD 指令的格式和 RUN 類似
格式:
  • shell 格式:CMD <命令>
  • exec 格式:CMD ["可執行文件", "參數1", "參數2"...]
  • CMD ["參數1", "參數2"...] 提供給 ENTRYPOINT的默認參數
在指令格式上,通常推薦使用 exec 格式,這類格式在解析時會被解析爲 JSON 數組,所以必定要使用雙引號 ",而不要使用單引號。
每一個 Dockerfile 只能有一條 CMD 命令,若是指定了多條命令,只有最後一條會被執行。
若是用戶啓動容器時候手動指定了運行的命令(做爲 run 命令的參數),則會覆蓋掉CMD 指定的命令。
Docker 不是虛擬機,容器就是進程。既然是進程,那麼在啓動容器的時候,須要指定所運行的程序及參數。CMD 指令就是用於指定默認的容器主進程的啓動命令的。
Docker 不是虛擬機,容器中的應用都應該之前臺執行,而不是像虛擬機、物理機裏面那樣,用 systemd 去啓動後臺服務,容器內沒有後臺服務的概念。
 
 
ADD(添加內容到鏡像,更高級的複製文件)
格式: ADD  <源路徑>  <目標路徑> 
ADD 指令和 COPY 的格式和性質基本一致。可是在 COPY 基礎上增長了一些功能。
 <源路徑> 能夠是 Dockerfile 所在目錄的一個相對路徑(文件或目錄);也能夠是一個URL ;還能夠是一個 tar 文件。若是 <源路徑> 爲一個 tar 壓縮文件的話,壓縮格式爲 gzip, bzip2 以及 xz 的狀況下,ADD 指令將會自動解壓縮這個壓縮文件到 <目標路徑> 去。
 
原則: 儘量的使用 COPY, 最適合使用 ADD 的場合,就是所說起的須要自動解壓縮的場合。
 
 
COPY(複製內容到鏡像)
格式:
  • COPY [--chown=<user>:<group>] <源路徑>... <目標路徑>
  • COPY [--chown=<user>:<group>] ["<源路徑1>",... "<目標路徑>"]
<源路徑> 能夠是多個,甚至能夠是通配符,其通配符規則要知足 Go 的  filepath.Match 規則,且指的是上下文(context) 目錄下的路徑,所以 COPY 這類指令中的源文件的路徑都是相對路徑。
COPY 指令將從構建上下文目錄中 <源路徑> 的文件/目錄複製到新的一層的鏡像內的 <目標路徑> 位置。
<目標路徑> 能夠是容器內的絕對路徑,也能夠是相對於工做目錄的相對路徑(工做目錄能夠用 WORKDIR 指令來指定)。目標路徑不須要事先建立,若是目錄不存在會在複製文件前先行建立缺失目錄。
使用 COPY 指令,源文件的各類元數據都會保留。好比讀、寫、執行權限、文件變動時間等。
 

 
建立鏡像
 
基本的格式: docker build [OPTIONS]  PATH |URL | -
 
該命令將讀取指定路徑下(包括子目錄)的 Dockerfile ,並將該路徑下全部數據做爲上下文( Context )發送給 Docker 服務端 Docker 服務端在校驗 Dockerfile 格式經過後,逐條執行其中定義的指令,碰到 ADD 、COPY、 RUN 指令會生成一層新的鏡像。 最終若是建立鏡像成功,會返回最終鏡像的 ID。要指定生成鏡像的標籤信息,能夠經過 -t 選項
 
docker build 的工做原理:
 
Docker 在運行時分爲 Docker 引擎(也就是服務端守護進程)和客戶端工具。Docker 的引擎提供了一組 REST API,被稱爲  Docker Remote API,而如 docker 命令這樣的客戶端工具,則是經過這組 API 與 Docker 引擎交互,從而完成各類功能。
 
雖然表面上咱們好像是在本機執行各類 docker 功能,但實際上,一切都是使用的遠程調用形式在服務端(Docker 引擎)完成。也由於這種 C/S 設計,讓咱們操做遠程服務器的 Docker 引擎變得垂手可得。
 
docker build 命令構建鏡像,其實並不是在本地構建,而是在服務端,也就是 Docker 引擎中構建的。 當構建的時候,用戶會指定構建鏡像上下文的路徑,docker build 命令得知這個路徑後,會將路徑下的全部內容打包,而後上傳給 Docker 引擎。這樣 Docker 引擎收到這個上下文包後,展開就會得到構建鏡像所需的一切文件。
 
在默認狀況下,若是不額外指定 Dockerfile 的話,會將上下文目錄下的名爲 Dockerfile 的文件做爲 Dockerfile。
實際上 Dockerfile 的文件名並不要求必須爲 Dockerfile,並且並不要求必須位於上下文目錄中,好比能夠用 -f ../Dockerfile.php 參數指定某個文件做爲 Dockerfile。
 
上下文的概念。當構建的時候,用戶會指定構建鏡像上下文的路徑,docker build 命令得知這個路徑後,會將路徑下的全部內容打包,而後上傳給 Docker 引擎(注意看上圖第二行)。這樣 Docker 引擎收到這個上下文包後,展開就會得到構建鏡像所需的一切文件。 寫一個 .dockerignore 用於剔除不須要做爲上下文傳遞給 Docker 引擎的。
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息