日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用镜像

發(fā)布時間:2024/9/3 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用镜像 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

使用鏡像

使用 Docker 鏡像

在之前的介紹中,我們知道鏡像是 Docker 的三大組件之一。

Docker 運(yùn)行容器前需要本地存在對應(yīng)的鏡像,如果本地不存在該鏡像,Docker 會從鏡像倉庫下載該鏡像。

關(guān)于鏡像的內(nèi)容,包括:

  • 從倉庫獲取鏡像;

  • 管理本地主機(jī)上的鏡像;

  • 介紹鏡像實(shí)現(xiàn)的基本原理。

獲取鏡像

之前提到過,Docker Hub 上有大量的高質(zhì)量的鏡像可以用,這里我們就說一下怎么獲取這些鏡像。

從 Docker 鏡像倉庫獲取鏡像的命令是 docker pull。其命令格式為:

docker pull [選項] [Docker Registry 地址[:端口號]/]倉庫名[:標(biāo)簽]

具體的選項可以通過 docker pull --help 命令看到,這里我們說一下鏡像名稱的格式。

  • Docker 鏡像倉庫地址:地址的格式一般是 <域名/IP>[:端口號]。默認(rèn)地址是 Docker Hub(docker.io)。
  • 倉庫名:如之前所說,這里的倉庫名是兩段式名稱,即 <用戶名>/<軟件名>。對于 Docker Hub,如果不給出用戶名,則默認(rèn)為 library,也就是官方鏡像。

比如:

$ docker pull ubuntu:18.04 18.04: Pulling from library/ubuntu bf5d46315322: Pull complete 9f13e0ac480c: Pull complete e8988b5b3097: Pull complete 40af181810e7: Pull complete e6f7c7e5c03e: Pull complete Digest: sha256:147913621d9cdea08853f6ba9116c2e27a3ceffecf3b492983ae97c3d643fbbe Status: Downloaded newer image for ubuntu:18.04

上面的命令中沒有給出 Docker 鏡像倉庫地址,因此將會從 Docker Hub 獲取鏡像。而鏡像名稱是 ubuntu:18.04,因此將會獲取官方鏡像 library/ubuntu 倉庫中標(biāo)簽為 18.04 的鏡像。

從下載過程中可以看到我們之前提及的分層存儲的概念,鏡像是由多層存儲所構(gòu)成。下載也是一層層的去下載,并非單一文件。下載過程中給出了每一層的 ID 的前 12 位。并且下載結(jié)束后,給出該鏡像完整的 sha256 的摘要,以確保下載一致性。

在使用上面命令的時候,你可能會發(fā)現(xiàn),你所看到的層 ID 以及 sha256 的摘要和這里的不一樣。這是因為官方鏡像是一直在維護(hù)的,有任何新的 bug,或者版本更新,都會進(jìn)行修復(fù)再以原來的標(biāo)簽發(fā)布,這樣可以確保任何使用這個標(biāo)簽的用戶可以獲得更安全、更穩(wěn)定的鏡像。

如果從 Docker Hub 下載鏡像非常緩慢,可以參照 鏡像加速器 一節(jié)配置加速器。

運(yùn)行

有了鏡像后,我們就能夠以這個鏡像為基礎(chǔ)啟動并運(yùn)行一個容器。以上面的 ubuntu:18.04 為例,如果我們打算啟動里面的 bash 并且進(jìn)行交互式操作的話,可以執(zhí)行下面的命令。

$ docker run -it --rm ubuntu:18.04 bashroot@e7009c6ce357:/# cat /etc/os-release NAME="Ubuntu" VERSION="18.04.1 LTS (Bionic Beaver)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 18.04.1 LTS" VERSION_ID="18.04" HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" VERSION_CODENAME=bionic UBUNTU_CODENAME=bionic

