濮阳杆衣贸易有限公司

主頁 > 知識(shí)庫 > docker使用Dockerfile構(gòu)建鏡像的方法

docker使用Dockerfile構(gòu)建鏡像的方法

熱門標(biāo)簽:外呼系統(tǒng)不彈窗 申請400電話價(jià)格多少 外呼系統(tǒng)的經(jīng)營范圍 云會(huì)外呼系統(tǒng) 柳州市機(jī)器人外呼系統(tǒng)報(bào)價(jià) 涪陵商都400電話開通辦理 智能電話機(jī)器人坐席 安陽ai電銷機(jī)器人軟件 廈門營銷外呼系統(tǒng)平臺(tái)

構(gòu)建鏡像

前面我們使用各種鏡像進(jìn)行測試演示,很多情況下我們是需要自己的鏡像,滿足自己業(yè)務(wù)需要的鏡像,這就需要我們能夠定制自己需要的鏡像,構(gòu)建 Docker 鏡像有以下兩種方法。

  • 使用 docker commit 命令。
  • 使用 docker build 命令和 Dockerfile 構(gòu)建文件。

現(xiàn)在我們不推薦使用 docker commit 命令,而應(yīng)該使用更靈活、更強(qiáng)大的 Dockerfile 來構(gòu)建 Docker 鏡像。

1、使用 commit 命令構(gòu)建

docker commit 命令是創(chuàng)建新鏡像最直觀的方法,其過程包含三個(gè)步驟:

  • 運(yùn)行容器;
  • 修改容器;
  • 將容器保存為新的鏡像。

先從創(chuàng)建一個(gè)新容器開始,這個(gè)容器我們就使用很常見的 ubuntu 鏡像,操作步驟如下

1.1 運(yùn)行一個(gè)要進(jìn)行修改的容器

root@ubuntu:~# docker run -ti ubuntu /bin/bash
root@733a4b080491:/#

1.2 安裝 Apache 軟件包

root@733a4b080491:/# apt-get update
... ...
root@733a4b080491:/# apt-get install -y apache2
... ...

我們啟動(dòng)了一個(gè)容器,并在里面安裝了 Apache 。我們將會(huì)拿這個(gè)容器作為一個(gè) Web 服務(wù)器來運(yùn)行,我們需要把它保存下來,這樣就不用每次都運(yùn)行這個(gè)步驟了。

1.3 提交定制容器

root@ubuntu:~# docker ps -a
CONTAINER ID  IMAGE    COMMAND    CREATED    STATUS      PORTS    NAMES
733a4b080491  ubuntu    "/bin/bash"   11 minutes ago  Exited (0) 5 seconds ago      suspicious_mestorf
root@ubuntu:~# docker commit 733a4b080491 wzlinux/ubuntu_with_apache
sha256:902ac2c87147fefc5b70c741ce9550dcda426cea9f824f442d5cc2744bdc90ae
root@ubuntu:~# docker images
REPOSITORY     TAG     IMAGE ID   CREATED    SIZE
wzlinux/ubuntu_with_apache latest    902ac2c87147  33 seconds ago  261MB
ubuntu      latest    20c44cd7596f  10 days ago   123MB

可以看到,我們使用 docker commit 提交了修改過的容器,從 size 上可以看到鏡像因?yàn)榘惭b軟件而變大了,docker commit 提交的只是創(chuàng)建容器的鏡像與容器的當(dāng)前狀態(tài)之間有差異的部分,這使得該更新非常輕量。

以上演示了如何用 docker commit 創(chuàng)建新鏡像。然而,Docker 并不建議用戶通過這種方式構(gòu)建鏡像。因?yàn)檫@是一種手工創(chuàng)建鏡像的方式,容易出錯(cuò),效率低且可重復(fù)性弱。比如要在 debian base 鏡像中也加入 apache,還得重復(fù)前面的所有步驟。更重要的:使用者并不知道鏡像是如何創(chuàng)建出來的,里面是否有惡意程序。也就是說無法對鏡像進(jìn)行審計(jì),存在安全隱患。

不過,為了對 Docker 有一個(gè)更全面的了解,我們還是要了解一下如何使用 docker commit 構(gòu)建 Docker 鏡像。因?yàn)榧幢闶怯?Dockerfile(推薦方法)構(gòu)建鏡像,底層也 docker commit 一層一層構(gòu)建新鏡像的。學(xué)習(xí) docker commit 能夠幫助我們更加深入地理解構(gòu)建過程和鏡像的分層結(jié)構(gòu)。

2、使用 Dockerfile 構(gòu)建

