溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Docker鏡像怎么構(gòu)建

發(fā)布時(shí)間:2021-12-14 10:16:39 來(lái)源:億速云 閱讀:149 作者:iii 欄目:云計(jì)算

本篇內(nèi)容主要講解“Docker鏡像怎么構(gòu)建”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“Docker鏡像怎么構(gòu)建”吧!

Docker鏡像介紹

Docker鏡像是由文件系統(tǒng)疊加而成。最底端是一個(gè)引導(dǎo)文件系統(tǒng)(bootfs),Docker用戶幾乎不會(huì)和引導(dǎo)文件系統(tǒng)有交互,當(dāng)容器啟動(dòng)后它會(huì)被卸載而移動(dòng)到內(nèi)存中。

第二層是root文件系統(tǒng)(rootfs),它位于引導(dǎo)文件系統(tǒng)之上。rootfs可以是一種或多種操作系統(tǒng)。rootfs永遠(yuǎn)是只讀狀態(tài)。

Docker利用聯(lián)合加載(union mount)技術(shù)又會(huì)在rootfs層上加載更多的只讀文件系統(tǒng)。聯(lián)合加載指的是一次同時(shí)加載多個(gè)文件系統(tǒng),但在外部看起來(lái)像是一個(gè)文件系統(tǒng)。聯(lián)合加載會(huì)將各層文件系統(tǒng)疊加到一起,這樣最終的文件系統(tǒng)會(huì)包含所有底層的文件和目錄。

Docker將這樣的文件系統(tǒng)成為鏡像。一個(gè)鏡像可以放到另一個(gè)鏡像的頂部。位于下面的鏡像成為父鏡像,最底部的鏡像成為基礎(chǔ)鏡像。

最后,當(dāng)從一個(gè)鏡像啟動(dòng)容器時(shí),Docker會(huì)在該鏡像的最頂層加載一個(gè)讀寫文件系統(tǒng)。在Docker中運(yùn)行的程序是在這個(gè)讀寫層中執(zhí)行的。

當(dāng)Docker第一次啟動(dòng)一個(gè)容器時(shí),初始的讀寫層是空的。當(dāng)文件系統(tǒng)發(fā)生變化時(shí),這些變化都會(huì)應(yīng)用到這一層上。比如,想修改一個(gè)文件,這個(gè)文件首先會(huì)從該讀寫層下面的只讀層復(fù)制到讀寫層。該文件的只讀版本依然存在,但是已經(jīng)被讀寫層中的該文件副本隱藏。

這種機(jī)制成為寫時(shí)復(fù)制,這也是使Docker強(qiáng)大的技術(shù)之一。每個(gè)只讀鏡像都是只讀的,并且以后永遠(yuǎn)不會(huì)變化。當(dāng)創(chuàng)建一個(gè)容器時(shí),Docker會(huì)構(gòu)建出一個(gè)鏡像棧,并在棧的最頂端添加一個(gè)讀寫層。這個(gè)讀寫層再加上其下面的鏡像層以及一些配置數(shù)據(jù),就構(gòu)成了一個(gè)容器。

列出鏡像

docker images

本地鏡像都保存在Docker宿主機(jī)的/var/lib/docker目錄下,/var/lib/docker/containers目錄中保存著所有的容器。

鏡像從倉(cāng)庫(kù)下載下來(lái)。鏡像保存在倉(cāng)庫(kù)中,而倉(cāng)庫(kù)保存在Registry中。默認(rèn)的Registry是由Docker公司運(yùn)營(yíng)的公共Registry服務(wù),即Docker Hub。可以將鏡像倉(cāng)庫(kù)想象為類似Git倉(cāng)庫(kù)的東西,它包括鏡像、層以及鏡像的元數(shù)據(jù)。

每個(gè)鏡像倉(cāng)庫(kù)可以存放很多鏡像,比如ubuntu倉(cāng)庫(kù)包含了Ubuntu12.04、12.10、13.04等等。使用下面的名利可以把ubuntu倉(cāng)庫(kù)中的鏡像全部拉取到本地:

docker pull ubuntu

為了區(qū)分一個(gè)倉(cāng)庫(kù)中的不同鏡像,Docker提供了標(biāo)簽(功能 ),每個(gè)鏡像都帶有一個(gè)標(biāo)簽。我們可以通過在倉(cāng)庫(kù)名后面加上一個(gè)冒號(hào)和標(biāo)簽名來(lái)指定該倉(cāng)庫(kù)中的某一鏡像:

docker run -t -i --name new_container ubuntu:12.0 /bin/bash

Docker Hub中有兩種類型的倉(cāng)庫(kù):用戶倉(cāng)庫(kù)(user repository)和頂層倉(cāng)庫(kù)(top-level repository)。用戶倉(cāng)庫(kù)的鏡像都是由用戶創(chuàng)建的,而頂層倉(cāng)庫(kù)則是由Docker官方管理的。

用戶倉(cāng)庫(kù)的命名由用戶名和倉(cāng)庫(kù)名兩部分組成,如jamtur01/puppet。前面是用戶名后面是倉(cāng)庫(kù)名。

與之相對(duì),頂層倉(cāng)庫(kù)只包含倉(cāng)庫(kù)名,如ubuntu倉(cāng)庫(kù)。

拉取鏡像

用docker run 命令從鏡像啟動(dòng)一個(gè)容器時(shí),如果該鏡像不在本地,Docker會(huì)先從Docker Hub下載該鏡像。如果沒有指定具體的鏡像標(biāo)簽,那么Docker會(huì)自動(dòng)下載latest標(biāo)簽的鏡像。

也可以使用docker pull命令自己預(yù)先拉取鏡像到本地。下面的命令拉取所有的fedora基礎(chǔ)鏡像:

docker pull fedora

拉取完成后只查看fedora鏡像的內(nèi)容:

docker images fedora

如果只想拉取一種,可以在鏡像名后加標(biāo)簽,例如只拉取Fedora 20:

docker pull fedora:20

查找鏡像

可以使用docker search命令查找所有Docker Hub上公共的可用鏡像:

docker search puppet

上面的命令查找了所有帶puppet的鏡像,返回信息如下:

  • NAME 倉(cāng)庫(kù)名;

  • DESCRIPTION 描述;

  • STARTS 用戶評(píng)價(jià);

  • OFFICIAL  是否官方;

  • AUTOMATED     是否由Docker Hub的自動(dòng)構(gòu)建流程創(chuàng)建的。

 構(gòu)建鏡像

構(gòu)建鏡像由兩種方法:

  • 使用 docker commit 命令;

  • 使用 docker build 命令和Dockerfile文件。

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

一般來(lái)說(shuō)我們不是真正創(chuàng)建新鏡像,而是基于一個(gè)已有的基礎(chǔ)鏡像,如ubuntu、fedora等,構(gòu)建鏡像。

(1)創(chuàng)建并登陸Docker Hub賬號(hào)

注冊(cè)一個(gè)Docker Hub賬號(hào)后,登陸:

docker login

成功登陸后,認(rèn)證信息保存到~/.dockercfg文件中,供后面使用。在我的測(cè)試環(huán)境中未找到~/.dockercfg文件。

(2) 用 docker commit 命令創(chuàng)建鏡像

首先創(chuàng)建一個(gè)新容器:

docker run -i -t ubuntu /bin/bash

接下來(lái)安裝Apache:

apt-get -yqq update

apt-get -y install apache2

使用exti從容器中退出,然后提交:

docker commit 容器ID ivan/apache2

命令指定了要提交修改的容器ID,以及一個(gè)目標(biāo)鏡像倉(cāng)庫(kù)名。

也可以在提交鏡像時(shí)指定更多的數(shù)據(jù)(包括標(biāo)簽)來(lái)詳細(xì)描述:

docker commit -m="A new custom image" --author="Ivan" 容器ID ivan/apache2:webserver

在這條命令里,用 -m 指定了鏡像的提交信息, --author 列出鏡像的作者信息,最后為該鏡像添加了:webserver標(biāo)簽。

可以使用docker inspect命令來(lái)查看鏡像的詳細(xì)信息:

docker inspect ivan/apache2:webserver

(3)用Dockerfile構(gòu)建鏡像

官方推薦使用Dockerfile定義文件和docker build 命令來(lái)構(gòu)建鏡像。Dockerfile使用基本的基于DSL語(yǔ)法(聲明式編程語(yǔ)言)的指令來(lái)構(gòu)建一個(gè)Docker鏡像,之后使用docker build命令基于該Dockerfile中的指令構(gòu)建一個(gè)新的鏡像。

首先需要?jiǎng)?chuàng)建一個(gè)文件夾,然后在這個(gè)文件夾里創(chuàng)建初始的Dockerfile。