docker run 就是運(yùn)行容器的命令,具體格式我們會在 容器 一節(jié)進(jìn)行詳細(xì)講解,我們這里簡要的說明一下上面用到的參數(shù)。

  • -it:這是兩個參數(shù),一個是 -i:交互式操作,一個是 -t 終端。我們這里打算進(jìn)入 bash 執(zhí)行一些命令并查看返回結(jié)果,因此我們需要交互式終端。
  • --rm:這個參數(shù)是說容器退出后隨之將其刪除。默認(rèn)情況下,為了排障需求,退出的容器并不會立即刪除,除非手動 docker rm。我們這里只是隨便執(zhí)行個命令,看看結(jié)果,不需要排障和保留結(jié)果,因此使用 --rm 可以避免浪費(fèi)空間。
  • ubuntu:18.04:這是指用 ubuntu:18.04 鏡像為基礎(chǔ)來啟動容器。
  • bash:放在鏡像名后的是 命令,這里我們希望有個交互式 Shell,因此用的是 bash。

進(jìn)入容器后,我們可以在 Shell 下操作,執(zhí)行任何所需的命令。這里,我們執(zhí)行了 cat /etc/os-release,這是 Linux 常用的查看當(dāng)前系統(tǒng)版本的命令,從返回的結(jié)果可以看到容器內(nèi)是 Ubuntu 18.04.1 LTS 系統(tǒng)。

最后我們通過 exit 退出了這個容器。

列出鏡像

要想列出已經(jīng)下載下來的鏡像,可以使用 docker image ls 命令。

$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE redis latest 5f515359c7f8 5 days ago 183 MB nginx latest 05a60462f8ba 5 days ago 181 MB mongo 3.2 fe9198c04d62 5 days ago 342 MB <none> <none> 00285df0df87 5 days ago 342 MB ubuntu 18.04 f753707788c5 4 weeks ago 127 MB ubuntu latest f753707788c5 4 weeks ago 127 MB

列表包含了 倉庫名、標(biāo)簽、鏡像 ID、創(chuàng)建時間 以及 所占用的空間。

其中倉庫名、標(biāo)簽在之前的基礎(chǔ)概念章節(jié)已經(jīng)介紹過了。鏡像 ID 則是鏡像的唯一標(biāo)識,一個鏡像可以對應(yīng)多個 標(biāo)簽。因此,在上面的例子中,我們可以看到 ubuntu:18.04 和 ubuntu:latest 擁有相同的 ID,因為它們對應(yīng)的是同一個鏡像。

鏡像體積

如果仔細(xì)觀察,會注意到,這里標(biāo)識的所占用空間和在 Docker Hub 上看到的鏡像大小不同。比如,ubuntu:18.04 鏡像大小,在這里是 127 MB,但是在 Docker Hub 顯示的卻是 50 MB。這是因為 Docker Hub 中顯示的體積是壓縮后的體積。在鏡像下載和上傳過程中鏡像是保持著壓縮狀態(tài)的,因此 Docker Hub 所顯示的大小是網(wǎng)絡(luò)傳輸中更關(guān)心的流量大小。而 docker image ls 顯示的是鏡像下載到本地后,展開的大小,準(zhǔn)確說,是展開后的各層所占空間的總和,因為鏡像到本地后,查看空間的時候,更關(guān)心的是本地磁盤空間占用的大小。

另外一個需要注意的問題是,docker image ls 列表中的鏡像體積總和并非是所有鏡像實(shí)際硬盤消耗。由于 Docker 鏡像是多層存儲結(jié)構(gòu),并且可以繼承、復(fù)用,因此不同鏡像可能會因為使用相同的基礎(chǔ)鏡像,從而擁有共同的層。由于 Docker 使用 Union FS,相同的層只需要保存一份即可,因此實(shí)際鏡像硬盤占用空間很可能要比這個列表鏡像大小的總和要小的多。

你可以通過以下命令來便捷的查看鏡像、容器、數(shù)據(jù)卷所占用的空間。

$ docker system dfTYPE TOTAL ACTIVE SIZE RECLAIMABLE Images 24 0 1.992GB 1.992GB (100%) Containers 1 0 62.82MB 62.82MB (100%) Local Volumes 9 0 652.2MB 652.2MB (100%) Build Cache 0B 0B

虛懸鏡像

上面的鏡像列表中,還可以看到一個特殊的鏡像,這個鏡像既沒有倉庫名,也沒有標(biāo)簽,均為 <none>。:

<none> <none> 00285df0df87 5 days ago 342 MB

這個鏡像原本是有鏡像名和標(biāo)簽的,原來為 mongo:3.2,隨著官方鏡像維護(hù),發(fā)布了新版本后,重新 docker pull mongo:3.2 時,mongo:3.2 這個鏡像名被轉(zhuǎn)移到了新下載的鏡像身上,而舊的鏡像上的這個名稱則被取消,從而成為了 <none>。除了 docker pull 可能導(dǎo)致這種情況,docker build 也同樣可以導(dǎo)致這種現(xiàn)象。由于新舊鏡像同名,舊鏡像名稱被取消,從而出現(xiàn)倉庫名、標(biāo)簽均為 <none> 的鏡像。這類無標(biāo)簽鏡像也被稱為 虛懸鏡像(dangling image) ,可以用下面的命令專門顯示這類鏡像:

$ docker image ls -f dangling=true REPOSITORY TAG IMAGE ID CREATED SIZE <none> <none> 00285df0df87 5 days ago 342 MB

一般來說,虛懸鏡像已經(jīng)失去了存在的價值,是可以隨意刪除的,可以用下面的命令刪除。

$ docker image prune

中間層鏡像

為了加速鏡像構(gòu)建、重復(fù)利用資源,Docker 會利用 中間層鏡像。所以在使用一段時間后,可能會看到一些依賴的中間層鏡像。默認(rèn)的 docker image ls 列表中只會顯示頂層鏡像,如果希望顯示包括中間層鏡像在內(nèi)的所有鏡像的話,需要加 -a 參數(shù)。

$ docker image ls -a

這樣會看到很多無標(biāo)簽的鏡像,與之前的虛懸鏡像不同,這些無標(biāo)簽的鏡像很多都是中間層鏡像,是其它鏡像所依賴的鏡像。這些無標(biāo)簽鏡像不應(yīng)該刪除,否則會導(dǎo)致上層鏡像因為依賴丟失而出錯。實(shí)際上,這些鏡像也沒必要刪除,因為之前說過,相同的層只會存一遍,而這些鏡像是別的鏡像的依賴,因此并不會因為它們被列出來而多存了一份,無論如何你也會需要它們。只要刪除那些依賴它們的鏡像后,這些依賴的中間層鏡像也會被連帶刪除。

列出部分鏡像

不加任何參數(shù)的情況下,docker image ls 會列出所有頂層鏡像,但是有時候我們只希望列出部分鏡像。docker image ls 有好幾個參數(shù)可以幫助做到這個事情。

根據(jù)倉庫名列出鏡像

$ docker image ls ubuntu REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu 18.04 f753707788c5 4 weeks ago 127 MB ubuntu latest f753707788c5 4 weeks ago 127 MB

列出特定的某個鏡像,也就是說指定倉庫名和標(biāo)簽

$ docker image ls ubuntu:18.04 REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu 18.04 f753707788c5 4 weeks ago 127 MB

除此以外,docker image ls 還支持強(qiáng)大的過濾器參數(shù) --filter,或者簡寫 -f。之前我們已經(jīng)看到了使用過濾器來列出虛懸鏡像的用法,它還有更多的用法。比如,我們希望看到在 mongo:3.2 之后建立的鏡像,可以用下面的命令:

$ docker image ls -f since=mongo:3.2 REPOSITORY TAG IMAGE ID CREATED SIZE redis latest 5f515359c7f8 5 days ago 183 MB nginx latest 05a60462f8ba 5 days ago 181 MB

想查看某個位置之前的鏡像也可以,只需要把 since 換成 before 即可。

此外,如果鏡像構(gòu)建時,定義了 LABEL,還可以通過 LABEL 來過濾。

$ docker image ls -f label=com.example.version=0.1 ...

以特定格式顯示

默認(rèn)情況下,docker image ls 會輸出一個完整的表格,但是我們并非所有時候都會需要這些內(nèi)容。比如,剛才刪除虛懸鏡像的時候,我們需要利用 docker image ls 把所有的虛懸鏡像的 ID 列出來,然后才可以交給 docker image rm 命令作為參數(shù)來刪除指定的這些鏡像,這個時候就用到了 -q 參數(shù)。

