Docker鏡像創建、Dockerfile使用(Apache,Nginx的鏡像創建)


Docker 鏡像的創建

創建鏡像有三種方法,分別為基於已有鏡像創建、基於本地模板創建以及基於Dockerfile創建。

1. 基於現有鏡像創建

(1)首先啟動一個鏡像,在容器里做修改

docker run -idt --name No1 centos:7 /bin/bash

docker ps-a

(2)然后將修改后的容器提交為新的鏡像,需要使用該容器的 ID 號創建新鏡像

docker commit -m "new" -a "centos" 208181f8f689 centos: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

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM