DockerFile使用與自定義鏡像詳解

【1】DockerFile是什麼

簡單來說,Dockerfile是用來構建Docker鏡像的構建文件,是由一系列命令和參數構成的腳本。

構建的三個步驟:

  • 編寫Dockerfile文件
  • docker build生成鏡像
  • docker run創建容器運行

這裏以我們熟悉的Centos爲例 ,查看DockerFile大致文件結構

FROM scratch
ADD CentOS-8-Container-8.1.1911-20200113.3-layer.x86_64.tar.xz  /

LABEL org.label-schema.schema-version="1.0" \
    org.label-schema.name="CentOS Base Image" \
    org.label-schema.vendor="CentOS" \
    org.label-schema.license="GPLv2" \
    org.label-schema.build-date="20200114" \
    org.opencontainers.image.title="CentOS Base Image" \
    org.opencontainers.image.vendor="CentOS" \
    org.opencontainers.image.licenses="GPL-2.0-only" \
    org.opencontainers.image.created="2020-01-14 00:00:00-08:00"

CMD ["/bin/bash"]

從應用軟件的角度來看,Dockerfile、Docker鏡像與Docker容器分別代表軟件的三個不同階段,

  • Dockerfile是軟件的原材料
  • Docker鏡像是軟件的交付品
  • Docker容器則可以認爲是軟件的運行態

Dockerfile面向開發,Docker鏡像成爲交付標準,Docker容器則涉及部署與運維,三者缺一不可,合力充當Docker體系的基石。

在這裏插入圖片描述

定義一個Dockerfile,Dockerfile定義了進程需要的一切東西。Dockerfile涉及的內容包括執行代碼或者是文件、環境變量、依賴包、運行時環境、動態鏈接庫、操作系統的發行版、服務進程和內核進程(當應用進程需要和系統服務和內核進程打交道,這時需要考慮如何設計namespace的權限控制)等等;

Docker鏡像,在用Dockerfile定義一個文件之後,docker build時會產生一個Docker鏡像,當運行 Docker鏡像時,會創建Docker容器,容器是直接提供服務的。


【2】DockerFile構建過程解析

① Dockerfile內容基礎知識

  • 每條保留字指令都必須爲大寫字母且後面要跟隨至少一個參數
  • 指令按照從上到下,順序執行
  • #表示註釋
  • 每條指令都會創建一個新的鏡像層,並對鏡像進行提交

② Docker執行Dockerfile的大致流程

  • docker從基礎鏡像運行一個容器
  • 執行一條指令並對容器作出修改
  • 執行類似docker commit的操作提交一個新的鏡像層
  • docker再基於剛提交的鏡像運行一個新容器
  • 執行dockerfile中的下一條指令直到所有指令都執行完成

③ DockerFile體系結構(保留字指令)

  • FROM:基礎鏡像,當前新鏡像是基於哪個鏡像的

  • MAINTAINER:鏡像維護者的姓名和郵箱地址

  • RUN:容器構建時需要運行的命令

  • EXPOSE:當前容器對外暴露出的端口

  • WORKDIR:指定在創建容器後,終端默認登陸的進來工作目錄,一個落腳點

  • ENV:用來在構建鏡像過程中設置環境變量

    ENV MY_PATH /usr/mytest
    這個環境變量可以在後續的任何RUN指令中使用,這就如同在命令前面指定了環境變量前綴一樣;也可以在其它指令中直接使用這些環境變量,比如:WORKDIR $MY_PATH

  • ADD:將宿主機目錄下的文件拷貝進鏡像且ADD命令會自動處理URL和解壓tar壓縮包

  • COPY:類似ADD,拷貝文件和目錄到鏡像中。將從構建上下文目錄中 <源路徑> 的文件/目錄複製到新的一層的鏡像內的 <目標路徑> 位置。實例如COPY src dest 或者 COPY ["src", "dest"]

  • VOLUME:容器數據卷,用於數據保存和持久化工作

  • CMD:指定一個容器啓動時要運行的命令。Dockerfile 中可以有多個 CMD 指令,但只有最後一個生效,CMD 會被 docker run 之後的參數替換。
    在這裏插入圖片描述

  • ENTRYPOINT :指定一個容器啓動時要運行的命令。ENTRYPOINT 的目的和 CMD 一樣,都是在指定容器啓動程序及參數。

  • ONBUILD:子鏡像繼承父鏡像,子鏡像運行時,父鏡像ONBUILD被觸發。

