1. 程式人生 > >Docker 第八篇 | Dockerfile的基本結構和定義

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中向函式傳參,使用的是賦值方式。 一,傳遞引數 引數是通過賦值來傳遞的,傳遞引數的特點是: 引數的傳遞是通過自動把物件賦值給函式的本地變數名來實現的, 在函式內部的變數名的賦值不會