$ docker image ls -q 5f515359c7f8 05a60462f8ba fe9198c04d62 00285df0df87 f753707788c5 f753707788c5 1e0c3dd64ccd

--filter 配合 -q 產(chǎn)生出指定范圍的 ID 列表,然后送給另一個 docker 命令作為參數(shù),從而針對這組實(shí)體成批的進(jìn)行某種操作的做法在 Docker 命令行使用過程中非常常見,不僅僅是鏡像,將來我們會在各個命令中看到這類搭配以完成很強(qiáng)大的功能。因此每次在文檔看到過濾器后,可以多注意一下它們的用法。

另外一些時候,我們可能只是對表格的結(jié)構(gòu)不滿意,希望自己組織列;或者不希望有標(biāo)題,這樣方便其它程序解析結(jié)果等,這就用到了 Go 的模板語法。

比如,下面的命令會直接列出鏡像結(jié)果,并且只包含鏡像ID和倉庫名:

$ docker image ls --format "{{.ID}}: {{.Repository}}" 5f515359c7f8: redis 05a60462f8ba: nginx fe9198c04d62: mongo 00285df0df87: <none> f753707788c5: ubuntu f753707788c5: ubuntu 1e0c3dd64ccd: ubuntu

或者打算以表格等距顯示,并且有標(biāo)題行,和默認(rèn)一樣,不過自己定義列:

$ docker image ls --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}" IMAGE ID REPOSITORY TAG 5f515359c7f8 redis latest 05a60462f8ba nginx latest fe9198c04d62 mongo 3.2 00285df0df87 <none> <none> f753707788c5 ubuntu 18.04 f753707788c5 ubuntu latest

刪除本地鏡像

如果要刪除本地的鏡像,可以使用 docker image rm 命令,其格式為:

$ docker image rm [選項] <鏡像1> [<鏡像2> ...]

用 ID、鏡像名、摘要刪除鏡像

其中,<鏡像> 可以是 鏡像短 ID、鏡像長 ID、鏡像名 或者 鏡像摘要。

比如我們有這么一些鏡像:

$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE centos latest 0584b3d2cf6d 3 weeks ago 196.5 MB redis alpine 501ad78535f0 3 weeks ago 21.03 MB docker latest cf693ec9b5c7 3 weeks ago 105.1 MB nginx latest e43d811ce2f4 5 weeks ago 181.5 MB

我們可以用鏡像的完整 ID,也稱為 長 ID,來刪除鏡像。使用腳本的時候可能會用長 ID,但是人工輸入就太累了,所以更多的時候是用 短 ID 來刪除鏡像。docker image ls 默認(rèn)列出的就已經(jīng)是短 ID 了,一般取前3個字符以上,只要足夠區(qū)分于別的鏡像就可以了。

比如這里,如果我們要刪除 redis:alpine 鏡像,可以執(zhí)行:

$ docker image rm 501 Untagged: redis:alpine Untagged: redis@sha256:f1ed3708f538b537eb9c2a7dd50dc90a706f7debd7e1196c9264edeea521a86d Deleted: sha256:501ad78535f015d88872e13fa87a828425117e3d28075d0c117932b05bf189b7 Deleted: sha256:96167737e29ca8e9d74982ef2a0dda76ed7b430da55e321c071f0dbff8c2899b Deleted: sha256:32770d1dcf835f192cafd6b9263b7b597a1778a403a109e2cc2ee866f74adf23 Deleted: sha256:127227698ad74a5846ff5153475e03439d96d4b1c7f2a449c7a826ef74a2d2fa Deleted: sha256:1333ecc582459bac54e1437335c0816bc17634e131ea0cc48daa27d32c75eab3 Deleted: sha256:4fc455b921edf9c4aea207c51ab39b10b06540c8b4825ba57b3feed1668fa7c7

我們也可以用鏡像名,也就是 <倉庫名>:<標(biāo)簽>,來刪除鏡像。

