Dockerfile自定義鏡像
1) Dockerfile介紹
Dockerfile 是自動(dòng)構(gòu)建 docker鏡像的配置文件, 用戶可以使用 Dockerfile 快速創(chuàng)建自定義的鏡像。Dockerfile 中的命令非常類似于linux 下的 shell 命令。
我們可以通過(guò)下面這幅圖來(lái)直觀地感受下 Docker 鏡像、容器和 Dockerfile 三者之間的關(guān)系。
image.png
我們從上圖中可以看到, Dockerfile 可以自定義鏡像,通過(guò) Docker 命令去運(yùn)行鏡像,從而達(dá)到啟動(dòng)容器的目的。
2) Dockerfile的基本結(jié)構(gòu)
Dockerfile 是由一行行命令語(yǔ)句組成,并且支持已 # 開(kāi)頭的注釋行。
一般來(lái)說(shuō),我們可以將 Dockerfile 分為四個(gè)部分:
基礎(chǔ)鏡像(父鏡像)信息指令 FROM
維護(hù)者信息指令 MAINTAINER
鏡像操作指令 RUN 、 EVN 、 ADD 和 WORKDIR 等
容器啟動(dòng)指令 CMD 、ENTRYPOINT 和 USER 等
3)使用 Dockerfile 定制鏡像/自定義鏡像
Q
為什么要自定義Docker鏡像?
A
工作中Docker中的鏡像并不滿足工作的需要,需要進(jìn)行自己的配置。
Docker Hub 中 99% 的鏡像都是通過(guò)在base 鏡像中安裝和配置需要的軟件構(gòu)建出來(lái)的
4) 使用 Docker build 構(gòu)建鏡像創(chuàng)建容器的步驟
第一步 編寫(xiě)Dockerfile文件
第二步 Docker build
第三步 Docker run
4-1 企業(yè)案例通過(guò)Dockerfile自定義Centos鏡像
docker pull centos
image.png
官方鏡像 docker run -i -t
Snipaste_2020-02-23_09-31-23.jpg
官方進(jìn)行我們執(zhí)行的命令不支持,顯然是不符合我們需求的
image.png
【注意】現(xiàn)在我們需要自定義一個(gè)鏡像來(lái)支持 VIM、ifconfig、并且登錄后的默認(rèn)路徑改做修改。
企業(yè)級(jí)案例
一、拉一個(gè)基礎(chǔ)centos鏡像
docker pull centos
二、編寫(xiě)dockerfile文件
vim Dockerfile
#從哪一個(gè)基礎(chǔ)鏡像構(gòu)建
FROM centos
#定義作者的信息
MAINTAINER 1907
#定義一個(gè)變量
ENV newpath /tmp
#設(shè)置登錄以后工作路徑(落腳點(diǎn))
WORKDIR $newpath
#干了什么(執(zhí)行你要的操作)
RUN yum install -y vim
RUN yum install -y net-tools
##如果有更多的需求 。。。RUN
#開(kāi)放指定的端口
EXPOSE 80
EXPOSE 22
#執(zhí)行命令
CMD echo $newpath
CMD echo "success ok"
CMD /bin/bash
~
三、通過(guò)dockerfile文件創(chuàng)建鏡像
[root@localhost home]# docker build -f Dockerfile -t azkaban/custom_centos:v1 .
Sending build context to Docker daemon 5.632kB
Step 1/11 : FROM centos
---> 470671670cac
Step 2/11 : MAINTAINER 1907
---> Running in d24bf9043207
Removing intermediate container d24bf9043207
---> 159ad59927d2
Step 3/11 : ENV newpath /tmp
---> Running in 5fa9a2ebc28c
Removing intermediate container 5fa9a2ebc28c
---> c6bec0ee09b9
Step 4/11 : WORKDIR $newpath
---> Running in ab29e7e49eda
Removing intermediate container ab29e7e49eda
---> f79d02d81a18
Step 5/11 : RUN yum install -y vim
---> Running in 9474c83bfe6c
CentOS-8 - AppStream 342 kB/s | 6.4 MB 00:19
CentOS-8 - Base 113 kB/s | 5.0 MB 00:44
CentOS-8 - Extras 1.9 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 50 kB/s | 39 kB 00:00
(2/5): vim-filesystem-8.0.1763-13.el8.noarch.rp 239 kB/s | 48 kB 00:00
(3/5): which-2.21-10.el8.x86_64.rpm 121 kB/s | 49 kB 00:00
(4/5): vim-common-8.0.1763-13.el8.x86_64.rpm 573 kB/s | 6.3 MB 00:11
[MIRROR] vim-enhanced-8.0.1763-13.el8.x86_64.rpm: Curl error (28): Timeout was reached for http://mirrors.ustc.edu.cn/centos/8.1.1911/AppStream/x86_64/os/Packages/vim-enhanced-8.0.1763-13.el8.x86_64.rpm [Operation too slow. Less than 1000 bytes/sec transferred the last 30 seconds]
(5/5): vim-enhanced-8.0.1763-13.el8.x86_64.rpm 44 kB/s | 1.4 MB 00:31
--------------------------------------------------------------------------------
Total 208 kB/s | 7.8 MB 00:38
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.6 MB/s | 1.6 kB 00:00
Importing GPG key 0x8483C65D:
Userid : "CentOS (CentOS Official Signing Key) <security@centos.org>"
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!
Removing intermediate container 9474c83bfe6c
---> d1773a676980
Step 6/11 : RUN yum install -y net-tools
---> Running in c28e68f52b0e
Last metadata expiration check: 0:00:47 ago on Sun Feb 23 01:59:52 2020.
Dependencies resolved.
================================================================================
Package Architecture Version Repository Size
================================================================================
Installing:
net-tools x86_64 2.0-0.51.20160912git.el8 BaseOS 323 k
Transaction Summary
================================================================================
Install 1 Package
Total download size: 323 k
Installed size: 1.0 M
Downloading Packages:
net-tools-2.0-0.51.20160912git.el8.x86_64.rpm 1.1 MB/s | 323 kB 00:00
--------------------------------------------------------------------------------
Total 112 kB/s | 323 kB 00:02
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : net-tools-2.0-0.51.20160912git.el8.x86_64 1/1
Running scriptlet: net-tools-2.0-0.51.20160912git.el8.x86_64 1/1
Verifying : net-tools-2.0-0.51.20160912git.el8.x86_64 1/1
Installed:
net-tools-2.0-0.51.20160912git.el8.x86_64
Complete!
Removing intermediate container c28e68f52b0e
---> 9de3592d6946
Step 7/11 : EXPOSE 80
---> Running in 5569cdc7691d
Removing intermediate container 5569cdc7691d
---> 3a16923f249c
Step 8/11 : EXPOSE 22
---> Running in 272964d43403
Removing intermediate container 272964d43403
---> 66a7ac68030b
Step 9/11 : CMD echo $newpath
---> Running in 86d6d8655e4b
Removing intermediate container 86d6d8655e4b
---> bb617cf4c488
Step 10/11 : CMD echo "success ok"
---> Running in 876412b8e523
Removing intermediate container 876412b8e523
---> 96915955be0c
Step 11/11 : CMD /bin/bash
---> Running in 809bd856d4fa
Removing intermediate container 809bd856d4fa
---> 2ba838e1b3ae
Successfully built 2ba838e1b3ae
Successfully tagged azkaban/custom_centos:v1
自己構(gòu)建的鏡像成功 docker images查看
image.png
四 通過(guò)Docker run 創(chuàng)建容器,,驗(yàn)證vim 以及net-tools
通過(guò)我們自定義的鏡像創(chuàng)建容器
image.png
測(cè)試ifconfig命令 OK
測(cè)試vim 命令OK
image.png
看看構(gòu)建過(guò)程是否是如前面所說(shuō),這也證實(shí)了鏡像的分層
image.png
4)Dockerfile鏡像分層
dockerfile中的每一條命令,都會(huì)構(gòu)建一層文件。

