Docker專題(七)-DockerFile詳解

1.DockerFile是什麼

當我們從docker鏡像倉庫中下載的鏡像不能滿足我們的需求時,我們可以通過以下兩種方式對鏡像進行更改。

1.從已經創建的容器中更新鏡像,並且提交這個鏡像
2.使用 Dockerfile 指令來創建一個新的鏡像

Dockerfile是用來構建Docker鏡像的構建文件,是由一系列命令和參數構成的腳本。DockerFile是描述鏡像的一種文件!

DockerFile是鏡像的說明書,裏面有一系列的執行,告訴Docker如何構建鏡像!

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

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

  • 在Docker中創建鏡像最常用的方式,就是使用Dockerfile。Dockerfile是一個Docker鏡像的描述文件,我們可以理解成火箭發射的A、B、C、D…的步驟。Dockerfile其內部包含了一條條的指令,每一條指令構建一層,因此每一條指令的內容,就是描述該層應當如何構建。
    在這裏插入圖片描述

  • Docker鏡像,在用Dockerfile定義一個文件之後,docker build時會產生一個Docker鏡像,當運行 Docker鏡像時,會真正開始提供服務;

  • Docker容器,容器是直接提供服務的。

  • 構建三步驟

編寫Dockerfile文件 -----> 編寫DockerFile文件
docker build      -----> 構建鏡像
docker run        -----> 使用鏡像啓動容器

DockerFile就是鏡像的描述文件!

2.DockerFile文件什麼樣

2.1.以我們熟悉的CentOS爲例

網站:https://hub.docker.com/_/centos/
在這裏插入圖片描述
在這裏插入圖片描述

2.2.一個Dockerfile的示例如下所示

#基於centos鏡像
FROM centos

#維護人的信息
MAINTAINER The CentOS Project <[email protected]>

#安裝httpd軟件包
RUN yum -y update
RUN yum -y install httpd

#開啓80端口
EXPOSE 80

#複製網站首頁文件至鏡像中web站點下
ADD index.html /var/www/html/index.html

#複製該腳本至鏡像中,並修改其權限
ADD run.sh /run.sh
RUN chmod 775 /run.sh

#當啓動容器時執行的腳本文件
CMD ["/run.sh"]
由上可知,Dockerfile結構大致分爲四個部分:
  (1)基礎鏡像信息
  (2)維護者信息
  (3)鏡像操作指令
  (4)容器啓動時執行指令。
Dockerfile每行支持一條指令,每條指令可帶多個參數,支持使用以#號開頭的註釋。下面會對上面使用到的一些常用指令做一些介紹。

2.3.DockerFile構建過程解析

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

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

  • 小結
    從應用軟件的角度來看,Dockerfile、Docker鏡像與Docker容器分別代表軟件的三個不同階段:
    1:Dockerfile是軟件的原材料
    2:Docker鏡像是軟件的交付品
    3**:Docker容器**則可以認爲是軟件的運行態。

3.Dockerfile常用指令

在這裏插入圖片描述

3.1.FROM

指明構建的新鏡像是來自於哪個基礎鏡像,例如:

FROM centos:6

基礎鏡像不存在會在Docker Hub上拉去(一般會是文件的第一個指令) 使用格式:
FROM <鏡像>:[tag]

3.2.MAINTAINER

指明鏡像維護着及其聯繫方式(一般是郵箱地址),例如

MAINTAINER BRUCELIU<[email protected]>

不過,MAINTAINER並不推薦使用,更推薦使用LABEL來指定鏡像作者,例如:

LABEL maintainer="bruceliu.cn"

[逐漸廢棄] LABLE --替代MAINTANIER 具體使用: LABLE maintainer=“作者信息”

3.3.RUN

RUN 指令是用來執行命令行命令的。由於命令行的強大能力,RUN 指令在定製鏡像時是最常用的指令之一。其格式有兩種:
• shell 格式:RUN <命令>,就像直接在命令行中輸入的命令一樣。剛纔寫的 Dockerfile 中的 RUN 指令就是這種格式.
• exec 格式:RUN [“可執行文件”, “參數1”, “參數2”],這更像是函數調用中的格式。
使用格式:

RUN RUN ["","",""]

構建鏡像時運行的Shell命令,例如:

RUN ["yum", "install", "httpd"]

RUN yum install httpd

RUN 就像 Shell 腳本一樣可以執行命令,那麼我們是否就可以像 Shell 腳本一樣把每個命令對應一個 RUN 呢?比如
這樣:

RUN apt-get update
RUN apt-get install -y gcc libc6-dev make
RUN wget http://download.redis.io/releases/redis-4.0.1.tar.gz
RUN tar xzf redis-4.0.1.tar.gz
RUN cd redis-4.0.1