Dockerfile 使用基本的基于DSL(Domain Specific Language)語法的指令來構(gòu)建一個(gè) Docker 鏡像,我們推薦使用 Dockerfile 方法來代替 docker commit,因?yàn)橥ㄟ^前者構(gòu)建鏡像更具備可重復(fù)性、透明性以及冪等性。

一旦有了 Dockerfile,我們就可以使用 docker build 命令基于該 Dockerfile 中的指令構(gòu)建一個(gè)新的鏡像。

2.1 我們的第一個(gè) Dockerfile

用 Dockerfile 創(chuàng)建上面的 ubuntu_with_apache,內(nèi)容如下。

# Version 0.0.1
FROM ubuntu
RUN sed -i 's/archive.ubuntu.com/cn.archive.ubuntu.com/g' /etc/apt/sources.list
RUN sed -i 's/security.ubuntu/cn.archive.ubuntu/g' /etc/apt/sources.list
RUN apt-get -y update && apt-get -y install apache2
EXPOSE 80

執(zhí)行 docker build 命令時(shí),Dockerfile 中的所有指令都會(huì)被執(zhí)行并且提交,并且在該命令成功結(jié)束后返回一個(gè)新鏡像。

root@ubuntu:~/sample# docker build -t ubuntu_with_apache_dockerfile .  ①
Sending build context to Docker daemon 6.144kB  ②
Step 1/5 : FROM ubuntu   ③
 ---> 20c44cd7596f
Step 2/5 : RUN sed -i 's/archive.ubuntu.com/cn.archive.ubuntu.com/g' /etc/apt/sources.list
 ---> Running in bac6dc3b900f
 ---> c66ad94ad8a4
Removing intermediate container bac6dc3b900f
Step 3/5 : RUN sed -i 's/security.ubuntu/cn.archive.ubuntu/g' /etc/apt/sources.list
 ---> Running in 5158558b6403
 ---> 0a4c480147c5
Removing intermediate container 5158558b6403
Step 4/5 : RUN apt-get -y update && apt-get -y install apache2    ④
 ---> Running in f547ce7a1b39   ⑤
 ……
 ……
 ---> 118bde35120a   ⑥
Removing intermediate container f547ce7a1b39  ⑦
Step 5/5 : EXPOSE 80
 ---> Running in e546786de05b
 ---> f55d7b07365b
Removing intermediate container e546786de05b
Successfully built f55d7b07365b   ⑧
Successfully tagged ubuntu_with_apache_dockerfile:latest


① 運(yùn)行 docker build 命令,-t 將新鏡像命名為 ubuntu-with-apache-dockerfile,命令末尾的 . 指明 build context 為當(dāng)前目錄。Docker 默認(rèn)會(huì)從 build context 中查找 Dockerfile 文件,我們也可以通過 -f 參數(shù)指定 Dockerfile 的位置。

② 從這步開始就是鏡像真正的構(gòu)建過程。 首先 Docker 將 build context 中的所有文件發(fā)送給 Docker daemon。build context 為鏡像構(gòu)建提供所需要的文件或目錄。

Dockerfile 中的 ADD、COPY 等命令可以將 build context 中的文件添加到鏡像。此例中,build context 為當(dāng)前目錄 /sample,該目錄下的所有文件和子目錄都會(huì)被發(fā)送給 Docker daemon。

所以,使用 build context 就得小心了,不要將多余文件放到 build context,特別不要把 /、/usr 作為 build context,否則構(gòu)建過程會(huì)相當(dāng)緩慢甚至失敗。

③ Step 1:執(zhí)行 FROM,將 ubuntu 作為 base 鏡像。ubuntu 鏡像 ID 為 452a96d81c30。

④ Step 4:執(zhí)行 RUN,安裝 apache,具體步驟為 ⑤ ~ ⑬。

⑤ 啟動(dòng) ID 為 e38bc83df8b1 的臨時(shí)容器,在容器中通過 apt-get 安裝 apache。

⑥ 安裝成功后,將容器保存為鏡像,其 ID 為 fbc9af08328d。這一步底層使用的是類似 docker commit 的命令。

⑦ 刪除臨時(shí)容器 02a4f3243dda。

⑧ 鏡像構(gòu)建成功。

通過 docker images 查看鏡像信息。

root@ubuntu:~/sample# docker images
REPOSITORY      TAG     IMAGE ID   CREATED    SIZE
ubuntu_with_apache_dockerfile latest    f55d7b07365b  27 minutes ago  261MB
wzlinux/ubuntu_with_apache  latest    902ac2c87147  About an hour ago 261MB
ubuntu       latest    20c44cd7596f  10 days ago   123MB

2.2 查看鏡像分成結(jié)構(gòu)

ubuntu_with_apache_dockerfile 是通過在 base 鏡像的頂部添加幾個(gè)新的鏡像層而得到的。

