Docker映象建立、Dockerfile使用(Apache,Nginx的映象建立)
Docker 映象的建立
建立映象有三種方法,分別為基於已有映象建立、基於本地模板建立以及基於Dockerfile建立。
1. 基於現有映象建立
(1)首先啟動一個映象,在容器裡做修改
docker run -idt --name No1 centos:7 /bin/bash
docker ps-a
(2)然後將修改後的容器提交為新的映象,需要使用該容器的 ID 號建立新映象
dockercommit -m "new" -a "centos" 208181f8f689centos:dd
#常用選項∶
-m:說明資訊
-a:作者資訊
-p:生成過程中停止容器的執行
docker images
2. 基於本地模板建立
通過匯入作業系統模板檔案可以生成映象, 模板可以從 OPENVZ 開源專案下載,下載地址為http://openvz.org/Download/template/precreated
#格式:wget [下載路徑] -o [儲存路徑]、curl -L [下載路徑] -o [儲存路徑]
wget http://download.openvz.org/template/precreated/debian-7.0-x86-minimal.tar.gz
#匯入為映象
cat debian-7.0-x86-minimal.tar.gz|docker import - debian:dd
3. 基於Dockerfile 建立 映象
聯合檔案系統(UnionFS)
UnionFS(聯合檔案系統):Union檔案系統(UnionFS)是一種分層、輕量級並且高效能的檔案系統,它支援對檔案系統的修改作為一次提交來一層層的疊加,同時可以將不同目錄掛載到同一個虛擬檔案系統下。AUFS、OverlayFS 及 Devicemapper 都是一種 UnionFS(現在用的overlay2聯合檔案系統)。
Union檔案系統是Docker映象的基礎。映象可以通過分層來進行繼承,基於基礎映象(沒有父映象),可以製作各種具體的應用映象。
特性∶一次同時載入多個檔案系統,但從外面看起來,只能看到一個檔案系統,聯合載入會把各層檔案系統疊加起來,這樣最終的檔案系統會包含所有底層的檔案和目錄。
我們下載的時候看到的一層層的就是聯合檔案系統。
映象載入原理
Docker的映象實際上由一層一層的檔案系統組成,這種層級的檔案系統就是UnionFS。
bootfs主要包含bootloader和kernel,bootloader主要是引導載入kernel,Linux剛啟動時會載入bootfs檔案系統。
在Docker映象的最底層是bootfs,這一層與我們典型的Linux/Unix系統是一樣的,包含boot載入器和核心。當boot載入完成之後整個核心就都在記憶體中了,此時記憶體的使用權己由bootfs轉交給核心,此時系統也會解除安裝bootfs(bootfs載入宿主機核心並提供與映象共享)
rootfs在bootfs之上。包含的就是典型Linux系統中的/dey、/proc、/bin、/etc等標準目錄和檔案。rootfs就是各種不同的作業系統發行版,比如Ubuntu、Centos等等(rootfs提供相同的執行環境,不同發行的作業系統和目錄環境)
簡答來說一開始bootfs引導載入宿主機核心,所有映象的執行建立基於共享宿主機的核心,操作一個命令下載debian(通用作業系統),這時就會在核心上面加了一層基礎映象,再安裝一個emacs, 會在基礎映象上疊加一層image,接著再安裝一個apache,又會在images上面再疊加一層image。最後它們看起來就像一個檔案系統即容器的rootfs。在Docker的體系裡把這些rootfs叫做Docker的映象。但是,此時的每一層rootfs都是read-only的,我們此時還不能對其進行操作。當我們建立一個容器,也就是將Docker映象進行例項化,系統會在一層或是多層read-only的rootfs(只讀層)之上分配一層空的read-write的rootfs(可讀可寫層)。
在映象例項化執行就會附加可讀可寫層,也就是容器化執行,使用者會對可讀可寫層進行操作,資料會只會儲存在讀寫層,伴隨著容器的生命週期。不會對映象本身進行操作,如果刪除容器,那之前在讀寫層進行的操作資料也會消失,讀寫層之前累計的層數都為只讀層
Dockerfile
Docker映象是一個特殊的檔案系統,除了提供容器執行時所需的程式、庫、資源、配置等檔案外,還包含了一些為執行時準備的一些配置引數(如匿名卷、環境變數、使用者等)。映象不包含任何動態資料,其內容在構建之後也不會被改變。
映象的定製實際上就是定製每一層所新增的配置、檔案。如果我們可以把每一層修改、安裝、構建、操作的命令都寫入一個指令碼,用這個指令碼來構建、定製映象,那麼映象構建透明性的問題、體積的問題就都會解決。這個指令碼就是Dockerfile。
Dockerfile是一個文字檔案,其內包含了一條條的指令(Instruction),每一條指令構建一層,因此每一條指令的內容,就是描述該層應當如何構建。有了Dockerfile,當我們需要定製自己額外的需求時,只需在Dockerfile上新增或者修改指令,重新生成 image即可,省去了敲命令的麻煩。
除了手動生成Docker映象之外,可以使用Dockerfile自動生成映象。Dockerfile是由多條的指令組成的檔案,其中每條指令對應 Linux 中的一條命令,Docker 程式將讀取Dockerfile 中的指令生成指定映象。
Dockerfile結構大致分為四個部分∶基礎映象資訊、維護者資訊、映象操作指令和容器啟動時執行指令。Dockerfile每行支援一條指令,每條指令可攜帶多個引數,支援使用以"#"號開頭的註釋。
Docker 映象結構的分層
映象不是一個單一的檔案,而是有多層構成。容器其實是在映象的最上面加了一層讀寫層,在執行容器裡做的任何檔案改動,都會寫到這個讀寫層。如果刪除了容器,也就刪除了其最上面的讀寫層,檔案改動也就丟失了。Docker使用儲存驅動管理映象每層內容及可讀寫層的容器層。
(1)Dockerfile 中的每個指令都會建立一個新的映象層,後面疊加的每一次映象都由overlay2聯合檔案系統管理
(2)映象層將被快取和複用
(3)當Dockerfile的指令修改了,複製的檔案變化了,或者構建映象時指定的變數不同了,對應的映象層快取就會失效
(4)某一層的映象快取失效,它之後的映象層快取都會失效(之後的映象層都在該層基礎上疊加)
(5)映象層是不可變的,如果在某一層中新增一個檔案,然後在下一層中刪除它,則映象中依然會包含該檔案,只是這個檔案在 Docker 容器中使用者不可見了。
Dockerfile 操作常用的指令
(1)FROM映象名
指定新映象所基於的基礎映象,第一條指令必須為EROM 指令,每建立一個映象就需要一條 FROM 指令
(2)MAINTAINER 名字
說明新映象的維護人資訊
(3)RUN 命令
在所基於的映象上執行命令,並提交到新的映象中
(4)ENTRYPOINT ["要執行的程式", "引數 1", "引數 2"]
設定容器啟動時第一個執行的命令及其引數。
可以通過使用命令docker run --entrypoint 來覆蓋映象中的ENTRYPOINT指令的內容。
docker run指定的命令優先順序最高,其次為ENTRYPOINT指定的命令最後為CMD
例如:
ENTRYPOINT[ "ls", "-lf", "*"]
(5)CMD ["要執行的程式", "引數1", "引數2"]
上面的是exec形式,shell形式:CMD命令 引數1 引數2
啟動容器時預設執行的命令或者指令碼,Dockerfile只能有一條CMD命令。如果指定多條命令,只執行最後一條命令
如果在docker run時指定了命令或者映象中有ENTRYPOINT,那麼CDM就會被覆蓋。
CMD 可以為 ENTRYPOINT 指令提供預設引數,相當於傳參的作用。
例如:
ENTRYPOINT["ls"]
CMD ["-lf", "*"]
(6)EXPOSE 埠號
指定新映象載入到 Docker 時要開啟的埠
(7)ENV 環境變數 變數值
設定一個環境變數的值,會被後面的 RUN 使用
例如:
ENV PATH=$PATH:/opt #中間的 = 號可以使用空格替代
(8)ADD 原始檔/目錄目標檔案/目錄
將原始檔複製到映象中,原始檔要與 Dockerfile 位於相同目錄中,或者是一個URL
有如下注意事項∶
1、如果源路徑是個檔案,且目標路徑是以/結尾,則docker會把目標路徑當作一個目錄,會把原始檔拷貝到該目錄下。如果目標路徑不存在,則會自動建立目標路徑。
2、如果源路徑是個檔案,且目標路徑是不是以/結尾,則docker會把目標路徑當作一個檔案。
如果目標路徑不存在,會以目標路徑為名建立一個檔案,內容同源檔案
如果目標檔案是個存在的檔案,會用原始檔覆蓋它, 當然只是內容覆蓋,檔名還是目標檔名。
如果目標檔案實際是個存在的目錄,則會原始檔拷貝到該目錄下。注意,這種情況下,最好顯示的以/ 結尾,以避免混淆。
3、如果源路徑是個目錄,且目標路徑不存在,則docker會自動以目標路徑建立一個目錄,把源路徑目錄下的檔案拷貝進來。如果目標路徑是個已經存在的目錄,則docker會把源路徑目錄下的檔案拷貝到該目錄下。
4、如果原始檔是個歸檔檔案(使用tar命令壓縮的檔案),則docker會自動幫解壓。
URL下載和解壓特性不能一起使用。任何壓縮檔案通過URL拷貝,都不會自動解壓。
(9)COPY 原始檔/目錄 目標檔案/目錄
只複製本地主機上的檔案/目錄複製到目標地點,原始檔/目錄要與Dockerfile 在相同的目錄中
(10)VOLUME ["目錄"]
在容器中建立一個掛載點
(11)USER使用者名稱/UID
指定執行容器時的使用者
(12)WORKDIR 路徑
為後續的 RUN、CMD、ENTRYPOINT 指定工作目錄
(13)ONBUILD 命令
指定所生成的映象作為一個基礎映象時所要執行的命令。
當在一個Dockerfile檔案中加上ONBUILD指令,該指令對利用該Dockerfile構建映象(比如為A鐿像)不會產生實質性影響。
但是當編寫一個新的Dockerfile檔案來基於A映象構建一個映象(比如為B映象)時,這時構造A映象的Dockerfile檔案中的ONBUILD指令就生效了,在構建B映象的過程中,首先會執行ONBUILD指令指定的指令,然後才會執行其它指令。
(14)HEALTHCHECK
健康檢查
注意:Dockerfile中ENTRYPOINT和CMD命令的作用和區別
ENTRYPOINT和CMD都是容器啟動時預設執行的命令,ENTRYPOINT需要嚴格遵守exec形式,CMD命令可以使用shell形式
ENTRYPOINT的優先順序比CMD命令更高,如果同時存在會覆蓋CMD指定的命令,docker run指定的命令優先順序最高
Dockerfile中只能有一條CMD命令,多條CMD只會執行最後一條
注意:Dockerfile中ADD和COPY命令的作用和區別
他們都具有複製本地檔案、目錄到映象的功能
ADD在複製tar壓縮包的歸檔檔案時候自動支援解壓縮,並且支援使用url路徑拉取檔案
COPY只能複製本地檔案/目錄到映象
編寫 Dockerfile 時需要嚴格遵循的格式
●第一行必須使用 FROM 指令指明所基於的映象名稱
●之後使用 MAINTAINER 指令說明維護該映象的使用者資訊(可以忽略)
●然後是映象操作相關指令,如 RUN 指令。每執行一條指令,都會給基礎映象新增新的一層(因為RUN指令會不斷疊加映象,增大整個映象的大小,儘量減少多條RUN命令)。
●最後使用 CMD 指令指定啟動容器時要執行的命令操作。
●指令名都需要大寫
Dockerfile使用
一、Apache 服務yum安裝配置
#建立工作目錄
mkdir /opt/apache
cd /opt/apache
vim Dockerfile
FROM centos:7 #基於的基礎映象
MAINTAINER this is apache image <dd> #維護映象的使用者資訊
RUN yum -y update #映象操作更新yum倉庫
RUN yum -y install httpd #映象操作指令yum安裝apache軟體
EXPOSE 80 #開啟 80 埠
ADD index.html /var/www/html/ #複製網站首頁檔案
#方法一:
ADD run.sh /run.sh #將服務啟動指令碼複製到映象中
RUN chmod 755 /run.sh
CMD ["/run.sh"] #建立容器後啟動該指令碼
#方法二:
ENTRYPOINT [ "/usr/sbin/apachectl" ]
CMD [ "-D", "FOREGROUND" ]
#ENTRYPOINT指定的命令用來控制Apache HTTP伺服器的程式,CMD指定的是傳給ENTRYPOINT命令的引數,使apache服務前臺啟動,因為Docker容器僅在它的1號程序(PID為1)執行時,會保持執行。
如果1號程序退出了,Docker容器也就退出了,所以為了保證該apache容器建立執行後不直接關閉將服務放在前臺一直進行執行
#如果使用方法一需要準備執行指令碼
vim run.sh
#!/bin/bash
rm -rf /run/httpd/* #清理httpd的快取
/usr/sbin/apachectl -D FOREGROUND #指定為前臺執行
echo "this is web1">index.html #準備網站頁面
#生成映象
docker build -t httpd:centos . #注意別忘了末尾有".",表示使用當前路徑下的檔案構建映象
#新映象執行容器,並進行web測試
docker run -it --name No1 -p 5555:80 httpd:centos
http://192.168.150.30:5555
#如果有網路報錯提示#
[Warning] IPv4 forwarding is disabled.Networking will not work.
解決方法∶
vim /etc/sysctl.conf #配置核心轉發
net.ipv4.ip forward=1
sysctl -p #過載核心配置,重啟網絡卡和docker服務
systemctl restart network
systemctl restart docker
二、Nginx服務原始碼安裝配置
mkdir /opt/nginx
cd /opt/nginx
vim Dockerfile
FROM centos:7
MAINTAINER this is nginx image <dd>
RUN yum -y install pcre-devel zlib-devel gcc gcc-c++ make;useradd -M -s /sbin/nologin nginx #nginx原始碼編譯安裝需要的工具和環境,建立nginx執行的使用者,兩條命令中間使用 ; 號間隔
ADD nginx-1.12.0.tar.gz /opt/ #將nginx原始碼包複製到映象中的opt目錄下
WORKDIR /opt/nginx-1.12.0 #指定預設執行命令的路徑
RUN ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module;make -j 2 && make install #安裝模組並且編譯安裝
EXPOSE 80 #開啟80埠
ADD index.html /usr/local/nginx/html/index.html #複製首頁檔案到映象中
CMD /usr/local/nginx/sbin/nginx -g "daemon off;" #前臺啟動nginx的命令
echo "this is nginx" > index.html #準備首頁檔案
docker build -t ngnix:dd . #讀取Dockerfile檔案建立映象
docker run -itd --name No1 -p 5333:80 nginx:dd #使用該映象建立容器
docker ps -a
http://192.168.150.30:5333