mkdir static_web
cd static_web
touch Dockerfile

上述代碼創(chuàng)建了一個(gè)static_web的目錄用來(lái)保存Dockerfile,這個(gè)目錄就是構(gòu)建環(huán)境,Docker稱此為上下文(context)或構(gòu)建上下文(build context)。Docker會(huì)在構(gòu)建鏡像時(shí)將構(gòu)建上下文和該上下文中的文件和目錄上傳到Docker守護(hù)進(jìn)程。這樣Docker守護(hù)進(jìn)程就能直接訪問想在進(jìn)程中存儲(chǔ)的代碼、文件或者其他數(shù)據(jù)。

下面向Dockerfile中添加內(nèi)容:

# Version: 0.0.1
FROM ubuntu:14.04
MAINTAINER James Turnbull "james@example.com"
RUN apt-get update
RUN apt-get install -y nginx
RUN echo "Hi, I am in your container' > /user/share/nginx/html/index.html
EXPOSE 80

該Dockerfile由一系列指令和參數(shù)組成。每條指令,如FROM,都必須是大寫字母且后面要跟隨一個(gè)參數(shù)。Dockerfile中的指令會(huì)按順序從上向下執(zhí)行。

每條指令都會(huì)創(chuàng)建一個(gè)新的鏡像層并對(duì)鏡像進(jìn)行提交。Docker大體上按照如下流程執(zhí)行Dockerfile中的指令:

  1. Docker從集成鏡像運(yùn)行一個(gè)容器;

  2. 執(zhí)行一條指令,對(duì)容器做出修改;

  3. 執(zhí)行類型docker commit的操作,提交一個(gè)新的鏡像層;

  4. Docker再基于剛剛提交的鏡像運(yùn)行一個(gè)新容器;

  5. 執(zhí)行Dockerfile中的下一條指令,直到所有指定都執(zhí)行完畢。

如果Dockerfile由于某些原因沒有正常結(jié)束(如某條指令失敗了),那么將得到一個(gè)可以使用的鏡像。這對(duì)調(diào)試很有幫助:可以基于該鏡像運(yùn)行一個(gè)具備交互功能的容器,使用最后創(chuàng)建的鏡像對(duì)為什么指令會(huì)失敗進(jìn)行調(diào)試。

Dockerfile也支持注釋,以 # 開發(fā)的行都會(huì)被認(rèn)為是注釋。

每個(gè)Dockerfile的第一條指令都應(yīng)該是FROM。FROM指令指定一個(gè)已經(jīng)存在的鏡像,后續(xù)指令都將基于這個(gè)鏡像運(yùn)行,這個(gè)鏡像稱為基礎(chǔ)鏡像。

接著寫入了MAINTAINER指令,這條指令會(huì)告訴Docker該鏡像的作者以及作者的郵件地址。

在這之后指定了三條RUN指令。RUN指令會(huì)在當(dāng)前鏡像中運(yùn)行指定的命令。在這個(gè)例子中,通過RUN指令更新了已經(jīng)安裝的APT倉(cāng)庫(kù),安裝nginx包,之后創(chuàng)建了/usr/share/nginx/html/index.html文件。

默認(rèn)情況下,RUN指令會(huì)在shell里使用命令包裝器/bin/sh -c來(lái)執(zhí)行。如果在一個(gè)不支持shell的平臺(tái)運(yùn)行或者不希望在shell中運(yùn)行,也可以使用exec格式的RUN指令,如:

RUN [“apt-get”, "install", "-y", "nginx"]

接著使用了EXPOSE指令,這條指令告訴Docker該容器內(nèi)的應(yīng)用程序?qū)?huì)使用容器的指定端口。注意,這并不意味著可以自動(dòng)訪問該端口。出于安全的原因,Docker不會(huì)自動(dòng)打開該端口,而是需要在使用docker run運(yùn)行容器時(shí)來(lái)指定需要打開哪些端口。

可以指定多個(gè)EXPOSE指令來(lái)向外部公開多個(gè)端口。

(4)基于Dockerfile構(gòu)建新鏡像

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

cd static_web
docker build -t="ivan/static_web" .

-t 參數(shù)為新鏡像設(shè)置倉(cāng)庫(kù),也可以在構(gòu)建時(shí)為鏡像設(shè)置標(biāo)簽。

docker build -t="ivan/static_web:v1" .