Dockerfile 中每一個指令都會建立一層,RUN 也不例外。每一個 RUN 的行爲,和剛纔我們手工建立鏡像的過程一樣:新建立一層,在其上執行這些命令,執行結束後,commit 這一層的修改,構成新的鏡像。 而上面的這種寫法,創建了 多 層鏡像。這是完全沒有意義的,而且很多運行時不需要的東西,都被裝進了鏡像裏,比如編譯環境、更新的軟件包等等。結果就是產生非常臃腫、非常多層的鏡像,不僅僅增加了構建部署的時間,也很容易出錯。 這是很多初學 Docker 的人常犯的一個錯誤。

Union FS 是有最大層數限制的,比如 AUFS,曾經是最大不得超過 42 層,現在是不得超過 127 層。上面的Dockerfile 正確的寫法應該是這樣

FROM centos

RUN apt-get update \
&& apt-get install -y gcc libc6-dev make \
&& wget http://download.redis.io/releases/redis-4.0.1.tar.gz \
&& tar xzf redis-4.0.1.tar.gz \
&& cd redis-4.0.1

首先,之前所有的命令只有一個目的,就是編譯、安裝 redis 可執行文件。因此沒有必要建立很多層,這只是一層的事情。因此,這裏沒有使用很多個 RUN 對一一對應不同的命令,而是僅僅使用一個 RUN 指令,並使用 && 將各個所需命令串聯起來。將之前的 7 層,簡化爲了 1 層。

在撰寫 Dockerfile 的時候,要經常提醒自己,這並不是在寫Shell 腳本,而是在定義每一層該如何構建且,這裏爲了格式化還進行了換行。Dockerfile 支持 Shell 類的行尾添加 \ 的命令換行方式,以及行首 # 進行註釋的格式。良好的格式,比如換行、縮進、註釋等,會讓維護、排障更爲容易,這是一個比較好的習慣。

3.4.CMD

啓動容器時執行的Shell命令,例如:

CMD ["-C", "/start.sh"] 
CMD ["/usr/sbin/sshd", "-D"] 
CMD /usr/sbin/sshd -D

3.5.EXPOSE

聲明容器運行的服務端口,爲容器打開指定要監聽的端口以實現與外部通信,例如:

EXPOSE 80 443

3.6.ENV

ENV指令可以用於爲docker容器設置環境變量 ENV設置的環境變量,可以使用 docker inspect命令來查看。同時還可以使用docker run --env =來修改環境變量。

具體用法:
ENV JAVA_HOME /usr/local/jdk
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/:$JRE_HOME/lib/
ENV PATH $PATH:$JAVA_HOME/bin/

3.7.ADD

類似COPY命令,拷貝文件或目錄到鏡像中,例如:

ADD <src>...<dest>

ADD html.tar.gz /var/www/html
ADD https://xxx.com/html.tar.gz /var/www/html

3.8.COPY

拷貝文件或目錄到鏡像中,用法同ADD,只是不支持自動下載和解壓,例如:

COPY ./start.sh /start.sh

3.9.ENTRYPOINT

啓動容器時執行的Shell命令,同CMD類似,只是由ENTRYPOINT啓動的程序不會被docker run命令行指定的參數所覆蓋,而且,這些命令行參數會被當作參數傳遞給ENTRYPOINT指定指定的程序,例如:

ENTRYPOINT ["/bin/bash", "-C", "/start.sh"]
ENTRYPOINT /bin/bash -C '/start.sh'

PS:Dockerfile文件中也可以存在多個ENTRYPOINT指令,但僅有最後一個會生效。

3.10. VOLUME

創建一個可以從本地主機或其他容器掛載的掛載點,一般用來存放數據庫和需要保持的數據等。例如:

VOLUME ["/var/lib/mysql"]

只能定義docker管理的卷: VOLUME /data/mysql運行的時候會隨機在宿主機的目錄下生成一個卷目錄!
一般不會在Dockerfile中用到,更常見的還是在docker run的時候指定-v數據卷。

3.11 USER

爲RUN、CMD和ENTRYPOINT執行Shell命令指定運行用戶,例如:

USER <user>[:<usergroup>]
USER <UID>[:<UID>]
USER bruceliu

3.12 WORKDIR

Docker 默認的工作目錄是/,只有 RUN 能執行 cd 命令切換目錄,而且還只作用在當下下的 RUN,也就是說每一個 RUN 都是獨立進行的。

如果想讓其他指令在指定的目錄下執行,就得靠 WORKDIR。WORKDIR 動作的目錄改變是持久的,不用每個指令前都使用一次 WORKDIR。

WORKDIR /usr/local/tomcat/

3.13.小總結

在這裏插入圖片描述

4.DockerFile案例

4.1.Base鏡像(scratch)

Docker Hub 中 99% 的鏡像都是通過在 base 鏡像中安裝和配置需要的軟件構建出來的
在這裏插入圖片描述

