Dockerfile 是一個文本文件,記錄了鏡像構建的所有步驟。
第一個 Dockerfile
用 Dockerfile 創建上節的 ubuntu-with-vi,其內容則為:
下面我們運行 docker build 命令構建鏡像並詳細分析每個細節。
root@ubuntu:~# pwd ①
/root
root@ubuntu:~# ls ②
Dockerfile
root@ubuntu:~# docker build -t ubuntu-with-vi-dockerfile . ③
Sending build context to Docker daemon 32.26 kB ④
Step 1 : FROM ubuntu ⑤
---> f753707788c5
Step 2 : RUN apt-get update && apt-get install -y vim ⑥
---> Running in 9f4d4166f7e3 ⑦
......
Setting up vim (2:7.4.1689-3ubuntu1.1) ...
---> 35ca89798937 ⑧
Removing intermediate container 9f4d4166f7e3 ⑨
Successfully built 35ca89798937 ⑩
root@ubuntu:~#
① 當前目錄為 /root。
② Dockerfile 准備就緒。
③ 運行 docker build 命令,-t
將新鏡像命名為 ubuntu-with-vi-dockerfile
,命令末尾的 .
指明 build context 為當前目錄。Docker 默認會從 build context 中查找 Dockerfile 文件,我們也可以通過 -f
參數指定 Dockerfile 的位置。
④ 從這步開始就是鏡像真正的構建過程。 首先 Docker 將 build context 中的所有文件發送給 Docker daemon。build context 為鏡像構建提供所需要的文件或目錄。
Dockerfile 中的 ADD、COPY 等命令可以將 build context 中的文件添加到鏡像。此例中,build context 為當前目錄 /root
,該目錄下的所有文件和子目錄都會被發送給 Docker daemon。
所以,使用 build context 就得小心了,不要將多余文件放到 build context,特別不要把 /
、/usr
作為 build context,否則構建過程會相當緩慢甚至失敗。
⑤ Step 1:執行 FROM
,將 ubuntu 作為 base 鏡像。
ubuntu 鏡像 ID 為 f753707788c5。
⑥ Step 2:執行 RUN
,安裝 vim,具體步驟為 ⑦、⑧、⑨。
⑦ 啟動 ID 為 9f4d4166f7e3 的臨時容器,在容器中通過 apt-get 安裝 vim。
⑧ 安裝成功后,將容器保存為鏡像,其 ID 為 35ca89798937。
這一步底層使用的是類似 docker commit 的命令。
⑨ 刪除臨時容器 9f4d4166f7e3。
⑩ 鏡像構建成功。
通過 docker images 查看鏡像信息。 鏡像 ID 為 35ca89798937,與構建時的輸出一致。
在上面的構建過程中,我們要特別注意指令 RUN 的執行過程 ⑦、⑧、⑨。Docker 會在啟動的臨時容器中執行操作,並通過 commit 保存為新的鏡像。
查看鏡像分層結構
ubuntu-with-vi-dockerfile 是通過在 base 鏡像的頂部添加一個新的鏡像層而得到的。
這個新鏡像層的內容由 RUN apt-get update && apt-get install -y vim
生成。這一點我們可以通過 docker history
命令驗證。
docker history
會顯示鏡像的構建歷史,也就是 Dockerfile 的執行過程。
ubuntu-with-vi-dockerfile 與 ubuntu 鏡像相比,確實只是多了頂部的一層 35ca89798937,由 apt-get 命令創建,大小為 97.07MB。docker history 也向我們展示了鏡像的分層結構,每一層由上至下排列。
注: 表示無法獲取 IMAGE ID,通常從 Docker Hub 下載的鏡像會有這個問題。
下一節我們學習鏡像的緩存特性。