上面兩個(gè)命令中的 . 告訴Docker到本地當(dāng)前目錄找Dockerfile文件。也可以指定一個(gè)Git倉(cāng)庫(kù)的源地址來(lái)指定Dockerfile的位置。

docker build -t="ivan/static_web:v1" git@github.com:ivan/docker-static_web

構(gòu)建過程中,構(gòu)建上下文會(huì)被上傳到Docker守護(hù)進(jìn)程。如果在構(gòu)建上下文的根目錄中存在.dockerignore文件,那么該文件內(nèi)容會(huì)被按行進(jìn)行分割,每一行都是一條文件過濾匹配規(guī)則。匹配通過的文件不會(huì)被上傳到Docker守護(hù)進(jìn)程。該文件中模式的匹配規(guī)則采用了Go語(yǔ)言中的filepath。

(5)指令失敗

如果指令失敗會(huì)返回失敗前構(gòu)建的鏡像,我們可以啟動(dòng)容器加載鏡像檢查失敗原因。

(6)構(gòu)建的緩存

由于每一步的構(gòu)建過程都會(huì)講結(jié)果提交為鏡像,所以之前的鏡像層會(huì)被看做是緩存。比如在構(gòu)建的第四步出錯(cuò),修改后第四步后重新構(gòu)建,由于第一步到第三步未被修改,Docker會(huì)從第四步開始構(gòu)建。如果第一步到第三步之間做了一些修改,Docker會(huì)從發(fā)生變化的第一條指令開始構(gòu)建。

有時(shí)構(gòu)建時(shí)不希望利用緩存可以加入--no-cache標(biāo)志:

docker build --no-chace -t-"inva/static_web"

(7)基于構(gòu)建緩存的Dockerfile模板

一般在Dockerfile文件的開頭都會(huì)使用相同的指令集模板,比如

FROM ubuntu:14.04
MAINTAINER James Turnbull "james@example.com"
ENV REPERESHED_AT 2016-07-08
RUN apt-get -qq update

前兩條指令的運(yùn)行結(jié)果不會(huì)改變,第三條指令使用ENV創(chuàng)建了一個(gè)REFRESHED_AT環(huán)境變量,這個(gè)環(huán)境變量用來(lái)表明該鏡像模板最后的更新時(shí)間。最后使用RUN指令來(lái)運(yùn)行apt-get -qq update指令。該指令運(yùn)行時(shí)會(huì)刷新APT包的緩存,用來(lái)確保將要安裝的每個(gè)軟件包都更新到最新版本。

對(duì)于這個(gè)模板,如果想刷新一個(gè)構(gòu)建,只需要修改ENV指令中的日期。

(8)查看新鏡像

可以使用docker images 來(lái)查看新構(gòu)建的鏡像。

使用docker history命令深入了解該鏡像是怎么構(gòu)建的:

docker history 鏡像ID

(9)從新鏡像啟動(dòng)容器

上面的例子中構(gòu)建了一個(gè)nginx鏡像,現(xiàn)在啟動(dòng)它看看是否正常:

docker run -d -p 80 --name static_web ivan/static_web nginx -g "daemon off";

命令中參數(shù) -d 表示容器以守護(hù)方式運(yùn)行,nginx -g "daemon off"是需要在容器中運(yùn)行的命令。

新出現(xiàn)的參數(shù) -p 控制Docker在運(yùn)行時(shí)應(yīng)該公開哪些網(wǎng)絡(luò)端口給宿主機(jī)。運(yùn)行一個(gè)容器時(shí),Docker可以通過兩種方法來(lái)在宿主機(jī)上分配端口:

  • Docker可以在宿主機(jī)上隨機(jī)選擇一個(gè)位于49153~65535的一個(gè)比較大的端口號(hào)來(lái)映射到容器中的指定端口(例子中是80);

  • 可以在Docker宿主機(jī)中指定一個(gè)具體的端口號(hào)來(lái)映射到容器中的指定端口上(例子中是80)。

使用 docker ps 命令可以查看端口分配情況。

也可以通過docker port查看容器的端口映射情況:

docker port 容器ID 80

上面的名利指定了向查看映射情況的容器ID和容器端口號(hào),返回的將是宿主機(jī)中映射的端口號(hào)。

docker run 的 -p 選項(xiàng)可以靈活的指定容器和宿主機(jī)之間的端口映射關(guān)系。比如指定將容器中的端口映射到Docker宿主機(jī)的某一特定端口上:

