日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線(xiàn)咨詢(xún)客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

目錄
  • 前言
  • 一、Dockerfile介紹
  • 二、FROM指定基礎(chǔ)鏡像
  • 三、RUN執(zhí)行命令
  • 四、構(gòu)建鏡像
  • 五、鏡像構(gòu)建上下文(Context)
  • 六、遷移鏡像

前言

鏡像的定制實(shí)際上就是定制每?層所添加的配置、?件等信息。

但是命令畢竟只是命令,一般用 docker commit 每次定制都得去重復(fù)執(zhí)?這個(gè)命令,?且還不夠直觀,如果我們可以把每?層修改、安裝、構(gòu)建、操作的命令都寫(xiě)??個(gè)腳本,?這個(gè)腳本來(lái)構(gòu)建、定制鏡像,那么這些問(wèn)題就迎刃而解了,而這個(gè)腳本就是我們今天要說(shuō)的 Dockerfile

一、Dockerfile介紹

Dockerfile 是?個(gè)?本?件,其內(nèi)包含了?條條的指令(Instruction),每?條指令構(gòu)建?層,因此每?條指令的內(nèi)容,就是描述該層應(yīng)當(dāng)如何構(gòu)建。

還以之前定制 nginx 鏡像為例,這次我們使? Dockerfile 來(lái)定制。在?個(gè)空??錄中,建??個(gè)?本 ?件,并命名為 Dockerfile: 

$ mkdir mynginx 
$ cd mynginx 
$ touch Dockerfile

其內(nèi)容為:

FROM nginx 
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

 這個(gè) Dockerfile 很簡(jiǎn)單,?共就兩?。涉及到了兩條指令,F(xiàn)ROM 和 RUN。

二、FROM指定基礎(chǔ)鏡像

所謂定制鏡像,那?定是以?個(gè)鏡像為基礎(chǔ),在其上進(jìn)?定制。就像我們之前運(yùn)?了?個(gè) nginx 鏡像 的容器,再進(jìn)?修改?樣,基礎(chǔ)鏡像是必須指定的。? FROM 就是指定基礎(chǔ)鏡像,因此?個(gè) Dockerfile 中 FROM 是必備的指令,并且必須是第?條指令。

在Docker Store上有?常多的?質(zhì)量的官?鏡像,有可以直接拿來(lái)使?的服務(wù)類(lèi)的鏡像,如 nginx、 redis、mongo、mysql、httpd、php、tomcat 等;也有?些?便開(kāi)發(fā)、構(gòu)建、運(yùn)?各種語(yǔ)?應(yīng)?的鏡 像,如 node、openjdk、python、ruby、golang 等。可以在其中尋找?個(gè)最符合我們最終?標(biāo)的鏡像 為基礎(chǔ)鏡像進(jìn)?定制。

如果沒(méi)有找到對(duì)應(yīng)服務(wù)的鏡像,官?鏡像中還提供了?些更為基礎(chǔ)的操作系統(tǒng)鏡像,如 ubuntu、 debian、centos、fedora、alpine 等,這些操作系統(tǒng)的軟件庫(kù)為我們提供了更?闊的擴(kuò)展空間。

除了選擇現(xiàn)有鏡像為基礎(chǔ)鏡像外,Docker 還存在?個(gè)特殊的鏡像,名為 scratch 。這個(gè)鏡像是虛擬的 概念,并不實(shí)際存在,它表示?個(gè)空?的鏡像。

FROM scratch 
...

如果你以 scratch 為基礎(chǔ)鏡像的話(huà),意味著你不以任何鏡像為基礎(chǔ),接下來(lái)所寫(xiě)的指令將作為鏡像第 ?層開(kāi)始存在。有的同學(xué)可能感覺(jué)很奇怪,沒(méi)有任何基礎(chǔ)鏡像,我怎么去執(zhí)?我的程序呢,其實(shí)對(duì)于 Linux 下靜態(tài)編譯的程序來(lái)說(shuō),并不需要有操作系統(tǒng)提供運(yùn)?時(shí)?持,所需的?切庫(kù)都已經(jīng)在可執(zhí)?? 件?了,因此直接 FROM scratch 會(huì)讓鏡像體積更加?巧。使? Go 語(yǔ)? 開(kāi)發(fā)的應(yīng)?很多會(huì)使?這種? 式來(lái)制作鏡像,這也是為什么有?認(rèn)為 Go 是特別適合容器微服務(wù)架構(gòu)的語(yǔ)?的原因之?。

三、RUN執(zhí)行命令