BUILD BOTH RUN
FROM WORKDIR CMD
MAINTAINER USER ENV
COPY EXPOSE
ADD VOLUME
RUN ENTRYPOINT
ONBUILD

④ ONBUILD測試

兩個DockerFile文件:DockerFile3與DockerFile4。

DockerFile3內容如下:

FROM centos
RUN yum install -y curl
ENTRYPOINT [ "curl", "-s", "https://ip.cn" ]
ONBUILD RUN echo "now ,dockerfile3 is execute..."

生成鏡像myip:

docker build -f DockerFile3 -t myip .

DockerFile4內容如下:

FROM myip
RUN yum install -y curl
ENTRYPOINT [ "curl", "-s", "https://ip.cn" ]

生成鏡像myip4:

在這裏插入圖片描述


【3】案例之自定義鏡像mycentos

首先需要了解一個Base(scratch)鏡像。Docker Hub 中 99% 的鏡像都是通過在 base 鏡像中安裝和配置需要的軟件構建出來的。

① 編寫DockerFile文件

默認centos鏡像是不支持登陸後的默認路徑、 vim編輯器、查看網絡配置ifconfig的,這裏自定義DockerFile使其支持。

在自定義目錄下創建DockerFile文件,如/mydocker/下,內容如下:

##使用的時候注意去掉註釋  可以在vim窗口模式下使用dd命令快速刪除一行
#繼承自centos鏡像
FROM centos

#作者與郵箱
MAINTAINER jane<jane@qq.com>

#設置環境 
ENV MYPATH /usr/local

#容器啓動後的落腳路徑
WORKDIR $MYPATH
 
#運行安裝命令 
RUN yum -y install vim
RUN yum -y install net-tools

#暴露80端口 
EXPOSE 80
 
CMD echo $MYPATH
CMD echo "success--------------ok"
CMD /bin/bash

② 構建生成鏡像

在當前路徑下/mydocker/執行如下格式命令:

docker build -f DockFile路徑 -t 新鏡像名字:TAG .

會看到 docker build 命令最後有一個 . ,其表示當前目錄。

實例如下:

docker build -f DockerFile  -t mycentos:2.0 .

在這裏插入圖片描述
檢測鏡像:

[root@localhost mydocker]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
mycentos            2.0                 df8160eb077f        About a minute ago   314.3 MB
jane/centos         latest              b3a32e0a2930        14 hours ago         237.1 MB
badtomcat           1.0                 4c900ee6d6e3        19 hours ago         528.7 MB
tomcat              latest              dd7dc39599b6        37 hours ago         528.6 MB
centos              latest              495a24dc98e8        3 weeks ago          237.1 MB
hello-world         latest              9f5834b25059        13 months ago        1.84 kB

③ 創建容器並運行

命令格式如下:

docker run -it 新鏡像名字:TAG  [/bin/bash]

實例如下:

docker run -it df8160eb077f /bin/bash

結果如下:
在這裏插入圖片描述


④ 列出鏡像的變更歷史

命令格式如下:

docker history 鏡像ID

在這裏插入圖片描述


【4】CMD/ENTRYPOINT 鏡像案例

二者相似之處都是都是指定一個容器啓動時要運行的命令。

① CMD命令

Dockerfile 中可以有多個 CMD 指令,但只有最後一個生效,CMD 會被 docker run 之後的參數替換。

實例如下:

docker run -it -p 8888:8080 tomcat ls -l

那麼DockerFile中的最後一個CMD會被ls -l替換,如下圖所示:
在這裏插入圖片描述


② ENTRYPOINT

docker run 之後的參數會被當做參數傳遞給 ENTRYPOINT,之後形成新的命令組合。