docker run -d -p 80:80 --name static_web ivan/static_web nginx -g "daemon off";

頁(yè)可以將容器內(nèi)的端口綁定到特定的IP的端口上:

docker run -d -p 127.0.0.1:80:80 --name static_web ivan/static_web nginx -g "daemon off";

將容器內(nèi)的80端口綁定到宿主機(jī)127.0.0.1這個(gè)IP的80端口上。

也可以綁定到一個(gè)宿主機(jī)的特定IP的隨機(jī)端口上:

docker run -d -p 127.0.0.1::80 --name static_web ivan/static_web nginx -g "daemon off";

使用 -P 參數(shù),可以用來(lái)將Dockerfile中EXPOSE指令設(shè)置的端口綁定到宿主機(jī)的隨機(jī)端口上:

docker run -d -P --name static_web ivan/static_web nginx -g "daemon off";

在端口綁定時(shí)使用/udp后綴來(lái)指定UPD端口綁定。

在得到宿主機(jī)的綁定IP和端口后可以使用curl來(lái)測(cè)試nginx:

curl 127.0.0.1:端口號(hào)

(10)Dockerfile指令

  • CMD 

用于指定一個(gè)容器啟動(dòng)時(shí)要運(yùn)行的命令。類似于RUN指令,但是RUN指令是在指定鏡像被構(gòu)建時(shí)要運(yùn)行的命令,而CMD是指定容器被啟動(dòng)時(shí)要運(yùn)行的命令。這和docker run命令啟動(dòng)容器指定要運(yùn)行的命令是一樣的。

CMD ["/bin/bash", "-l]

例子中要運(yùn)行的命令存放在一個(gè)數(shù)組結(jié)構(gòu)中。這將告訴Docker按指定的原樣來(lái)運(yùn)行該命令。也可以不使用數(shù)組,這時(shí)候Docker會(huì)在指定的命令前加上/bin/sh -c。這在執(zhí)行該命令的時(shí)候可能會(huì)導(dǎo)致意料之外的行為,所以Docker推薦一直使用以數(shù)組語(yǔ)法來(lái)設(shè)置要執(zhí)行的命令。

使用docker run命令時(shí)指定參數(shù)會(huì)覆蓋Dockerfile中的CMD命令。

在Dockerfile中只能指定一條CMD指令。如果指定了多條,也只有最后一條CMD指令會(huì)被使用。如果想在啟動(dòng)容器時(shí)運(yùn)行多個(gè)進(jìn)程或者多條命令,可以考慮使用類似Supervisor這樣的服務(wù)管理工具。

  • ENTRYPOINT

與CMD相似也是指定一些要運(yùn)行的命令。如果在Dockerfile中指定了ENTRYPOINT,CMD指令或docker run指定的命令參數(shù)都會(huì)被當(dāng)做參數(shù)再次傳遞給ENTRYPOIN指定的命令。

例如

ENTRYPOINT ["/user/bin/nginx"]

重新構(gòu)建鏡像后啟動(dòng):

docker run -t -i ivan/static_web -g "daemon off;"

這樣-g "daemon off;"就會(huì)傳遞給ENTRYPOINT,組成一條命令。

也可以組合使用ENTRYPOINT和CMD指令:

ENTRYPOINT ["/user/bin/nginx"]
CMD ["-h"]

此時(shí)當(dāng)啟動(dòng)一個(gè)容器,如果指定-g "daemon off;"參數(shù)就會(huì)讓Nginx守護(hù)進(jìn)程以前臺(tái)方式運(yùn)行。如果在啟動(dòng)容器的時(shí)候不指定任何參數(shù),則CMD中的-h就會(huì)傳遞給/user/bin/nginx,顯示Nginx的幫助信息。

這使我們可以構(gòu)建一個(gè)鏡像,該鏡像既可以運(yùn)行一個(gè)默認(rèn)的命令,也支持通過docker run為該命令指定可覆蓋的選項(xiàng)或者標(biāo)志。

也可以在docker run中指定--entrypoint標(biāo)志覆蓋ENTRYPOINT指令。

  • WORKDIR

用來(lái)為Dockerfile中后續(xù)的一系列指令設(shè)置工作目錄,也可以為最終的容器設(shè)置工作目錄:

WORKDIR /opt/webapp/db
RUN bundle install
WORKDIR /opt/webapp
ENTRYPOINT ["rackup"]

例子中將工作目錄切換為/opt/webapp/db后運(yùn)行了bundle install命令,之后又將工作目錄設(shè)置為/opt/webapp,最后設(shè)置了ENTRYPOINT。

docker run 命令可以使用-w覆蓋WORKDIR。

  • ENV

用來(lái)在鏡像構(gòu)建過程中指定環(huán)境變量:

ENV RVM_PATH /home/rvm/

這個(gè)新環(huán)境變量可以在后續(xù)的任何RUN指令中使用。

也可以在其他指令中直接使用這些環(huán)境變量:

ENV TARGET_DIR /opt/app
WORKDIR $TARGET_DIR

如果需要可以通過在環(huán)境變量前加上一個(gè)反斜線來(lái)進(jìn)行轉(zhuǎn)義。

這些環(huán)境變量會(huì)被持久保存到從我們的鏡像創(chuàng)建的任何容器中。

也可以使用docker run -e來(lái)傳遞環(huán)境變量,但這些環(huán)境變量只會(huì)在運(yùn)行時(shí)有效:

docker run -ti -e "WEB-PORT=8080" ubuntu env
  • USER

用來(lái)指定該鏡像以什么用戶運(yùn)行,可以指定用戶名或UID,組或GID,也可以是兩者的組合:

USER user
USER user:group
USER uid
USER uid:gid
USER user:gid
USER uid:group

也可以在docker run 命令中通過-u 選項(xiàng)來(lái)覆蓋USER指定的值。

如果不指定,默認(rèn)用戶為root。

  • VOLUME

用來(lái)向基于鏡像創(chuàng)建的容器添加卷。一個(gè)卷是可以存在于一個(gè)或者多個(gè)容器內(nèi)的特定目錄。這個(gè)目錄可以繞過聯(lián)合文件系統(tǒng),并提供如下功能:

  • 卷可以在容器間共享和重用;

  • 一個(gè)容器可以不必須和其他容器共享卷;

  • 對(duì)卷的修改是立刻生效的;

  • 對(duì)卷的修改不會(huì)對(duì)更新鏡像產(chǎn)生影響;

  • 卷會(huì)一直存在直到?jīng)]有任何容器再使用它。