RUN 指令是?來(lái)執(zhí)?命令?命令的。由于命令?的強(qiáng)?能?, RUN 指令在定制鏡像時(shí)是最常?的指令 之?。其格式有兩種:
shell 格式:RUN <命令>,就像直接在命令?中輸?的命令?樣。剛才寫(xiě)的 Dockerfile 中的 RUN 指令就是這種格式。

RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

exec 格式:RUN ["可執(zhí)??件", "參數(shù)1", "參數(shù)2"],這更像是函數(shù)調(diào)?中的格式。 既然 RUN 就像 Shell 腳本?樣可以執(zhí)?命令,那么我們是否就可以像 Shell 腳本?樣把每個(gè)命令對(duì)應(yīng)?個(gè) RUN 呢??如這樣:

FROM debian:jessie 
RUN apt-get update 
RUN apt-get install -y gcc libc6-dev make 
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" 
RUN mkdir -p /usr/src/redis 
RUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 
RUN make -C /usr/src/redis 
RUN make -C /usr/src/redis install

之前說(shuō)過(guò),Dockerfile 中每?個(gè)指令都會(huì)建??層,RUN 也不例外。每?個(gè) RUN 的?為,就和剛才 我們??建?鏡像的過(guò)程?樣:新建??層,在其上執(zhí)?這些命令,執(zhí)?結(jié)束后,commit 這?層的修改,構(gòu)成新的鏡像。 

?上?的這種寫(xiě)法,創(chuàng)建了 7 層鏡像。這是完全沒(méi)有意義的,?且很多運(yùn)?時(shí)不需要的東?,都被裝 進(jìn)了鏡像?,?如編譯環(huán)境、更新的軟件包等等。結(jié)果就是產(chǎn)??常臃腫、?常多層的鏡像,不僅僅 增加了構(gòu)建部署的時(shí)間,也很容易出錯(cuò)。 這是很多初學(xué) Docker 的?常犯的?個(gè)錯(cuò)誤。

Union FS 是有最?層數(shù)限制的,?如 AUFS,曾經(jīng)是最?不得超過(guò) 42 層,現(xiàn)在是不得超過(guò) 127 層。

 上?的 Dockerfile 正確的寫(xiě)法應(yīng)該是這樣:

FROM debian:jessie 
RUN buildDeps='gcc libc6-dev make' \ 
&& apt-get update \ 
&& apt-get install -y $buildDeps \ 
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \ 
&& mkdir -p /usr/src/redis \ 
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \ 
&& make -C /usr/src/redis \ 
&& make -C /usr/src/redis install \
&& rm -rf /var/lib/apt/lists/* \ 
&& rm redis.tar.gz \ 
&& rm -r /usr/src/redis \ 
&& apt-get purge -y --auto-remove $buildDeps

?先,之前所有的命令只有?個(gè)?的,就是編譯、安裝 redis 可執(zhí)??件。因此沒(méi)有必要建?很多層, 這只是?層的事情。因此,這?沒(méi)有使?很多個(gè) RUN 對(duì)??對(duì)應(yīng)不同的命令,?是僅僅使??個(gè) RUN 指令,并使? && 將各個(gè)所需命令串聯(lián)起來(lái)。將之前的 7 層,簡(jiǎn)化為了 1 層。在撰寫(xiě) Dockerfile 的時(shí)候,要經(jīng)常提醒??,這并不是在寫(xiě) Shell 腳本,?是在定義每?層該如何構(gòu)建。

并且,這?為了格式化還進(jìn)?了換?。Dockerfile ?持 Shell 類(lèi)的?尾添加 \ 的命令換??式,以及 ?? # 進(jìn)?注釋的格式。良好的格式,?如換?、縮進(jìn)、注釋等,會(huì)讓維護(hù)、排障更為容易,這是? 個(gè)?較好的習(xí)慣。

此外,還可以看到這?組命令的最后添加了清理?作的命令,刪除了為了編譯構(gòu)建所需要的軟件,清 理了所有下載、展開(kāi)的?件,并且還清理了 apt 緩存?件。這是很重要的?步,我們之前說(shuō)過(guò),鏡像 是多層存儲(chǔ),每?層的東?并不會(huì)在下?層被刪除,會(huì)?直跟隨著鏡像。因此鏡像構(gòu)建時(shí),?定要確 保每?層只添加真正需要添加的東?,任何?關(guān)的東?都應(yīng)該清理掉。 很多?初學(xué) Docker 制作出了 很臃腫的鏡像的原因之?,就是忘記了每?層構(gòu)建的最后?定要清理掉?關(guān)?件。

四、構(gòu)建鏡像

好了,讓我們?cè)倩氐街岸ㄖ频?nginx 鏡像的 Dockerfile 來(lái)。現(xiàn)在我們明?了這個(gè) Dockerfile 的內(nèi) 容,那么讓我們來(lái)構(gòu)建這個(gè)鏡像吧。在 Dockerfile ?件所在?錄執(zhí)?:

$ docker build -t nginx:v3 . 
Sending build context to Docker daemon 2.048 kB 
Step 1 : FROM nginx 
---> e43d811ce2f4 
Step 2 : RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html 
---> Running in 9cdc27646c7b 
---> 44aa4490ce2c 
Removing intermediate container 9cdc27646c7b 
Successfully built 44aa4490ce2c

從命令的輸出結(jié)果中,我們可以清晰的看到鏡像的構(gòu)建過(guò)程。在 Step 2 中,如同我們之前所說(shuō)的那 樣,RUN 指令啟動(dòng)了?個(gè)容器 9cdc27646c7b,執(zhí)?了所要求的命令,并最后提交了這?層 44aa4490ce2c,隨后刪除了所?到的這個(gè)容器 9cdc27646c7b。這?我們使?了 docker build 命令 進(jìn)?鏡像構(gòu)建。其格式為:

$ docker build [選項(xiàng)] <上下?路徑/URL/->

在這?我們指定了最終鏡像的名稱(chēng) -t nginx:v3,構(gòu)建成功后,我們可以像之前運(yùn)? nginx:v2 那樣來(lái)運(yùn) ?這個(gè)鏡像,其結(jié)果會(huì)和 nginx:v2 ?樣。

五、鏡像構(gòu)建上下文(Context)

如果注意,會(huì)看到 docker build 命令最后有?個(gè) . 。 . 表示當(dāng)前?錄,? Dockerfile 就在當(dāng)前?錄, 因此不少初學(xué)者以為這個(gè)路徑是在指定 Dockerfile 所在路徑,這么理解其實(shí)是不準(zhǔn)確的。如果對(duì)應(yīng)上?的命令格式,你可能會(huì)發(fā)現(xiàn),這是在指定上下?路徑。那么什么是上下?呢?

?先我們要理解 docker build 的?作原理。Docker 在運(yùn)?時(shí)分為 Docker 引擎(也就是服務(wù)端守護(hù)進(jìn) 程)和客戶(hù)端?具。Docker 的引擎提供了?組 REST API,被稱(chēng)為 Docker Remote API,?如 docker 命令這樣的客戶(hù)端?具,則是通過(guò)這組 API 與 Docker 引擎交互,從?完成各種功能。因此,雖然表 ?上我們好像是在本機(jī)執(zhí)?各種 docker 功能,但實(shí)際上,?切都是使?的遠(yuǎn)程調(diào)?形式在服務(wù)端 (Docker 引擎)完成。也因?yàn)檫@種 C/S 設(shè)計(jì),讓我們操作遠(yuǎn)程服務(wù)器的 Docker 引擎變得輕?易舉。

當(dāng)我們進(jìn)?鏡像構(gòu)建的時(shí)候,并?所有定制都會(huì)通過(guò) RUN 指令完成,經(jīng)常會(huì)需要將?些本地?件復(fù)制 進(jìn)鏡像,?如通過(guò) COPY 指令、ADD 指令等。? docker build 命令構(gòu)建鏡像,其實(shí)并?在本地構(gòu)建, ?是在服務(wù)端,也就是 Docker 引擎中構(gòu)建的。那么在這種客戶(hù)端/服務(wù)端的架構(gòu)中,如何才能讓服務(wù) 端獲得本地?件呢?

這就引?了上下?的概念。當(dāng)構(gòu)建的時(shí)候,?戶(hù)會(huì)指定構(gòu)建鏡像上下?的路徑,docker build 命令得知 這個(gè)路徑后,會(huì)將路徑下的所有內(nèi)容打包,然后上傳給 Docker 引擎。這樣 Docker 引擎收到這個(gè)上下 ?包后,展開(kāi)就會(huì)獲得構(gòu)建鏡像所需的?切?件。如果在 Dockerfile 中這么寫(xiě):

COPY ./package.json /app/

這并不是要復(fù)制執(zhí)? docker build 命令所在的?錄下的 package.json,也不是復(fù)制 Dockerfile 所在?錄下的 package.json,?是復(fù)制 上下?(context) ?錄下的 package.json。

因此, COPY 這類(lèi)指令中的源?件的路徑都是相對(duì)路徑。這也是初學(xué)者經(jīng)常會(huì)問(wèn)的為什么 COPY ../package.json /app 或者 COPY /opt/xxxx /app ?法?作的原因,因?yàn)檫@些路徑已經(jīng)超出了上下?的 范圍,Docker 引擎?法獲得這些位置的?件。如果真的需要那些?件,應(yīng)該將它們復(fù)制到上下??錄 中去。

現(xiàn)在就可以理解剛才的命令 docker build -t nginx:v3 . 中的這個(gè) . ,實(shí)際上是在指定上下?的? 錄,docker build 命令會(huì)將該?錄下的內(nèi)容打包交給 Docker 引擎以幫助構(gòu)建鏡像。

如果觀察 docker build 輸出,我們其實(shí)已經(jīng)看到了這個(gè)發(fā)送上下?的過(guò)程:

$ docker build -t nginx:v3 . 
Sending build context to Docker daemon 2.048 kB 
...

理解構(gòu)建上下?對(duì)于鏡像構(gòu)建是很重要的,可以避免犯?些不應(yīng)該的錯(cuò)誤。?如有些初學(xué)者在發(fā)現(xiàn) COPY /opt/xxxx /app 不?作后,于是?脆將 Dockerfile 放到了硬盤(pán)根?錄去構(gòu)建,結(jié)果發(fā)現(xiàn) docker build 執(zhí)?后,在發(fā)送?個(gè)?? GB 的東?,極為緩慢?且很容易構(gòu)建失敗。那是因?yàn)檫@種做法是在讓 docker build 打包整個(gè)硬盤(pán),這顯然是使?錯(cuò)誤。

?般來(lái)說(shuō),應(yīng)該會(huì)將 Dockerfile 置于?個(gè)空?錄下,或者項(xiàng)?根?錄下。如果該?錄下沒(méi)有所需? 件,那么應(yīng)該把所需?件復(fù)制?份過(guò)來(lái)。如果?錄下有些東?確實(shí)不希望構(gòu)建時(shí)傳給 Docker 引擎,那 么可以? .gitignore ?樣的語(yǔ)法寫(xiě)?個(gè) .dockerignore ,該?件是?于剔除不需要作為上下?傳遞給 Docker 引擎的。

那么為什么會(huì)有?誤以為 . 是指定 Dockerfile 所在?錄呢?這是因?yàn)樵谀J(rèn)情況下,如果不額外指定 Dockerfile 的話(huà),會(huì)將上下??錄下的名為 Dockerfile 的?件作為 Dockerfile。

這只是默認(rèn)?為,實(shí)際上 Dockerfile 的?件名并不要求必須為 Dockerfile,?且并不要求必須位于上下 ??錄中,?如可以? -f ../Dockerfile.php 參數(shù)指定某個(gè)?件作為 Dockerfile。

當(dāng)然,?般?家習(xí)慣性的會(huì)使?默認(rèn)的?件名 Dockerfile,以及會(huì)將其置于鏡像構(gòu)建上下??錄中。

六、遷移鏡像

Docker 還提供了 docker load 和 docker save 命令,?以將鏡像保存為?個(gè) tar ?件,然后傳輸?shù)搅??個(gè)位置上,再加載進(jìn)來(lái)。這是在沒(méi)有 Docker Registry 時(shí)的做法,現(xiàn)在已經(jīng)不推薦,鏡像遷移應(yīng)該直 接使? Docker Registry,?論是直接使? Docker Hub 還是使?內(nèi)?私有 Registry 都可以。

使? docker save 命令可以將鏡像保存為歸檔?件。?如我們希望保存這個(gè) alpine 鏡像。

$ docker image ls alpine 
REPOSITORY TAG IMAGE ID CREATED SIZE 
alpine latest baa5d63471ea 5 weeks ago 4.803 MB

保存鏡像的命令為:

$ docker save alpine | gzip > alpine-latest.tar.gz

然后我們將 alpine-latest.tar.gz ?件復(fù)制到了到了另?個(gè)機(jī)器上,可以?下?這個(gè)命令加載鏡像:

$ docker load -i alpine-latest.tar.gz 
Loaded image: alpine:latest

如果我們結(jié)合這兩個(gè)命令以及 ssh 甚? pv 的話(huà),利? Linux 強(qiáng)?的管道,我們可以寫(xiě)?個(gè)命令完成從 ?個(gè)機(jī)器將鏡像遷移到另?個(gè)機(jī)器,并且?guī)нM(jìn)度條的功能:

docker save <鏡像名> | bzip2 | pv | ssh <?戶(hù)名>@<主機(jī)名> 'cat | docker load'

分享到:
標(biāo)簽:定制 方法 服務(wù)器 腳本 鏡像
用戶(hù)無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定