$ docker image rm centos Untagged: centos:latest Untagged: centos@sha256:b2f9d1c0ff5f87a4743104d099a3d561002ac500db1b9bfa02a783a46e0d366c Deleted: sha256:0584b3d2cf6d235ee310cf14b54667d889887b838d3f3d3033acd70fc3c48b8a Deleted: sha256:97ca462ad9eeae25941546209454496e1d66749d53dfa2ee32bf1faabd239d38

當(dāng)然,更精確的是使用 鏡像摘要 刪除鏡像。

$ docker image ls --digests REPOSITORY TAG DIGEST IMAGE ID CREATED SIZE node slim sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228 6e0c4c8e3913 3 weeks ago 214 MB$ docker image rm node@sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228 Untagged: node@sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228

Untagged 和 Deleted

如果觀察上面這幾個命令的運(yùn)行輸出信息的話,你會注意到刪除行為分為兩類,一類是 Untagged,另一類是 Deleted。我們之前介紹過,鏡像的唯一標(biāo)識是其 ID 和摘要,而一個鏡像可以有多個標(biāo)簽。

因此當(dāng)我們使用上面命令刪除鏡像的時候,實(shí)際上是在要求刪除某個標(biāo)簽的鏡像。所以首先需要做的是將滿足我們要求的所有鏡像標(biāo)簽都取消,這就是我們看到的 Untagged 的信息。因為一個鏡像可以對應(yīng)多個標(biāo)簽,因此當(dāng)我們刪除了所指定的標(biāo)簽后,可能還有別的標(biāo)簽指向了這個鏡像,如果是這種情況,那么 Delete 行為就不會發(fā)生。所以并非所有的 docker image rm 都會產(chǎn)生刪除鏡像的行為,有可能僅僅是取消了某個標(biāo)簽而已。

當(dāng)該鏡像所有的標(biāo)簽都被取消了,該鏡像很可能會失去了存在的意義,因此會觸發(fā)刪除行為。鏡像是多層存儲結(jié)構(gòu),因此在刪除的時候也是從上層向基礎(chǔ)層方向依次進(jìn)行判斷刪除。鏡像的多層結(jié)構(gòu)讓鏡像復(fù)用變得非常容易,因此很有可能某個其它鏡像正依賴于當(dāng)前鏡像的某一層。這種情況,依舊不會觸發(fā)刪除該層的行為。直到?jīng)]有任何層依賴當(dāng)前層時,才會真實(shí)的刪除當(dāng)前層。這就是為什么,有時候會奇怪,為什么明明沒有別的標(biāo)簽指向這個鏡像,但是它還是存在的原因,也是為什么有時候會發(fā)現(xiàn)所刪除的層數(shù)和自己 docker pull 看到的層數(shù)不一樣的原因。

除了鏡像依賴以外,還需要注意的是容器對鏡像的依賴。如果有用這個鏡像啟動的容器存在(即使容器沒有運(yùn)行),那么同樣不可以刪除這個鏡像。之前講過,容器是以鏡像為基礎(chǔ),再加一層容器存儲層,組成這樣的多層存儲結(jié)構(gòu)去運(yùn)行的。因此該鏡像如果被這個容器所依賴的,那么刪除必然會導(dǎo)致故障。如果這些容器是不需要的,應(yīng)該先將它們刪除,然后再來刪除鏡像。

用 docker image ls 命令來配合

像其它可以承接多個實(shí)體的命令一樣,可以使用 docker image ls -q 來配合使用 docker image rm,這樣可以成批的刪除希望刪除的鏡像。我們在“鏡像列表”章節(jié)介紹過很多過濾鏡像列表的方式都可以拿過來使用。

比如,我們需要刪除所有倉庫名為 redis 的鏡像:

$ docker image rm $(docker image ls -q redis)

或者刪除所有在 mongo:3.2 之前的鏡像:

$ docker image rm $(docker image ls -q -f before=mongo:3.2)

充分利用你的想象力和 Linux 命令行的強(qiáng)大,你可以完成很多非常贊的功能。

利用 commit 理解鏡像構(gòu)成

注意:如果您是初學(xué)者,您可以暫時跳過后面的內(nèi)容,直接學(xué)習(xí) 容器 一節(jié)。