③ CMD測試步驟

##新增DockerFile文件
[root@localhost mydocker]# vim DockerFile2

##build創建鏡像
[root@localhost mydocker]# docker build -f DockerFile2 -t myip .
Sending build context to Docker daemon 4.096 kB
Sending build context to Docker daemon
Step 0 : FROM centos
 ---> 495a24dc98e8
Step 1 : RUN yum install -y curl
 ---> Running in 4fd0ea665eaf
CentOS-8 - AppStream                            704 kB/s | 6.4 MB     00:09
CentOS-8 - Base                                 410 kB/s | 5.0 MB     00:12
CentOS-8 - Extras                               2.2 kB/s | 2.1 kB     00:00
Package curl-7.61.1-11.el8.x86_64 is already installed.
Dependencies resolved.
Nothing to do.
Complete!
 ---> 58218afb3e20
Removing intermediate container 4fd0ea665eaf
Step 2 : CMD curl -s http://ip.cn
 ---> Running in 6d14169fb841
 ---> af6a8441dcc9
Removing intermediate container 6d14169fb841
Successfully built af6a8441dcc9
[root@localhost mydocker]# docker run af6a8441dcc9
{"ip": "114.244.77.52", "country": "北京市", "city": "聯通"}

DockerFile文件內容如下:

FROM centos
RUN yum install -y curl
CMD [ "curl", "-s", "https://ip.cn" ]

如果我們希望顯示 HTTP 頭信息,就需要加上 -i 參數,但是就會報錯。

[root@localhost mydocker]# docker run c18008dfcc35 -i
Error response from daemon: Cannot start container 42d9aaf8ffabde5b000bea14673b4d2be86fa8c66c16d3feccece3dc4d2d2b59: [8] System error: exec: "-i": executable file not found in $PATH

我們可以看到可執行文件找不到的報錯,executable file not found。之前我們說過,跟在鏡像名後面的是 command,運行時會替換 CMD 的默認值。因此這裏的 -i 替換了原來的 CMD,而不是添加在原來的 curl -s http://ip.cn 後面。而 -i 根本不是命令,所以自然找不到。

那麼如果我們希望加入 -i 這參數,我們就必須重新完整的輸入這個命令:

$ docker run myip curl -s http://ip.cn -i

④ ENTRYPOINT測試步驟

複製並修改DockerFile文件爲DockerFile3:

FROM centos
RUN yum install -y curl
ENTRYPOINT [ "curl", "-s", "https://ip.cn" ]

重複上面構建、運行步驟,結果如下:

在這裏插入圖片描述


【5】自定義Tomcat鏡像

① 在/mydocker/路徑下創建路徑mytomcat,並放入jdk與tomcat二進制壓縮包

在這裏插入圖片描述
然後在該目錄下創建文件c.txt:

#純粹爲了copy命令使用
touch c.txt

② 在mytomcat目錄下新建DockerFile文件

內容如下:

FROM         centos
MAINTAINER    jane<jane@qq.com>
#把宿主機當前上下文的c.txt拷貝到容器/usr/local/路徑下
COPY c.txt /usr/local/cincontainer.txt
#把java與tomcat添加到容器中
ADD jdk-8u121-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-8.5.42.tar.gz /usr/local/
#安裝vim編輯器
RUN yum -y install vim
#設置工作訪問時候的WORKDIR路徑,登錄落腳點
ENV MYPATH /usr/local
WORKDIR $MYPATH
#配置java與tomcat環境變量
ENV JAVA_HOME /usr/local/jdk1.8.0_121
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.42
ENV CATALINA_BASE /usr/local/apache-tomcat-8.5.42
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
#容器運行時監聽的端口
EXPOSE  8080
#啓動時運行tomcat
# ENTRYPOINT ["/usr/local/apache-tomcat-8.5.42/bin/startup.sh" ]
# CMD ["/usr/local/apache-tomcat-8.5.42/bin/catalina.sh","run"]
CMD /usr/local/apache-tomcat-8.5.42/bin/startup.sh && tail -f /usr/local/apache-tomcat-8.5.42/logs/catalina.out

