Docker 第八篇 | Dockerfile的基本結構和定義
Dockerfile 概念
Docker 映象是一個特殊的檔案系統,除了提供容器執行時所需的程式、庫、資源、配置等檔案外,還包含了一些為執行時準備的一些配置引數(如匿名卷、環境變數、使用者等)。映象不包含任何動態資料,其內容在構建之後也不會被改變。
映象的定製實際上就是定製每一層所新增的配置、檔案。如果我們可以把每一層修改、安裝、構建、操作的命令都寫入一個指令碼,用這個指令碼來構建、定製映象,那麼之前提及的無法重複的問題、映象構建透明性的問題、體積的問題就都會解決。這個指令碼就是 Dockerfile。
Dockerfile 是一個文字檔案,其內包含了一條條的指令(Instruction),每一條指令構建一層,因此每一條指令的內容,就是描述該層應當如何構建。有了 Dockerfile,當我們需要定製自己額外的需求時,只需在 Dockerfile 上新增或者修改指令,重新生成 image 即可,省去了敲命令的麻煩。
可以用一張圖來說明:Docker映象,Dockerfile ,容器之間的關係
通過上圖可以看出使用 Dockerfile 定義映象,執行映象啟動容器。
Dockerfile 檔案格式
## Dockerfile檔案格式 # This dockerfile uses the ubuntu image # VERSION 2 - EDITION 1 # Author: docker_user # Command format: Instruction [arguments / command] .. # 1、第一行必須指定 基礎映象資訊 FROM ubuntu # 2、維護者資訊 MAINTAINER docker_user [email protected]
# 3、映象操作指令 RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list RUN apt-get update && apt-get install -y nginx RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf # 如果命令有多行可以用 \分隔 RUN buildDeps='gcc libc6-dev make' \ && apt-get update \ && apt-get install -y $buildDeps \ && wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \ && mkdir -p /usr/src/redis \ && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \ # 4、容器啟動執行指令 CMD /usr/sbin/nginx
Dockerfile 分為四部分:基礎映象資訊、維護者資訊、映象操作指令、容器啟動時執行指令。一開始必須要指明所基於的映象名稱,接下來一般會說明維護者資訊;後面則是映象操作指令,例如 RUN 指令。每執行一條RUN 指令,映象新增新的一層,並提交;最後是 CMD 指令,來指明執行容器時的操作命令。
指令說明(Dockerfile 檔案中涉及的指令)
映象標籤
docker build 命令會根據 Dockerfile 檔案及上下文構建新 Docker 映象。構建上下文是指 Dockerfile 所在的本地路徑或一個URL(Git倉庫地址)。構建上下文環境會被遞迴處理,將該路徑下的所有內容傳送給Docker服務端,由服務端來建立映象。因此除非生成映象需要,否則一般建議放置Dockerfile的目錄為空目錄。
1.如果使用非內容路徑下的Dockerfile,可以通過-f選項來指定其路徑;
2.要指定生成映象的標籤資訊,可以使用-t選項。
如下通過指定標籤構建映象(預設Dockerfile在上下文環境的根目錄中):
docker build -t nginx:v15 .
如果存在多個倉庫下,或使用多個映象標籤,就可以使用多個-t引數,會構建出多個映象:
構建映象
說明:構建會在 Docker 後臺守護程序(daemon)中執行,而不是CLI中。構建前,構建程序會將全部內容(遞迴)傳送到守護程序。大多情況下,應該將一個空目錄作為構建上下文環境,並將 Dockerfile 檔案放在該目錄下。
在構建上下文中使用的 Dockerfile 檔案,是一個構建指令檔案。為了提高構建效能,可以通過 .dockeringore檔案(每一行新增一條匹配模式)來讓Docker忽略匹配模式路徑下的目錄和檔案。
在 Docker 構建映象的第一步,docker CLI 會先在上下文目錄中尋找.dockerignore檔案,根據.dockerignore 檔案排除上下文目錄中的部分檔案和目錄,然後把剩下的檔案和目錄傳遞給 Docker 服務。
Dockerfile 一般位於構建上下文的根目錄下,也可以通過-f
指定該檔案的位置:
docker build -f /path/to/a/Dockerfile .
例項如:
語法檢查
在 Docker 守護程序執行 Dockerfile 中的指令前,首先會對 Dockerfile 進行語法檢查,有語法錯誤時會返回:
docker build -t nginx/v3 .
Sending build context to Docker daemon 2.048 kB
Error response from daemon: Unknown instruction: RUNCMD
快取
Docker 守護程序會一條一條的執行 Dockerfile 中的指令,而且會在每一步提交併生成一個新映象,最後會輸出最終映象的ID。生成完成後,Docker 守護程序會自動清理你傳送的上下文。
Dockerfile檔案中的每條指令會被獨立執行,並會建立一個新映象,RUN cd /tmp等命令不會對下條指令產生影響。
Docker 會重用已生成的中間映象,以加速docker build的構建速度。以下是一個使用了快取映象的執行過程:
$ docker build -t svendowideit/ambassador .
Sending build context to Docker daemon 15.36 kB
Step 1/4 : FROM alpine:3.2
---> 31f630c65071
Step 2/4 : MAINTAINER [email protected]
---> Using cache
---> 2a1c91448f5f
Step 3/4 : RUN apk update && apk add socat && rm -r /var/cache/
---> Using cache
---> 21ed6e7fbb73
Step 4/4 : CMD env | grep _TCP= | (sed 's/.*_PORT_\([0-9]*\)_TCP=tcp:\/\/\(.*\):\(.*\)/socat -t 100000000 TCP4-LISTEN:\1,fork,reuseaddr TCP4:\2:\3 \&/' && echo wait) | sh
---> Using cache
---> 7ea8aef582cc
Successfully built 7ea8aef582cc
構建快取僅會使用本地父生成鏈上的映象,如果不想使用本地快取的映象,也可以通過–cache-from指定快取。指定後將不再使用本地生成的映象鏈,而是從映象倉庫中下載。
尋找快取的邏輯
Docker 尋找快取的邏輯其實就是樹型結構根據 Dockerfile 指令遍歷子節點的過程。下圖可以說明這個邏輯:
FROM base_image:version Dockerfile:
+----------+ FROM base_image:version
|base image| RUN cmd1 --> use cache because we found base image
+-----X----+ RUN cmd11 --> use cache because we found cmd1
/ \
/ \
RUN cmd1 RUN cmd2 Dockerfile:
+------+ +------+ FROM base_image:version
|image1| |image2| RUN cmd2 --> use cache because we found base image
+---X--+ +------+ RUN cmd21 --> not use cache because there's no child node
/ \ running cmd21, so we build a new image here
/ \
RUN cmd11 RUN cmd12
+-------+ +-------+
|image11| |image12|
+-------+ +-------+
大部分指令可以根據上述邏輯去尋找快取,除了 ADD 和 COPY 。這兩個指令會複製檔案內容到映象內,除了指令相同以外,Docker 還會檢查每個檔案內容校驗(不包括最後修改時間和最後訪問時間),如果校驗不一致,則不會使用快取。
除了這兩個命令,Docker 並不會去檢查容器內的檔案內容,比如 RUN apt-get -y update,每次執行時檔案可能都不一樣,但是 Docker 認為命令一致,會繼續使用快取。這樣一來,以後構建時都不會再重新執行apt-get -y update。
如果 Docker 沒有找到當前指令的快取,則會構建一個新的映象,並且之後的所有指令都不會再去尋找快取。
相關推薦
Docker 第八篇 | Dockerfile的基本結構和定義
Dockerfile 概念 Docker 映象是一個特殊的檔案系統,除了提供容器執行時所需的程式、庫、資源、配置等檔案外,還包含了一些為執行時準備的一些配置引數(如匿名卷、環境變數、使用者等)。映象不包含任何動態資料,其內容在構建之後也不會被改變。 映象的定製實
Docker第八篇-docker-compose教程(介紹,安裝,入門示例)
文章目錄 docker-compose介紹 docker-compose安裝 安裝docker(已安裝最新的請忽略此步驟) docker-compose安裝與解除安裝 docker-compose簡單示例 d
Docker第四篇-Dockerfile製作Docker映象
文章目錄 製作簡單Mysql映象 Dockerfile命令說明 總結 這一篇主要介紹Dockerfile命令的使用說明及如何使用Dockerfile製作簡單映象 製作簡單Mysql映象 建立目錄 mkdir /tmp/mysql
易學筆記-go語言-第4章:基本結構和基本資料型別/4.4 變數/4.4.3 函式體內最簡單的變數初始化
函式體內最簡單的變數賦值 格式: 變數名 := 值 舉例: var goos string = os.Getenv("GOOS") fmt.Printf("The operating system is: %s\n", goos) //函式體內最
易學筆記-go語言-第4章:基本結構和基本資料型別/4.4 變數/4.4.2 宣告和賦值語句結合
宣告和賦值語句結合 格式:var identifier [type] = value 這裡的type是可選的,具體的型別參照: 第4章:基本結構和基本資料型別/4.2 Go 程式的基本結構和要素/4.2.8 型別 顯式型別舉例: //整型 var a&nbs
易學筆記-go語言-第4章:基本結構和基本資料型別/4.4 變數/4.4.4 函式體內並行初始化
函式體內並行賦值 在 第4章:基本結構和基本資料型別/4.4 變數/4.4.3 函式體內最簡單的變數賦值基礎上,多個變數同時賦值 舉例: 程式碼: a, b, c := 5, 10, "易學筆記" fmt.Printf("a&n
易學筆記-Go語言-第4章:基本結構和基本資料型別/4.5 基本型別/4.5.2 整形
整形 固定位元組數整形:與作業系統無關 int 和 uint 在 32 位作業系統上,它們均使用 32 位(4 個位元組),在 64 位作業系統上,它們均使用 64 位(8 個位元組)。 uintptr 存放指標 指定位元組
易學筆記-Go語言-第4章:基本結構和基本資料型別/4.5 基本型別/4.5.1 bool型別
bool型別 關鍵字:bool,兩個結果:true 或者 false 何時回產生bool型別 ==:相等性筆記 !=:不相等性筆記 >、>=、<、<=:比較 可以進行的邏輯運算
易學筆記-Go語言-第4章:基本結構和基本資料型別/4.4 變數/4.4.7 變數的作用域
變數的作用域 變數的作用域有幾種: 包間變數:也是在函式外宣告的變數,而且第一個字母是大寫,所有本包函式或者包外函式都可見 全域性變數:在函式外宣告的變數,所有函式都可見 區域性變數:在本函式內部都可見 塊變數:僅僅在某個塊中可見,
第4章:基本結構和基本資料型別/4.2 Go 程式的基本結構和要素/4.2.5 可見性
易學筆記 十年IT經驗個人學習筆記分享: 開發語言:C/C++/JAVA/PYTHON/GO/JSP WEB架構:Servlets/springMVC/springBoot/springClound 容器架構:Docker容器/Docker叢集/Docker與微服務整合/
第4章:基本結構和基本資料型別/4.2 Go 程式的基本結構和要素/4.2.4 import:匯入包
易學筆記 十年IT經驗個人學習筆記分享: 開發語言:C/C++/JAVA/PYTHON/GO/JSP WEB架構:Servlets/springMVC/springBoot/springClound 容器架構:Docker容器/Docker叢集/Docker與微服務整合/
第4章:基本結構和基本資料型別/4.2 Go 程式的基本結構和要素/4.2.6 函式
易學筆記 十年IT經驗個人學習筆記分享: 開發語言:C/C++/JAVA/PYTHON/GO/JSP WEB架構:Servlets/springMVC/springBoot/springClound 容器架構:Docker容器/Docker叢集/Docker與微服務整合/
易學筆記-Go語言-第4章:基本結構和基本資料型別/4.6 字串概述/4.6.1 字串表示
易學筆記 十年IT經驗個人學習筆記分享: 開發語言:C/C++/JAVA/PYTHON/GO/JSP WEB架構:Servlets/springMVC/springBoot/springClound 容器架構:Docker容器/Docker叢集/Docker與微服務整合/
易學筆記-Go語言-第4章:基本結構和基本資料型別/4.5 基本型別/4.5.6 位運算
易學筆記 十年IT經驗個人學習筆記分享: 開發語言:C/C++/JAVA/PYTHON/GO/JSP WEB架構:Servlets/springMVC/springBoot/springClound 容器架構:Docker容器/Docker叢集/Docker與微服務整合/
易學筆記-Go語言-第4章:基本結構和基本資料型別/4.5 基本型別/4.5.7 隨機數
易學筆記 十年IT經驗個人學習筆記分享: 開發語言:C/C++/JAVA/PYTHON/GO/JSP WEB架構:Servlets/springMVC/springBoot/springClound 容器架構:Docker容器/Docker叢集/Docker與微服務整合/
FPGA第八篇:運算子、賦值語句和結構說明語句
第四章——《運算子、賦值語句和結構說明語句》 一、概念 1、邏輯運算子(&&、||、!) 2、關係運算符(<、<=、>、>=) 3、等式運算子(==、!=、===、!==) 4、移位運算子(>>、<<) 注
數據結構第八篇——鏈棧
val 條件 isempty pop 存儲 操作 部分 get sem ?註:未經博主同意,不得轉載。 鏈棧 鏈式存儲的棧稱為鏈棧。可用單鏈表來實現鏈棧,因此其節點結構與單鏈表的結構相同。下面給出這種結構的定義: 若要了解順序棧的內容請跳轉至http://www.cnb
從.Net到Java學習第八篇——SpringBoot實現session共享和國際化
區分 cal request 展示 hang 輸入 nds www target SpringBoot Session共享 修改pom.xml添加依賴 <!--spring session--> <dependen
Docker第九篇-docker-compose命令和模板檔案說明
文章目錄 docker-compose常用命令 docker-compose.yml模板 docker-compose常用命令 docker-compose up 啟動容器,會出現互動命令視窗,若此時Ctrl+C
Python 語言學習 第八篇:函式2(引數、lamdba和函式屬性)
函式的引數是引數暴露給外部的介面,向函式傳遞引數,可以控制函式的流程,函式可以0個、1個或多個引數;在Python中向函式傳參,使用的是賦值方式。 一,傳遞引數 引數是通過賦值來傳遞的,傳遞引數的特點是: 引數的傳遞是通過自動把物件賦值給函式的本地變數名來實現的, 在函式內部的變數名的賦值不會