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

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

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

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

前言

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

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

一、Dockerfile介紹

Dockerfile 是?個?本?件,其內包含了?條條的指令(Instruction),每?條指令構建?層,因此每?條指令的內容,就是描述該層應當如何構建。

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

$ mkdir mynginx 
$ cd mynginx 
$ touch Dockerfile

其內容為:

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

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

二、FROM指定基礎鏡像

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

在Docker Store上有?常多的?質量的官?鏡像,有可以直接拿來使?的服務類的鏡像,如 nginx、 redis、mongo、mysql、httpd、php、tomcat 等;也有?些?便開發(fā)、構建、運?各種語?應?的鏡 像,如 node、openjdk、python、ruby、golang 等。可以在其中尋找?個最符合我們最終?標的鏡像 為基礎鏡像進?定制。

如果沒有找到對應服務的鏡像,官?鏡像中還提供了?些更為基礎的操作系統(tǒng)鏡像,如 ubuntu、 debian、centos、fedora、alpine 等,這些操作系統(tǒng)的軟件庫為我們提供了更?闊的擴展空間。

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

FROM scratch 
...

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

三、RUN執(zhí)行命令

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

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

exec 格式:RUN ["可執(zhí)??件", "參數(shù)1", "參數(shù)2"],這更像是函數(shù)調?中的格式。 既然 RUN 就像 Shell 腳本?樣可以執(zhí)?命令,那么我們是否就可以像 Shell 腳本?樣把每個命令對應?個 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

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

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

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

 上?的 Dockerfile 正確的寫法應該是這樣:

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

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

并且,這?為了格式化還進?了換?。Dockerfile ?持 Shell 類的?尾添加 \ 的命令換??式,以及 ?? # 進?注釋的格式。良好的格式,?如換?、縮進、注釋等,會讓維護、排障更為容易,這是? 個?較好的習慣。

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

四、構建鏡像

好了,讓我們再回到之前定制的 nginx 鏡像的 Dockerfile 來。現(xiàn)在我們明?了這個 Dockerfile 的內 容,那么讓我們來構建這個鏡像吧。在 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

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

$ docker build [選項] <上下?路徑/URL/->

在這?我們指定了最終鏡像的名稱 -t nginx:v3,構建成功后,我們可以像之前運? nginx:v2 那樣來運 ?這個鏡像,其結果會和 nginx:v2 ?樣。

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

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

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

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

這就引?了上下?的概念。當構建的時候,?戶會指定構建鏡像上下?的路徑,docker build 命令得知 這個路徑后,會將路徑下的所有內容打包,然后上傳給 Docker 引擎。這樣 Docker 引擎收到這個上下 ?包后,展開就會獲得構建鏡像所需的?切?件。如果在 Dockerfile 中這么寫:

COPY ./package.json /app/

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

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

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

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

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

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

?般來說,應該會將 Dockerfile 置于?個空?錄下,或者項?根?錄下。如果該?錄下沒有所需? 件,那么應該把所需?件復制?份過來。如果?錄下有些東?確實不希望構建時傳給 Docker 引擎,那 么可以? .gitignore ?樣的語法寫?個 .dockerignore ,該?件是?于剔除不需要作為上下?傳遞給 Docker 引擎的。

那么為什么會有?誤以為 . 是指定 Dockerfile 所在?錄呢?這是因為在默認情況下,如果不額外指定 Dockerfile 的話,會將上下??錄下的名為 Dockerfile 的?件作為 Dockerfile。

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

當然,?般?家習慣性的會使?默認的?件名 Dockerfile,以及會將其置于鏡像構建上下??錄中。

六、遷移鏡像

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

使? docker save 命令可以將鏡像保存為歸檔?件。?如我們希望保存這個 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 ?件復制到了到了另?個機器上,可以?下?這個命令加載鏡像:

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

如果我們結合這兩個命令以及 ssh 甚? pv 的話,利? Linux 強?的管道,我們可以寫?個命令完成從 ?個機器將鏡像遷移到另?個機器,并且?guī)нM度條的功能:

docker save <鏡像名> | bzip2 | pv | ssh <?戶名>@<主機名> 'cat | docker load'

分享到:
標簽:定制 方法 服務器 腳本 鏡像
用戶無頭像

網(wǎng)友整理

注冊時間:

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

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

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

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

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

答題星2018-06-03

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

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數(shù)有氧達人2018-06-03

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

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

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

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定