③ 構建生成鏡像

命令如下:

docker build -f DockerFile -t mytomcat8.5 .

詳細過程如下所示:

[root@localhost mytomcat]# docker build -f DockerFile -t mytomcat8.5 .
Sending build context to Docker daemon   193 MB
Sending build context to Docker daemon
Step 0 : FROM centos
 ---> 495a24dc98e8
Step 1 : MAINTAINER jane<jane@qq.com>
 ---> Using cache
 ---> b2c306367103
Step 2 : COPY c.txt /usr/local/cincontainer.txt
 ---> 30125b712727
Removing intermediate container e7ce454acc1b
Step 3 : ADD jdk-8u121-linux-x64.tar.gz /usr/local/
 ---> a60edc35c1dd
Removing intermediate container a7d37532c8ed
Step 4 : ADD apache-tomcat-8.5.42.tar.gz /usr/local/
 ---> 835ce1e40fbb
Removing intermediate container 74877ed67a66
Step 5 : RUN yum -y install vim
 ---> Running in 632fbb5d8fab
CentOS-8 - AppStream                            475 kB/s | 6.4 MB     00:13
CentOS-8 - Base                                 249 kB/s | 5.0 MB     00:20
CentOS-8 - Extras                               2.0 kB/s | 2.1 kB     00:01
Dependencies resolved.
================================================================================
 Package             Arch        Version                   Repository      Size
================================================================================
Installing:
 vim-enhanced        x86_64      2:8.0.1763-13.el8         AppStream      1.4 M
Installing dependencies:
 gpm-libs            x86_64      1.20.7-15.el8             AppStream       39 k
 vim-common          x86_64      2:8.0.1763-13.el8         AppStream      6.3 M
 vim-filesystem      noarch      2:8.0.1763-13.el8         AppStream       48 k
 which               x86_64      2.21-10.el8               BaseOS          49 k

Transaction Summary
================================================================================
Install  5 Packages

Total download size: 7.8 M
Installed size: 31 M
Downloading Packages:
(1/5): gpm-libs-1.20.7-15.el8.x86_64.rpm        297 kB/s |  39 kB     00:00
(2/5): vim-filesystem-8.0.1763-13.el8.noarch.rp  27 kB/s |  48 kB     00:01
(3/5): vim-enhanced-8.0.1763-13.el8.x86_64.rpm  667 kB/s | 1.4 MB     00:02
(4/5): which-2.21-10.el8.x86_64.rpm             170 kB/s |  49 kB     00:00
(5/5): vim-common-8.0.1763-13.el8.x86_64.rpm    524 kB/s | 6.3 MB     00:12
--------------------------------------------------------------------------------
Total                                           583 kB/s | 7.8 MB     00:13
warning: /var/cache/dnf/AppStream-02e86d1c976ab532/packages/gpm-libs-1.20.7-15.el8.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID 8483c65d: NOKEY
CentOS-8 - AppStream                            1.3 MB/s | 1.6 kB     00:00
Importing GPG key 0x8483C65D:
 Userid     : "CentOS (CentOS Official Signing Key) <[email protected]>"
 Fingerprint: 99DB 70FA E1D7 CE22 7FB6 4882 05B5 55B3 8483 C65D
 From       : /etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
Key imported successfully
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                        1/1
  Installing       : which-2.21-10.el8.x86_64                               1/5
  Installing       : vim-filesystem-2:8.0.1763-13.el8.noarch                2/5
  Installing       : vim-common-2:8.0.1763-13.el8.x86_64                    3/5
  Installing       : gpm-libs-1.20.7-15.el8.x86_64                          4/5
  Running scriptlet: gpm-libs-1.20.7-15.el8.x86_64                          4/5
  Installing       : vim-enhanced-2:8.0.1763-13.el8.x86_64                  5/5
  Running scriptlet: vim-enhanced-2:8.0.1763-13.el8.x86_64                  5/5
  Running scriptlet: vim-common-2:8.0.1763-13.el8.x86_64                    5/5
  Verifying        : gpm-libs-1.20.7-15.el8.x86_64                          1/5
  Verifying        : vim-common-2:8.0.1763-13.el8.x86_64                    2/5
  Verifying        : vim-enhanced-2:8.0.1763-13.el8.x86_64                  3/5
  Verifying        : vim-filesystem-2:8.0.1763-13.el8.noarch                4/5
  Verifying        : which-2.21-10.el8.x86_64                               5/5