注意: docker commit 命令除了學(xué)習(xí)之外,還有一些特殊的應(yīng)用場合,比如被入侵后保存現(xiàn)場等。但是,不要使用 docker commit 定制鏡像,定制鏡像應(yīng)該使用 Dockerfile 來完成。如果你想要定制鏡像請查看下一小節(jié)。

鏡像是容器的基礎(chǔ),每次執(zhí)行 docker run 的時候都會指定哪個鏡像作為容器運(yùn)行的基礎(chǔ)。在之前的例子中,我們所使用的都是來自于 Docker Hub 的鏡像。直接使用這些鏡像是可以滿足一定的需求,而當(dāng)這些鏡像無法直接滿足需求時,我們就需要定制這些鏡像。接下來的幾節(jié)就將講解如何定制鏡像。

回顧一下之前我們學(xué)到的知識,鏡像是多層存儲,每一層是在前一層的基礎(chǔ)上進(jìn)行的修改;而容器同樣也是多層存儲,是在以鏡像為基礎(chǔ)層,在其基礎(chǔ)上加一層作為容器運(yùn)行時的存儲層。

現(xiàn)在讓我們以定制一個 Web 服務(wù)器為例子,來講解鏡像是如何構(gòu)建的。

$ docker run --name webserver -d -p 80:80 nginx

這條命令會用 nginx 鏡像啟動一個容器,命名為 webserver,并且映射了 80 端口,這樣我們可以用瀏覽器去訪問這個 nginx 服務(wù)器。

如果是在本機(jī)運(yùn)行的 Docker,那么可以直接訪問:http://localhost ,如果是在虛擬機(jī)、云服務(wù)器上安裝的 Docker,則需要將 localhost 換為虛擬機(jī)地址或者實(shí)際云服務(wù)器地址。

直接用瀏覽器訪問的話,我們會看到默認(rèn)的 Nginx 歡迎頁面。

現(xiàn)在,假設(shè)我們非常不喜歡這個歡迎頁面,我們希望改成歡迎 Docker 的文字,我們可以使用 docker exec 命令進(jìn)入容器,修改其內(nèi)容。

$ docker exec -it webserver bash root@3729b97e8226:/# echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html root@3729b97e8226:/# exit exit

我們以交互式終端方式進(jìn)入 webserver 容器,并執(zhí)行了 bash 命令,也就是獲得一個可操作的 Shell。

然后,我們用 <h1>Hello, Docker!</h1> 覆蓋了 /usr/share/nginx/html/index.html 的內(nèi)容。

現(xiàn)在我們再刷新瀏覽器的話,會發(fā)現(xiàn)內(nèi)容被改變了。

我們修改了容器的文件,也就是改動了容器的存儲層。我們可以通過 docker diff 命令看到具體的改動。

$ docker diff webserver C /root A /root/.bash_history C /run C /usr C /usr/share C /usr/share/nginx C /usr/share/nginx/html C /usr/share/nginx/html/index.html C /var C /var/cache C /var/cache/nginx A /var/cache/nginx/client_temp A /var/cache/nginx/fastcgi_temp A /var/cache/nginx/proxy_temp A /var/cache/nginx/scgi_temp A /var/cache/nginx/uwsgi_temp

現(xiàn)在我們定制好了變化,我們希望能將其保存下來形成鏡像。

要知道,當(dāng)我們運(yùn)行一個容器的時候(如果不使用卷的話),我們做的任何文件修改都會被記錄于容器存儲層里。而 Docker 提供了一個 docker commit 命令,可以將容器的存儲層保存下來成為鏡像。換句話說,就是在原有鏡像的基礎(chǔ)上,再疊加上容器的存儲層,并構(gòu)成新的鏡像。以后我們運(yùn)行這個新鏡像的時候,就會擁有原有容器最后的文件變化。

docker commit 的語法格式為:

docker commit [選項] <容器ID或容器名> [<倉庫名>[:<標(biāo)簽>]]

我們可以用下面的命令將容器保存為鏡像:

$ docker commit \--author "Tao Wang <twang2218@gmail.com>" \--message "修改了默認(rèn)網(wǎng)頁" \webserver \nginx:v2 sha256:07e33465974800ce65751acc279adc6ed2dc5ed4e0838f8b86f0c87aa1795214