以下圖的Dockerfile為例分析構(gòu)建過(guò)程


當(dāng)容器啟動(dòng)時(shí),一個(gè)新的可寫(xiě)層被加載到鏡像的頂部。這一層通常被稱作“容器層”,“容器層”之下的都叫“鏡像層”。
image.png
所有對(duì)容器的改動(dòng) - 無(wú)論添加、刪除、還是修改文件都只會(huì)發(fā)生在容器層中。
只有容器層是可寫(xiě)的,容器層下面的所有鏡像層都是只讀的。
下面我們深入討論容器層的細(xì)節(jié)。
鏡像層數(shù)量可能會(huì)很多,所有鏡像層會(huì)聯(lián)合在一起組成一個(gè)統(tǒng)一的文件系統(tǒng)。如果不同層中有一個(gè)相同路徑的文件,比如 /a,上層的 /a 會(huì)覆蓋下層的 /a,也就是說(shuō)用戶只能訪問(wèn)到上層中的文件 /a。在容器層中,用戶看到的是一個(gè)疊加之后的文件系統(tǒng)。
1.添加文件
在容器中創(chuàng)建文件時(shí),新文件被添加到容器層中。
讀取文件
在容器中讀取某個(gè)文件時(shí),Docker 會(huì)從上往下依次在各鏡像層中查找此文件。一旦找到,打開(kāi)并讀入內(nèi)存。
修改文件
在容器中修改已存在的文件時(shí),Docker 會(huì)從上往下依次在各鏡像層中查找此文件。一旦找到,立即將其復(fù)制到容器層,然后修改之。
刪除文件
在容器中刪除文件時(shí),Docker 也是從上往下依次在鏡像層中查找此文件。找到后,會(huì)在容器層中記錄下此刪除操作。
只有當(dāng)需要修改時(shí)才復(fù)制一份數(shù)據(jù),這種特性被稱作 Copy-on-Write??梢?jiàn),容器層保存的是鏡像變化的部分,不會(huì)對(duì)鏡像本身進(jìn)行任何修改。
這樣就解釋了我們前面提出的問(wèn)題:容器層記錄對(duì)鏡像的修改,所有鏡像層都是只讀的,不會(huì)被容器修改,所以鏡像可以被多個(gè)容器共享。
5) Dockerfile指令詳解
一張圖搞定Dockerfile常見(jiàn)命令
image.png
Dockerfile中包括FROM、MAINTAINER、RUN、CMD、EXPOSE、ENV、ADD、COPY、ENTRYPOINT、VOLUME、USER、WORKDIR、ONBUILD等13個(gè)指令。
FROM
格式為FROM image或FROM image:tag,并且Dockerfile中第一條指令必須是FROM指令,且在同一個(gè)Dockerfile中創(chuàng)建多個(gè)鏡像時(shí),可以使用多個(gè)FROM指令。
MAINTAINER
格式為MAINTAINER user_name user_email,指定維護(hù)者信息
RUN
格式為RUN command或 RUN ["EXECUTABLE","PARAM1","PARAM2".....],前者在shell終端中運(yùn)行命令,/bin/sh -c command,例如:/bin/sh -c "echo hello";后者使用exec執(zhí)行,指定其他運(yùn)行終端使用RUN["/bin/bash","-c","echo hello"]
每條RUN指令將當(dāng)前的鏡像基礎(chǔ)上執(zhí)行指令,并提交為新的鏡像,命令較長(zhǎng)的時(shí)候可以使用\來(lái)?yè)Q行。
CMD
支持三種格式:
CMD ["executable","param1","param2"],使用exec執(zhí)行,這是推薦的方式。
CMD command param1 param2 在/bin/sh中執(zhí)行。
CMD ["param1","param2"] 提供給ENTERYPOINT的默認(rèn)參數(shù)。
CMD用于指定容器啟動(dòng)時(shí)執(zhí)行的命令,每個(gè)Dockerfile只能有一個(gè)CMD命令,多個(gè)CMD命令只執(zhí)行最后一個(gè)。若容器啟動(dòng)時(shí)指定了運(yùn)行的命令,則會(huì)覆蓋掉CMD中指定的命令。
EXPOSE
格式為 EXPOSE port [port2,port3,...],例如EXPOSE 80這條指令告訴Docker服務(wù)器暴露80端口,供容器外部連接使用。
在啟動(dòng)容器的使用使用-P,Docker會(huì)自動(dòng)分配一個(gè)端口和轉(zhuǎn)發(fā)指定的端口,使用-p可以具體指定使用哪個(gè)本地的端口來(lái)映射對(duì)外開(kāi)放的端口。
ENV
格式為:EVN key value 。用于指定環(huán)境變量,這些環(huán)境變量,后續(xù)可以被RUN指令使用,容器運(yùn)行起來(lái)之后,也可以在容器中獲取這些環(huán)境變量。
例如
ENV word hello
RUN echo $word
ADD
格式:ADD src dest
該命令將復(fù)制指定本地目錄中的文件到容器中的dest中,src可以是一個(gè)絕對(duì)路徑,也可以是一個(gè)URL或一個(gè)tar文件,tar文件會(huì)自動(dòng)解壓為目錄。
COPY
格式為:COPY src desc
復(fù)制本地主機(jī)src目錄或文件到容器的desc目錄,desc不存在時(shí)會(huì)自動(dòng)創(chuàng)建。
ENTRYPOINT
格式有兩種:
ENTRYPOINT ["executable","param1","param2"]
ENTRYPOINT command param1,param2 會(huì)在shell中執(zhí)行。
用于配置容器啟動(dòng)后執(zhí)行的命令,這些命令不能被docker run提供的參數(shù)覆蓋。和CMD一樣,每個(gè)Dockerfile中只能有一個(gè)ENTRYPOINT,當(dāng)有多個(gè)時(shí)最后一個(gè)生效。
VOLUME
格式為 VOLUME ["/data"]
作用是創(chuàng)建在本地主機(jī)或其他容器可以掛載的數(shù)據(jù)卷,用來(lái)存放數(shù)據(jù)。
USER
格式為:USER username
指定容器運(yùn)行時(shí)的用戶名或UID,后續(xù)的RUN也會(huì)使用指定的用戶。要臨時(shí)使用管理員權(quán)限可以使用sudo。在USER命令之前可以使用RUN命令創(chuàng)建需要的用戶。
例如:RUN groupadd -r docker && useradd -r -g docker docker
WORKDIR
格式: WORKDIR /path
為后續(xù)的RUN CMD ENTRYPOINT指定配置工作目錄,可以使用多個(gè)WORKDIR指令,若后續(xù)指令用得是相對(duì)路徑,則會(huì)基于之前的命令指定路徑。
ONBUILD
格式ONBUILD [INSTRUCTION]
該配置指定當(dāng)所創(chuàng)建的鏡像作為其他新建鏡像的基礎(chǔ)鏡像時(shí)所執(zhí)行的指令。
例如下面的Dockerfile創(chuàng)建了鏡像A:
ONBUILD ADD . /app
ONBUILD RUN python app.py
則基于鏡像A創(chuàng)建新的鏡像時(shí),新的Dockerfile中使用from A 指定基鏡像時(shí),自動(dòng)執(zhí)行ONBBUILD指令內(nèi)容,等價(jià)于在新的要構(gòu)建鏡像的Dockerfile中增加了兩條指令:
FROM A
ADD ./app
RUN python app.py
docker build
創(chuàng)建好Dockerfile之后,通過(guò)docker build命令來(lái)創(chuàng)建鏡像,該命令首先會(huì)上傳Dockerfile文件給Docker服務(wù)器端,服務(wù)器端將逐行執(zhí)行Dockerfile中定義的指令。
通常建議放置Dockerfile的目錄為空目錄。另外可以在目錄下創(chuàng)建.dockerignore文件,讓Docker忽略路徑下的文件和目錄,這一點(diǎn)與Git中的配置很相似。
通過(guò) -t 指定鏡像的標(biāo)簽信息,例如:docker build -t regenzm/first_image . ## "."指定的是Dockerfile所在的路徑
例:
簡(jiǎn)單 使用 Dockerfile文件事例









