共計(jì) 10229 個(gè)字符,預(yù)計(jì)需要花費(fèi) 26 分鐘才能閱讀完成。
本篇內(nèi)容主要講解“Docker 鏡像怎么構(gòu)建”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓丸趣 TV 小編來帶大家學(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),但在外部看起來像是一個(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 目錄中保存著所有的容器。
鏡像從倉庫下載下來。鏡像保存在倉庫中,而倉庫保存在 Registry 中。默認(rèn)的 Registry 是由 Docker 公司運(yùn)營(yíng)的公共 Registry 服務(wù),即 Docker Hub。可以將鏡像倉庫想象為類似 Git 倉庫的東西,它包括鏡像、層以及鏡像的元數(shù)據(jù)。
每個(gè)鏡像倉庫可以存放很多鏡像,比如 ubuntu 倉庫包含了 Ubuntu12.04、12.10、13.04 等等。使用下面的名利可以把 ubuntu 倉庫中的鏡像全部拉取到本地:
docker pull ubuntu
為了區(qū)分一個(gè)倉庫中的不同鏡像,Docker 提供了標(biāo)簽(功能 ),每個(gè)鏡像都帶有一個(gè)標(biāo)簽。我們可以通過在倉庫名后面加上一個(gè)冒號(hào)和標(biāo)簽名來指定該倉庫中的某一鏡像:
docker run -t -i --name new_container ubuntu:12.0 /bin/bash
Docker Hub 中有兩種類型的倉庫:用戶倉庫(user repository)和頂層倉庫(top-level repository)。用戶倉庫的鏡像都是由用戶創(chuàng)建的,而頂層倉庫則是由 Docker 官方管理的。
用戶倉庫的命名由用戶名和倉庫名兩部分組成,如 jamtur01/puppet。前面是用戶名后面是倉庫名。
與之相對(duì),頂層倉庫只包含倉庫名,如 ubuntu 倉庫。
拉取鏡像
用 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 倉庫名;
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 來構(gòu)建 Docker 鏡像。
一般來說我們不是真正創(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
接下來安裝 Apache:
apt-get -yqq update
apt-get -y install apache2
使用 exti 從容器中退出,然后提交:
docker commit 容器 ID ivan/apache2
命令指定了要提交修改的容器 ID,以及一個(gè)目標(biāo)鏡像倉庫名。
也可以在提交鏡像時(shí)指定更多的數(shù)據(jù)(包括標(biāo)簽)來詳細(xì)描述:
docker commit -m= A new custom image --author= Ivan 容器 ID ivan/apache2:webserver
在這條命令里,用 -m 指定了鏡像的提交信息,–author 列出鏡像的作者信息,最后為該鏡像添加了:webserver 標(biāo)簽。
可以使用 docker inspect 命令來查看鏡像的詳細(xì)信息:
docker inspect ivan/apache2:webserver
(3)用 Dockerfile 構(gòu)建鏡像
官方推薦使用 Dockerfile 定義文件和 docker build 命令來構(gòu)建鏡像。Dockerfile 使用基本的基于 DSL 語法(聲明式編程語言)的指令來構(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 的目錄用來保存 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 中的指令:
Docker 從集成鏡像運(yùn)行一個(gè)容器;
執(zhí)行一條指令,對(duì)容器做出修改;
執(zhí)行類型 docker commit 的操作,提交一個(gè)新的鏡像層;
Docker 再基于剛剛提交的鏡像運(yùn)行一個(gè)新容器;
執(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 倉庫,安裝 nginx 包,之后創(chuàng)建了 /usr/share/nginx/html/index.html 文件。
默認(rèn)情況下,RUN 指令會(huì)在 shell 里使用命令包裝器 /bin/sh - c 來執(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í)來指定需要打開哪些端口。
可以指定多個(gè) EXPOSE 指令來向外部公開多個(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è)置倉庫,也可以在構(gòu)建時(shí)為鏡像設(shè)置標(biāo)簽。
docker build -t= ivan/static_web:v1 .
上面兩個(gè)命令中的 . 告訴 Docker 到本地當(dāng)前目錄找 Dockerfile 文件。也可以指定一個(gè) Git 倉庫的源地址來指定 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 語言中的 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)境變量用來表明該鏡像模板最后的更新時(shí)間。最后使用 RUN 指令來運(yùn)行 apt-get -qq update 指令。該指令運(yùn)行時(shí)會(huì)刷新 APT 包的緩存,用來確保將要安裝的每個(gè)軟件包都更新到最新版本。
對(duì)于這個(gè)模板,如果想刷新一個(gè)構(gòu)建,只需要修改 ENV 指令中的日期。
(8)查看新鏡像
可以使用 docker images 來查看新構(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 可以通過兩種方法來在宿主機(jī)上分配端口:
Docker 可以在宿主機(jī)上隨機(jī)選擇一個(gè)位于 49153~65535 的一個(gè)比較大的端口號(hào)來映射到容器中的指定端口(例子中是 80);
可以在 Docker 宿主機(jī)中指定一個(gè)具體的端口號(hào)來映射到容器中的指定端口上(例子中是 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
頁可以將容器內(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ù),可以用來將 Dockerfile 中 EXPOSE 指令設(shè)置的端口綁定到宿主機(jī)的隨機(jī)端口上:
docker run -d -P --name static_web ivan/static_web nginx -g daemon off
在端口綁定時(shí)使用 /udp 后綴來指定 UPD 端口綁定。
在得到宿主機(jī)的綁定 IP 和端口后可以使用 curl 來測(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 按指定的原樣來運(yùn)行該命令。也可以不使用數(shù)組,這時(shí)候 Docker 會(huì)在指定的命令前加上 /bin/sh -c。這在執(zhí)行該命令的時(shí)候可能會(huì)導(dǎo)致意料之外的行為,所以 Docker 推薦一直使用以數(shù)組語法來設(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
用來為 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
用來在鏡像構(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è)反斜線來進(jìn)行轉(zhuǎn)義。
這些環(huán)境變量會(huì)被持久保存到從我們的鏡像創(chuàng)建的任何容器中。
也可以使用 docker run - e 來傳遞環(huán)境變量,但這些環(huán)境變量只會(huì)在運(yùn)行時(shí)有效:
docker run -ti -e WEB-PORT=8080 ubuntu env
USER
用來指定該鏡像以什么用戶運(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)來覆蓋 USER 指定的值。
如果不指定,默認(rèn)用戶為 root。
VOLUME
用來向基于鏡像創(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
用來將構(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ù)末尾的字符來判斷文件源是目錄還是文件。如果目的地址以 / 結(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)建緩存無效。
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 文件的倉庫連接到 Docker Hub 即可。向這個(gè)代碼倉庫推送代碼時(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 上的鏡像倉庫,需要登錄 Docker Hub 執(zhí)行刪除操作。
還可以指定一個(gè)鏡像名列表來刪除多個(gè)鏡像:
docker rmi ivan/apache2 ivan/static_web
刪除全部鏡像的技巧:
docker rmi docker images
-a -q
運(yùn)行自己的 Docker Registry
有兩種選擇:
利用 Docker Hub 上的私有倉庫;
運(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,說明 Registry Server 啟動(dòng)成功了。
(2)提交鏡像到自己的 Registry
成功運(yùn)行了 Registry 容器,但是無法提交,原因是不知道主機(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)建”有了更深的了解,不妨來實(shí)際操作一番吧!這里是丸趣 TV 網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!