上圖是從原文中拷貝的,下圖是在我的電腦上面實(shí)驗(yàn)得到的數(shù)據(jù),IMAGE的ID不同,但是其他都是相同的。


查看我本機(jī)的Ubuntu的IMAGE歷史如下:


從輸出的結(jié)果可以看出來,每個(gè)命令都會(huì)生成一個(gè)鏡像層。

docker history 會(huì)顯示鏡像的構(gòu)建歷史,也就是 Dockerfile 的執(zhí)行過程。

ubuntu_with_apache_dockerfile 與 ubuntu 鏡像相比,確實(shí)只是多了幾層,Dockerfile 中的每個(gè)指令都會(huì)創(chuàng)建一層,docker history 也向我們展示了鏡像的分層結(jié)構(gòu),每一層由上至下排列。

2.3 鏡像的緩存特性

由于每一步的構(gòu)建過程都會(huì)將結(jié)果提交為鏡像,所以 Docker 的構(gòu)建鏡像過程就顯得非常聰明。它會(huì)將之前的鏡像層看作緩存。

比如我們把 EXPOSE 80 改為 EXPOSE 8080。

root@ubuntu:~/sample# docker build -t ubuntu_with_apache_8080 .   
Sending build context to Docker daemon 6.144kB
Step 1/5 : FROM ubuntu 
---> 20c44cd7596f
Step 2/5 : RUN sed -i 's/archive.ubuntu.com/cn.archive.ubuntu.com/g'  /etc/apt/sources.list
 ---> Using cache ---> c66ad94ad8a4Step 3/5 : RUN sed -i 's/security.ubuntu/cn.archive.ubuntu/g' /etc/apt/sources.list 
---> Using cache 
---> 0a4c480147c5
Step 4/5 : RUN apt-get -y update && apt-get -y install apache2 
---> Using cache 
---> 118bde35120a
Step 5/5 : EXPOSE 8080 
---> Running in c89f8210c56a 
---> ac88967e578e
Removing intermediate container c89f8210c56a
Successfully built ac88967e578e
Successfully tagged ubuntu_with_apache_8080:latest

我們可以看到,之前的指令都是一樣的,所以 docker 直接利用之前的緩存,只構(gòu)建我們更改的指令,新的鏡像層如下。


如果我們希望在構(gòu)建鏡像時(shí)不使用緩存,可以在 docker build 命令中加上 --no-cache 參數(shù)。

Dockerfile 中每一個(gè)指令都會(huì)創(chuàng)建一個(gè)鏡像層,上層是依賴于下層的。無論什么時(shí)候,只要某一層發(fā)生變化,其上面所有層的緩存都會(huì)失效。也就是說,如果我們改變 Dockerfile 指令的執(zhí)行順序,或者修改或添加指令,都會(huì)使緩存失效。比如我們在前面添加指令 MAINTAINER wzlinux "admin@wzlinux.com"。如下:

# Version 0.0.1
FROM ubuntu
MAINTAINER wzlinux "admin@wzlinux.com"
RUN sed -i 's/archive.ubuntu.com/cn.archive.ubuntu.com/g' /etc/apt/sources.list
RUN sed -i 's/security.ubuntu/cn.archive.ubuntu/g' /etc/apt/sources.list
RUN apt-get -y update && apt-get -y install apache2
EXPOSE 80

然后使用docker進(jìn)行構(gòu)建,查看其過程。

root@ubuntu:~/sample# docker build -t ubuntu_with_apache_author .

Sending build context to Docker daemon 6.144kB
Step 1/6 : FROM ubuntu
 ---> 20c44cd7596f
Step 2/6 : MAINTAINER wzlinux "admin@wzlinux.com" 
---> Running in 637bb3457407 
---> 829b24531d69
Removing intermediate container 637bb3457407
Step 3/6 : RUN sed -i 's/archive.ubuntu.com/cn.archive.ubuntu.com/g' /etc/apt/sources.list 
---> Running in 416ae8aefb61 
---> 84643fe8447a
Removing intermediate container 416ae8aefb61
Step 4/6 : RUN sed -i 's/security.ubuntu/cn.archive.ubuntu/g' /etc/apt/sources.list 
---> Running in 58d8375fd5c3 
---> 1cb5776982d3
Removing intermediate container 58d8375fd5c3
Step 5/6 : RUN apt-get -y update && apt-get -y install apache2 
---> Running in 0514a7d04814
 ……
 ……
Processing triggers for sgml-base (1.26+nmu4ubuntu1)
 ... 
---> 30eb21527fee
Removing intermediate container 0514a7d04814
Step 6/6 : EXPOSE 80 
---> Running in 476ca5f98886 
---> 30672998f3d0
Removing intermediate container 476ca5f98886
Successfully built 30672998f3d0
Successfully tagged ubuntu_with_apache_author:latest


從輸出的結(jié)果生成了很多新的鏡像層,緩存已經(jīng)失效。

2.4 調(diào)試 Dockerfile

包括 Dockerfile 在內(nèi)的任何腳本和程序都會(huì)出錯(cuò)。有錯(cuò)并不可怕,但必須有辦法排查,那我們測試一下在構(gòu)建的過程中指令出現(xiàn)錯(cuò)誤怎么辦,比如我們把第二個(gè)sed指令寫錯(cuò)了,寫錯(cuò)了sd。

# Version 0.0.1
FROM ubuntu
MAINTAINER wzlinux "admin@wzlinux.com"
RUN sed -i 's/archive.ubuntu.com/cn.archive.ubuntu.com/g' /etc/apt/sources.list
RUN sd -i 's/security.ubuntu/cn.archive.ubuntu/g' /etc/apt/sources.list
RUN apt-get -y update && apt-get -y install apache2
EXPOSE 80

執(zhí)行 docker build,如下。


Dockerfile 在執(zhí)行第四步 RUN 指令時(shí)失敗。我們可以利用第三步創(chuàng)建的鏡像 84643fe8447a 進(jìn)行調(diào)試,方式是通過 docker run -it 啟動(dòng)鏡像的一個(gè)容器。

root@ubuntu:~/sample# docker run -ti 84643fe8447a /bin/bash
root@422ecce78664:/# sd
bash: sd: command not found

其實(shí)我們肯定不會(huì)傻到連 sd 不存在也不知道,我這里只是作為一個(gè)例子,其他更難的排錯(cuò)方法我們就使用這種方式。

2.5 Dockerfile 指令

FROM
指定 base 鏡像。

MAINTAINER
設(shè)置鏡像的作者,可以是任意字符串。

COPY
將文件從 build context 復(fù)制到鏡像。
COPY 支持兩種形式:
COPY src destCOPY ["src", "dest"]
注意:src 只能指定 build context 中的文件或目錄。

ADD
與 COPY 類似,從 build context 復(fù)制文件到鏡像。不同的是,如果 src 是歸檔文件(tar, zip, tgz, xz 等),文件會(huì)被自動(dòng)解壓到 dest。

ENV
設(shè)置環(huán)境變量,環(huán)境變量可被后面的指令使用。例如:

ENV MY_VERSION 1.3RUN apt-get install -y mypackage=$MY_VERSION

EXPOSE
指定容器中的進(jìn)程會(huì)監(jiān)聽某個(gè)端口,Docker 可以將該端口暴露出來。

VOLUME
將文件或目錄聲明為 volume。

WORKDIR
為后面的 RUN, CMD, ENTRYPOINT, ADD 或 COPY 指令設(shè)置鏡像中的當(dāng)前工作目錄。

RUN
在容器中運(yùn)行指定的命令。

CMD
容器啟動(dòng)時(shí)運(yùn)行指定的命令。
Dockerfile 中可以有多個(gè) CMD 指令,但只有最后一個(gè)生效。CMD 可以被 docker run 之后的參數(shù)替換。

ENTRYPOINT
設(shè)置容器啟動(dòng)時(shí)運(yùn)行的命令。
Dockerfile 中可以有多個(gè) ENTRYPOINT 指令,但只有最后一個(gè)生效。CMD 或 docker run 之后的參數(shù)會(huì)被當(dāng)做參數(shù)傳遞給 ENTRYPOINT。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

標(biāo)簽:蕪湖 晉城 孝感 綏化 巴中 撫順 南充 福州

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《docker使用Dockerfile構(gòu)建鏡像的方法》,本文關(guān)鍵詞  docker,使用,Dockerfile,構(gòu)建,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《docker使用Dockerfile構(gòu)建鏡像的方法》相關(guān)的同類信息!
  • 本頁收集關(guān)于docker使用Dockerfile構(gòu)建鏡像的方法的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    天全县| 文昌市| 泸水县| 天津市| 绥芬河市| 灵武市| 田东县| 珲春市| 白玉县| 拉孜县| 古丈县| 滨海县| 武隆县| 阿尔山市| 肥西县| 忻州市| 个旧市| 辽阳市| 古交市| 武山县| 湘西| 乐陵市| 汉寿县| 宿州市| 政和县| 宁安市| 乌鲁木齐县| 孙吴县| 印江| 江安县| 甘肃省| 司法| 额尔古纳市| 河北省| 亳州市| 高淳县| 伊川县| 阳信县| 芮城县| 京山县| 石嘴山市|