Installed:
  vim-enhanced-2:8.0.1763-13.el8.x86_64 gpm-libs-1.20.7-15.el8.x86_64
  vim-common-2:8.0.1763-13.el8.x86_64   vim-filesystem-2:8.0.1763-13.el8.noarch
  which-2.21-10.el8.x86_64

Complete!
 ---> e810859c3774
Removing intermediate container 632fbb5d8fab
Step 6 : ENV MYPATH /usr/local
 ---> Running in 6f29ac3aab57
 ---> 3046102d4b97
Removing intermediate container 6f29ac3aab57
Step 7 : WORKDIR $MYPATH
 ---> Running in d72543dcc1e5
 ---> 26216526ef34
Removing intermediate container d72543dcc1e5
Step 8 : ENV JAVA_HOME /usr/local/jdk1.8.0_121
 ---> Running in 043966dc5dd5
 ---> 31e881b878b2
Removing intermediate container 043966dc5dd5
Step 9 : ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
 ---> Running in 426decc562b0
 ---> d211b87e14b6
Removing intermediate container 426decc562b0
Step 10 : ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.42
 ---> Running in e7bd1fb680d3
 ---> 5e9d3b1a9842
Removing intermediate container e7bd1fb680d3
Step 11 : ENV CATALINA_BASE /usr/local/apache-tomcat-8.5.42
 ---> Running in 4751834bae65
 ---> 9a8f8a55f9db
Removing intermediate container 4751834bae65
Step 12 : ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
 ---> Running in abcd8a306cb4
 ---> e70a4215675b
Removing intermediate container abcd8a306cb4
Step 13 : EXPOSE 8080
 ---> Running in dd5ea962ca9e
 ---> f70b5c88c7b3
Removing intermediate container dd5ea962ca9e
Step 14 : CMD /usr/local/apache-tomcat-8.5.42/bin/startup.sh && tail -f /usr/local/apache-tomcat-8.5.42/bin/logs/catalina.out
 ---> Running in 2e86e232814e
 ---> 5234d0ef08ec
Removing intermediate container 2e86e232814e
Successfully built 5234d0ef08ec

在這裏插入圖片描述
如下所示,可以查看容器內Java環境:

[root@localhost test]# docker exec 9169df7aa44f java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
[root@localhost test]#

④ 創建容器實例並運行

命令如下:

docker run -d -p 9080:8080 --name mytomcat8 -v /mydocker/mytomcat/test:/usr/local/apache-tomcat-8.5.42/webapps/test -v /mydocker/mytomcat/tomcatlogs/:/usr/local/apache-tomcat-8.5.42/logs --privileged=true mytomcat8.5

在這裏插入圖片描述
可以使用命令查看容器日誌:

 docker logs -f -t --tail 10  712e7776a36e

使用瀏覽器訪問如下,說明正確啓動:
在這裏插入圖片描述
進入容器內部查看:

 docker exec -it 9169df7aa44f  /bin/bash

在這裏插入圖片描述
再次回到宿主機查看/mydocker/mytomcat下:
在這裏插入圖片描述

⑤ test裏面放入項目文件

在test項目裏面放入WEB-INF/web.xml 、a.jsp,將會同步到容器內webapps/test裏面。

宿主機如下:
在這裏插入圖片描述
容器內顯示如下:

#9169df7aa44f 爲容器ID
[root@9169df7aa44f test]# ls
WEB-INF  a.jsp
[root@9169df7aa44f test]#

瀏覽器驗證如下:
在這裏插入圖片描述

總結

宿主機、容器、Dockerfile以及遠程倉庫關係如下圖所示:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章