其中 --author 是指定修改的作者,而 --message 則是記錄本次修改的內(nèi)容。這點(diǎn)和 git 版本控制相似,不過這里這些信息可以省略留空。

我們可以在 docker image ls 中看到這個新定制的鏡像:

$ docker image ls nginx REPOSITORY TAG IMAGE ID CREATED SIZE nginx v2 07e334659748 9 seconds ago 181.5 MB nginx 1.11 05a60462f8ba 12 days ago 181.5 MB nginx latest e43d811ce2f4 4 weeks ago 181.5 MB

我們還可以用 docker history 具體查看鏡像內(nèi)的歷史記錄,如果比較 nginx:latest 的歷史記錄,我們會發(fā)現(xiàn)新增了我們剛剛提交的這一層。

$ docker history nginx:v2 IMAGE CREATED CREATED BY SIZE COMMENT 07e334659748 54 seconds ago nginx -g daemon off; 95 B 修改了默認(rèn)網(wǎng)頁 e43d811ce2f4 4 weeks ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daemon 0 B <missing> 4 weeks ago /bin/sh -c #(nop) EXPOSE 443/tcp 80/tcp 0 B <missing> 4 weeks ago /bin/sh -c ln -sf /dev/stdout /var/log/nginx/ 22 B <missing> 4 weeks ago /bin/sh -c apt-key adv --keyserver hkp://pgp. 58.46 MB <missing> 4 weeks ago /bin/sh -c #(nop) ENV NGINX_VERSION=1.11.5-1 0 B <missing> 4 weeks ago /bin/sh -c #(nop) MAINTAINER NGINX Docker Ma 0 B <missing> 4 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B <missing> 4 weeks ago /bin/sh -c #(nop) ADD file:23aa4f893e3288698c 123 MB

新的鏡像定制好后,我們可以來運(yùn)行這個鏡像。

docker run --name web2 -d -p 81:80 nginx:v2

這里我們命名為新的服務(wù)為 web2,并且映射到 81 端口。訪問 http://localhost:81 看到結(jié)果,其內(nèi)容應(yīng)該和之前修改后的 webserver 一樣。

至此,我們第一次完成了定制鏡像,使用的是 docker commit 命令,手動操作給舊的鏡像添加了新的一層,形成新的鏡像,對鏡像多層存儲應(yīng)該有了更直觀的感覺。

慎用 docker commit

使用 docker commit 命令雖然可以比較直觀的幫助理解鏡像分層存儲的概念,但是實(shí)際環(huán)境中并不會這樣使用。

首先,如果仔細(xì)觀察之前的 docker diff webserver 的結(jié)果,你會發(fā)現(xiàn)除了真正想要修改的 /usr/share/nginx/html/index.html 文件外,由于命令的執(zhí)行,還有很多文件被改動或添加了。這還僅僅是最簡單的操作,如果是安裝軟件包、編譯構(gòu)建,那會有大量的無關(guān)內(nèi)容被添加進(jìn)來,將會導(dǎo)致鏡像極為臃腫。

此外,使用 docker commit 意味著所有對鏡像的操作都是黑箱操作,生成的鏡像也被稱為 黑箱鏡像,換句話說,就是除了制作鏡像的人知道執(zhí)行過什么命令、怎么生成的鏡像,別人根本無從得知。而且,即使是這個制作鏡像的人,過一段時間后也無法記清具體的操作。這種黑箱鏡像的維護(hù)工作是非常痛苦的。

而且,回顧之前提及的鏡像所使用的分層存儲的概念,除當(dāng)前層外,之前的每一層都是不會發(fā)生改變的,換句話說,任何修改的結(jié)果僅僅是在當(dāng)前層進(jìn)行標(biāo)記、添加、修改,而不會改動上一層。如果使用 docker commit 制作鏡像,以及后期修改的話,每一次修改都會讓鏡像更加臃腫一次,所刪除的上一層的東西并不會丟失,會一直如影隨形的跟著這個鏡像,即使根本無法訪問到。這會讓鏡像更加臃腫。

總結(jié)

以上是生活随笔為你收集整理的使用镜像的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。