Dockerfile 簡單來說就是一個包含用於組合映象的命令的文字文件,Docker 通過讀取 Dockerfile 中的指令就可以按步驟生成映象,那麼在製作映象之前,我們先了解一下映象的原理。
1、映象原理
只有瞭解映象的原理,我們才能更清晰的通過 Dockerfile 製作映象。
前面幾篇文章我們簡單介紹了docker中的映象,映象是隻讀的檔案,提供了執行程式完整的軟硬體資源,是應用程式的“集裝箱”,包含執行某個軟體所需的所有內容,包括程式碼、執行時環境、所需庫、環境變數、配置檔案等等。
那麼映象是如何做到這些的呢?
1.1 UnionFS(聯合檔案系統)
聯合檔案系統(Union File System):2004 年由紐約州立大學開發,它可以把多個目錄內容聯合掛載到同一個目錄下,而目錄的物理位置是分開的。UnionFS可以把只讀和可讀寫檔案系統合併在一起,具有寫時複製功能,允許只讀檔案系統的修改可以儲存到可寫檔案系統當中。
UnionFS(Union File System) 一次性載入多個檔案系統,但是從外表看起來,只能看到一個檔案系統,聯合載入會把各層檔案系統疊加起來,這樣最終的檔案系統會包含所有底層的檔案和目錄。
1.2 Docker 映象載入原理
Docker 的映象實際上就是由一層一層的檔案系統組成,這裡給出 Docker 官方的一張圖:
Bootfs(boot file system):主要包含 bootloader 和 kernel,bootloader 主要是引導載入 kernel,比如 Linux 剛啟動時會載入 bootfs 檔案系統,在 Docker 映象的最底層就是 bootfs。這一層與我們典型的 Linux/Unix 系統是一樣的,包含 boot 載入器和核心。當 boot 載入完成之後整個核心就都在記憶體中了,此時記憶體的使用權已由 bootfs 轉交給核心,此時系統也會解除安裝 bootfs。
Rootfs(root file system):在 bootfs 之上,中間只讀的 rootfs 的集合稱為 Docker 映象,Docker 映象構建時,會一層層構建,前一層是後一層的基礎。每一層構建完就不會再發生改變,後一層上的任何改變只發生在自己這一層。UnionFS 使得映象的複用、定製變得更為容易。甚至可以用之前構建好的映象作為基礎層,然後進一步新增新的層,以定製自己所需的內容,構建新的映象。
Container(容器):容器 = 映象 + 讀寫層,從檔案系統上看,Docker容器比Docker映象多一層可讀寫的檔案系統掛載層。藉助於 UnionFS,容器內部的更改都被儲存到了最上面的讀寫層,而其他層都是隻讀的,這樣中間的只讀 rootfs 是可以被多個容器複用的。UnionFS 將檔案的更新掛載到老的檔案之上,而不去修改那些不更新的內容,這就意味著即使虛擬的檔案系統被反覆修改,也能保證宿主機空間佔用保持一個較低水平。
在 rootfs 的基礎上,Docker 公司創新性地提出了使用 UnionFS,多個增量 rootfs 聯合掛載一個完整 rootfs 的方案,通過“分層映象”的設計,圍繞 Docker 映象,大家甚至可以協同工作,再加上 Docker 官方提供的映象倉庫,進一步減少了共享映象的成本,這大大提高了開發部署的效率。
這樣你也能理解為什麼 docker 啟動塊,佔用資源少了吧。
1.3 實操理解分層概念
這裡我們下載一個 Tomcat9.0 映象:
我們也可以通過上一篇文章講解的命令檢視映象層結構:
docker inspect 映象id
2、Dockerfile 的 helloworld
例項:建立一個能訪問 Tomcat 首頁的容器
2.1 手動建立
通常我們啟動一個Tomcat容器,官方映象是簡化版的,在webapps 目錄下沒有任何內容,所有我們啟動之後訪問主頁也是沒有任何內容。
docker run -d -p 8080:8080 tomcat
但是官方映象的 webapps.dist 目錄下有首頁檔案,所以我們將 webapps.dist 目錄下的所有檔案複製到 webapps ,然後訪問首頁就有介面了。
1、進入啟動的容器
docker exec -it 容器id /bin/bash
2、將webapps.dist 目錄所有檔案複製到 webapps 目錄下
cp -r webapps.dist/* webapps/
再次訪問首頁:
2.2 Dockerfile 建立
PS: 不同命令沒關係,後面會解釋每條命令含義。
①、提前準備好 webapps 目錄檔案
我這裡直接將官方Tomcat容器中的 webapps.dist 目錄拷貝到本機的/home/webapps 目錄下:
docker cp 容器ID:/usr/local/tomcat/webapps.dist /home/webapps
②、準備 dockerfile 檔案
在本機 /home 目錄下新建一個 Dockerfile 檔案(可以任意命名,沒有字尾),內容如下:
FROM tomcat:latest
MAINTAINER itcoke
WORKDIR /usr/local/tomcat/webapps
COPY ./webapps/ /usr/local/tomcat/webapps/
③、構建映象
docker build -f Dockerfile -t itcoke/mytomcat:1.0 .
④、執行映象
docker run -d -p 8081:8080 itcoke/mytomcat:1.0
⑤、訪問首頁測試
可以看到如下圖的首頁介面,即構建執行成功。
3、Dockerfile 指令詳解
在上面了我們編寫了一個 Dockerfile 檔案,內容如下:
FROM tomcat:latest
MAINTAINER itcoke
WORKDIR /usr/local/tomcat/webapps
COPY ./webapps/ /usr/local/tomcat/webapps/
那這裡面每條指令是什麼意思呢?接下來我們揭開這層神祕的面紗。
3.1 編寫規範
①、每條指令(每行開頭關鍵字)都必須是大寫字母;
②、執行順序是按照編寫順序從上到下;
③、# 表示註釋;
3.2 常用指令介紹
①、FROM
FROM centos #依賴官方基準映象(centos:lastest)
FROM scratch #不依賴任何基準映象
FROM tomcat:9.0-jdk8-openjdk #指定具體版本號
②、MAINTAINER
通常表示映象來自哪個機構。類似還有比如 LABEL 標籤,展示映象的一些說明資訊,不會對映象有實際影響。
LABEL version=“1.0”
LABEL description="初版xxx服務"
③、WORKDIR
WORKDIR 路徑 # WORKDIR /usr/local
指定工作目錄,也是我們進入映象的路徑,如果指定路徑不存在,該指令也會自動建立該目錄。
PS:儘量使用絕對路徑,這樣更加清晰。
④、ADD 和 COPY
都是進行檔案複製。
ADD 功能更加強大一點,支援壓縮包的解壓,還支援遠端檔案的複製。
⑤、ENV
設定環境常量。
比如:
ENV JAVA_HOME /usr/local/openjdk8
RUN ${JAVA_HOME}/bin/java -jar test.jar
儘量使用環境常量,這樣可以提高程式的可維護性。
3.3 RUN 和 CMD 和 ENTRYPOINT
RUN: 在映象構建時執行命令,比如 RUN yum -y install vim;
ENTRYPOINT:容器啟動時執行的命令;
CMD:容器啟動後執行預設的命令或引數;
①、RUN
構建時執行,有兩種命令格式:
RUN yum install -y vim #Shell 命令格式
RUN ["yum","install","-y","vim"] #Exec命令格式
官方推薦使用 Exec 命令格式。
②、ENTRYPOINT
容器啟動時執行的命令。
命令格式也是推薦使用 Exec。
注意:Dockerfile 中只有最後一個 ENTRYPOINT 會被執行。
③、CMD
用於設定預設執行的命令。
和ENTRYPOINT 命令一樣,也是隻有最後一個 CMD 命令會被執行,但是如果容器啟動時附加指令,則CMD會被忽略。
CMD ["ps","-ef"] #推薦使用 Exec 格式。
比如有如下Dockerfile 檔案:
構建,然後啟動時(不附加命令),會輸出 3:
如果啟動時附加命令,則會執行附加的命令(下圖附加 ls 命令),而不執行Dockerfile 中的CMD 命令:
也就是說 ENTRYPOINT 指令一定會執行,但是 CMD 指令不一定會執行。
3.4 docker build 命令
編寫好的 Dockerfile 通過 docker build 構建映象。
docker build [OPTIONS] PATH | URL | -
①、-f:指定要使用的 Dockerfile 檔案路徑。
②、-t(-tag):映象的名字和標籤,通常是 name:tag。
4、Dockerfile 構建 centos
我們拉取官方的 centos 系統,發現是一個簡化版的,常用的一些 vim 命令,ifconfig 命令都無法使用。
於是我們就編寫一個Dockerfilew 檔案來構建一個自己的 centos系統,有兩個要求:
①、安裝好vim以及一些網路命令;
②、設定工作目錄為 /usr/local;
按照要求,我們在 /home 目錄下新建 Dockerfile_MyCentos 檔案,內容如下:
FROM centos
WORKDIR /usr/local
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo "install successful"
CMD /bin/bash
通過如下語句構建:
docker build -f Dockerfile_MyCentos -t mycentos:1.0 .
PS:對於構建命令,加入你新建的 Dockerfile 檔名稱就是【Dockerfile】,那可以不加 -f 檔名 來指定,docker 會自動尋找。
構建成功後,就生成了自己的映象:
我們執行這個映象,發現這個centos 系統,vim,ifconfig 等網路命令都可以用了。
5、推送映象到阿里雲
上面我們映象製作完成,如何推送到阿里雲呢?
5.1 登入阿里雲
5.2 建立名稱空間
5.3 建立映象倉庫
測試階段選擇本地倉庫就行。
5.4 推送操作指南
點開建立的映象倉庫,就會看到詳細的操作指南。
看到第 3 點,將映象推送到 Registry:
docker login --username=182****5732 registry.cn-hangzhou.aliyuncs.com
docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/itcoke/test:[映象版本號]
docker push registry.cn-hangzhou.aliyuncs.com/itcoke/test:[映象版本號]
第一條命令是登入阿里雲,輸入時需要在此輸入密碼,如果忘記密碼了,可以到【訪問憑證】裡面重新設定。
第二條是設定 tag:
docker tag e10136600f85 registry.cn-hangzhou.aliyuncs.com/itcoke/test:1.0
第三條命令是推送到阿里雲:
docker push registry.cn-hangzhou.aliyuncs.com/itcoke/test:1.0
檢視阿里雲映象版本,也能看到我們推送過去的映象資訊:
點開【層資訊】,裡面的內容就是我們編寫的 Dockerfile 相關資訊。
6、從阿里雲pull映象
7、退出登入
docker logout
docker run -p 8082:8080 -it --name tomcat02 4b8ea0a44f9a /bin/bash