1. 程式人生 > 其它 >Docker映象建立、Dockerfile使用(Apache,Nginx的映象建立)

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轉交給核心,此時系統也會解除安裝bootfsbootfs載入宿主機核心並提供與映象共享

rootfs在bootfs之上。包含的就是典型Linux系統中的/dey/proc/bin/etc等標準目錄和檔案。rootfs就是各種不同的作業系統發行版,比如UbuntuCentos等等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