VOLUMN ["/opt/project","/data"]

這條指令將會(huì)為基于此鏡像創(chuàng)建的任何容器創(chuàng)建兩個(gè)掛載點(diǎn)。

  • ADD

用來(lái)將構(gòu)建環(huán)境下的文件和目錄復(fù)制到鏡像中。

ADD software.lic /opt/application/software.lic

ADD指令將構(gòu)建目錄下的software.lic文件復(fù)制到鏡像中去。

源文件的位置可以是一個(gè)URL,或者構(gòu)建上下文中的文件名或目錄。不能對(duì)構(gòu)建目錄之外的文件進(jìn)行ADD操作。

在ADD文件時(shí),Docker通過目的地址參數(shù)末尾的字符來(lái)判斷文件源是目錄還是文件。如果目的地址以/結(jié)尾,那么Docker認(rèn)為源位置指向的是目錄;如果目的地址不以/結(jié)尾,那么Docker就認(rèn)為源位置指向的是文件。

如果源文件是本地歸檔文件(合法的歸檔文件包括gzip、bzip2和xz),Docker會(huì)自動(dòng)將歸檔文件解開:

ADD lastest.tar.gz /var/www/wordpress/

上例將歸檔文件解壓到/var/www/wordpress/目錄下。Docker解開歸檔文件的行為和使用帶-x選項(xiàng)的tar命令一樣:原目的目錄已經(jīng)存在的內(nèi)容加上歸檔文件中的內(nèi)容。如果目的位置的目錄下已經(jīng)存在了和歸檔文件同名的文件或者目錄,目的位置中的文件或者目錄不會(huì)被覆蓋。

截止到1.0.0版本還不能解壓URL方式制定的歸檔文件。

如果目的位置不存在,Docker將會(huì)為我們創(chuàng)建這個(gè)全路徑,包括路徑中的任何目錄。新創(chuàng)建的文件和目錄的模式為0755,并且UID和GID是0.

ADD命令會(huì)使得構(gòu)建緩存無(wú)效。

  • COPY

類似于ADD,它只復(fù)制文件而不會(huì)做提取和解壓。

COPY conf.d /etc/apache2/