4.2.自定義鏡像mycentos

Docker Hub默認CentOS鏡像什麼情況??
在這裏插入圖片描述

  • 準備編寫DockerFile文件
[root@localhost myfile]# pwd
/root/myfile
[root@localhost myfile]# vi mycentos_dockerfile
  • myCentOS內容DockerFile
FROM centos
MAINTAINER bruceliu<bruceliu167@126.com>

ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "success--------------ok"
CMD /bin/bash
  • 構建
    命令:

docker build -t 新鏡像名字:TAG .
會看到 docker build 命令最後有一個 .
. 表示當前目錄

[root@localhost myfile]# docker build -f /root/myfile/mycentos_dockerfile -t mycentos:1.3 .
Sending build context to Docker daemon 2.048 kB
Step 1/10 : FROM centos
 ---> 9f38484d220f
Step 2/10 : MAINTAINER bruceliu<bruceliu167@126.com>
 ---> Using cache
 ---> 281446cb753d
Step 3/10 : ENV MYPATH /usr/local
 ---> Using cache
 ---> 2e09cdb61576
Step 4/10 : WORKDIR $MYPATH
 ---> Using cache
 ---> 4aa136d65f26
Step 5/10 : RUN yum -y install vim
 ---> Using cache
 ---> 585392f09407
Step 6/10 : RUN yum -y install net-tools
 ---> Using cache
 ---> 9c7971b08e59
Step 7/10 : EXPOSE 80
 ---> Using cache
 ---> 6741c0b61390
Step 8/10 : CMD echo $MYPATH
 ---> Using cache
 ---> fb1b4b72ba02
Step 9/10 : CMD echo "success--------------ok"
 ---> Using cache
 ---> 3d636347cc9a
Step 10/10 : CMD /bin/bash
 ---> Using cache
 ---> 720d4eb5c5f0
Successfully built 720d4eb5c5f0
  • 運行
    docker run -it 新鏡像名字:TAG
    可以看到,我們自己的新鏡像已經支持vim/ifconfig命令,擴展成功了。
[root@localhost ~]# docker images
REPOSITORY            TAG                 IMAGE ID            CREATED                  SIZE
docker.io/mongo       latest              9c02a5a12c52        Less than a second ago   413 MB
mycentos              1.3                 720d4eb5c5f0        50 minutes ago           480 MB
bruceliu/centos9527   latest              071e944a589b        8 hours ago              202 MB
bruceliu/tomcat       7-jre7              a66f9aba334d        13 hours ago             359 MB
docker.io/tomcat      7-jre7              47c156f4d4e3        5 weeks ago              359 MB
docker.io/mysql       latest              7bb2586065cd        2 months ago             477 MB
docker.io/centos      7                   9f38484d220f        3 months ago             202 MB
docker.io/centos      latest              9f38484d220f        3 months ago             202 MB
[root@localhost ~]# docker run -it mycentos:1.3
[root@50784a17d114 local]# pwd
/usr/local
[root@50784a17d114 local]# vi 1.txt
[root@50784a17d114 local]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.3  netmask 255.255.0.0  broadcast 0.0.0.0
        inet6 fe80::42:acff:fe11:3  prefixlen 64  scopeid 0x20<link>
        ether 02:42:ac:11:00:03  txqueuelen 0  (Ethernet)
        RX packets 8  bytes 656 (656.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8  bytes 656 (656.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
  • 列出鏡像的變更歷史
    命令:

docker history 鏡像名

[root@localhost ~]# docker history 720d4eb5c5f0
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
720d4eb5c5f0        53 minutes ago      /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "/b...   0 B                 
3d636347cc9a        53 minutes ago      /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "ec...   0 B                 
fb1b4b72ba02        53 minutes ago      /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "ec...   0 B                 
6741c0b61390        53 minutes ago      /bin/sh -c #(nop)  EXPOSE 80/tcp                0 B                 
9c7971b08e59        53 minutes ago      /bin/sh -c yum -y install net-tools             112 MB              
585392f09407        54 minutes ago      /bin/sh -c yum -y install vim                   167 MB              
4aa136d65f26        About an hour ago   /bin/sh -c #(nop) WORKDIR /usr/local            0 B                 
2e09cdb61576        About an hour ago   /bin/sh -c #(nop)  ENV MYPATH=/usr/local        0 B                 
281446cb753d        About an hour ago   /bin/sh -c #(nop)  MAINTAINER bruceliu<bru...   0 B                 
9f38484d220f        3 months ago        /bin/sh -c #(nop)  CMD ["/bin/bash"]            0 B                 
<missing>           3 months ago        /bin/sh -c #(nop)  LABEL org.label-schema....   0 B                 
<missing>           3 months ago        /bin/sh -c #(nop) ADD file:074f2c974463ab3...   202 MB   

5.小結

在這裏插入圖片描述

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