這條指令會(huì)將本地conf.d目錄中的文件復(fù)制到/etc/apache2/目錄中。

文件源路徑必須是在構(gòu)建目錄中。

任何由該指令創(chuàng)建的文件或者目錄的UID和GID都會(huì)設(shè)置為0.

如果目的目錄不存在,Docker會(huì)自動(dòng)創(chuàng)建所有需要的目錄結(jié)構(gòu)。

  • ONBUILD

為鏡像添加觸發(fā)器。當(dāng)一個(gè)鏡像被用做其他鏡像的基礎(chǔ)鏡像時(shí),該鏡像中的觸發(fā)器會(huì)被執(zhí)行。

觸發(fā)器會(huì)在構(gòu)建過程中插入新指令,可以認(rèn)為這些指令是緊跟在FROM之后指定的。觸發(fā)器可以是任何構(gòu)建指令:

ONBUILD ADD . /app/src
ONBUILD RUN cd /app/src && make

但是FROM、MAINTAINER和ONBUILD不能用于ONBUILD指令,為了防止在Dockerfile構(gòu)建過程中產(chǎn)生遞歸調(diào)用的問題。

使用docker inspect 容器ID可以查看容器使用的鏡像的ONBUILD指令信息。

ONBUILD觸發(fā)器會(huì)按照在父鏡像中指定的順序執(zhí)行,并且只能被繼承一次(即只能在子鏡像中執(zhí)行,而不會(huì)再孫鏡像中執(zhí)行)。

 將鏡像推送到Docker Hub上

docker push ivan/static_web

還可以進(jìn)行自動(dòng)構(gòu)建,只需要將Github或BitBucket中含有Dockerfile文件的倉(cāng)庫(kù)連接到Docker Hub即可。向這個(gè)代碼倉(cāng)庫(kù)推送代碼時(shí),將會(huì)觸發(fā)一次鏡像構(gòu)建活動(dòng)并創(chuàng)建一個(gè)新鏡像。

點(diǎn)擊Dockr Hub網(wǎng)站右上角的Create下面的Create Automated Build,關(guān)聯(lián)一個(gè)Github賬號(hào)然后在Github網(wǎng)站上做授權(quán)確認(rèn)。成功后返回Docker Hub點(diǎn)擊“Create Auto-build”,選擇一個(gè)Github Repository并輸入描述就創(chuàng)建成功了。

 刪除鏡像

docker rmi ivan/static_web

從刪除命令的輸出可以看出Docker的分層文件系統(tǒng),每個(gè)Deleted行都代表一個(gè)鏡像層被刪除。

上述操作只會(huì)將本地的鏡像刪除。如果之前已經(jīng)將該鏡像推送到Docker Hub上,它在Docker Hub上將依然存在。如果想刪除Docker Hub上的鏡像倉(cāng)庫(kù),需要登錄Docker Hub執(zhí)行刪除操作。

還可以指定一個(gè)鏡像名列表來(lái)刪除多個(gè)鏡像:

docker rmi ivan/apache2 ivan/static_web

刪除全部鏡像的技巧:

docker rmi 'docker images -a -q'

 運(yùn)行自己的Docker Registry

有兩種選擇:

  • 利用Docker Hub上的私有倉(cāng)庫(kù);

  • 運(yùn)行自己的Registry。

Docker公司開源了運(yùn)行Docker Registry當(dāng)然代碼,可以基于此運(yùn)行自己的Registry。

(1)從容器中運(yùn)行Registry

docker run -p 5000:5000 registry

啟動(dòng)一個(gè)Registry應(yīng)用的容器,并綁定到宿主機(jī)的5000端口。

運(yùn)行完成后在瀏覽器輸入地址:宿主機(jī)IP:5000;看到信息:"docker-registry server",說(shuō)明Registry Server啟動(dòng)成功了。

(2)提交鏡像到自己的Registry

成功運(yùn)行了Registry容器,但是無(wú)法提交,原因是不知道主機(jī)名,自己認(rèn)為的localhost是不對(duì)的。

經(jīng)過測(cè)試用127.0.0.1是可以的。

首先將已有的鏡像打上新的Registry標(biāo)簽

docker tag 鏡像ID 127.0.0.1:5000/ivan/static_web

最后將鏡像提交

docker push 127.0.0.1:5000/ivan/static_web

到此,相信大家對(duì)“Docker鏡像怎么構(gòu)建”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI