1. 程式人生 > 實用技巧 >Docker (三) 使用commit建立Docker映象

Docker (三) 使用commit建立Docker映象

利用commit方式建立Docker映象

原文連結

建立原理

映象是容器的基礎,每次執行 docker run 的時候都會指定哪個映象作為容器執行的基礎。當我們使用Docker Hub的映象無法滿足我們的需求時,我們就需要自己定製映象來滿足我們的需求。

映象是多層儲存,每一層是在前一層的基礎上進行的修改;而容器同樣也是多層儲存是在以映象為基礎層,在基礎層上加一層作為容器執行時的儲存層。

示例說明映象是如何構建的。

[root@server ~]# docker run --name web -d -p 80:80 nginx  #啟動一個容器,基於docker hub上面的nginx:1.11映象

這條命令會用 nginx映象啟動一個容器,命名為 web,並且映射了80 埠,這樣便可以去訪問這個 nginx 伺服器。然後我們直接訪問宿主機的IP可以看到Nginx的歡迎頁面

現在,假設我們不喜歡這個歡迎頁面,我們喜歡改成別的文字,我們可以使用docker exec 命令進入到容器,修改其內容,如下

root@714830c04e5e:/# echo '<h1>Hello Docker Nginx Server</h1>' >/usr/share/nginx/html/index.html   #修改預設首頁的內容
root@714830c04e5e:/# exit
exit

已互動式終端方式進入 web容器,並執行了 bash命令, 也就是獲得了一個可操作的shell。然後覆蓋了index.html內容,再次重新整理瀏覽器,會發現內容被改變了。

修改了容器的檔案,也就是改動了容器的儲存器,可以通過 docker diff 命令檢視具體的改動

[root@server ~]# docker diff web #檢視webServer容器改動的內容
C /var
C /var/cache
C /var/cache/nginx
A /var/cache/nginx/scgi_temp
A /var/cache/nginx/uwsgi_temp
A /var/cache/nginx/client_temp
A /var/cache/nginx/fastcgi_temp
A /var/cache/nginx/proxy_temp
C /root
A /root/.bash_history
C /usr
C 
/usr/share C /usr/share/nginx C /usr/share/nginx/html C /usr/share/nginx/html/index.html C /run A /run/nginx.pid

現在我們定製好了變化,我們希望能將其儲存下來形成映象。要知道,當我們執行一個容器的時候(如果不使用卷的話),我們做的任何檔案修改都會被記錄於容器儲存器裡。而Docker提供了一個 docker commit 命令,可以將容器的儲存層儲存下來稱為映象。也就是說在原有映象的基礎上,再疊加上容器的儲存層,並構成新的映象。以後我們在執行這個新映象的時候,就會擁有原有容器最後的檔案變化。

docker commit 語法格式:

docker commit [選項] <容器ID或容器名> [<倉庫名>[:<標籤>]]

示例將上面更改首頁的webServer 容器儲存為映象:

[root@server ~]# docker commit \
--author "wallace <[email protected]>" \
--message "修復了預設首頁" \
web \
nginx:v1

[root@server ~]# docker images nginx   #檢視製作完成的nginx映象
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               v1                  b639fbcc5ec4        2 minutes ago       183MB
nginx              latest               5766334bdaa0        21 months ago       183MB

其中 --author 是指定修改的作者,而 --message 則是記錄本次修改的內容。這點和 git 版本控制器相似。還可以使用 docker history 具體檢視映象內的歷史記錄

[root@server ~]# docker history nginx:v1  #檢視nginx:v1映象的歷史記錄
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
b639fbcc5ec4        5 minutes ago       nginx -g daemon off;                            157B                修復了預設首頁
5766334bdaa0        21 months ago       /bin/sh -c #(nop)  CMD ["nginx" "-g" "daemon…   0B                  
<missing>           21 months ago       /bin/sh -c #(nop)  EXPOSE 443/tcp 80/tcp        0B                  
<missing>           21 months ago       /bin/sh -c ln -sf /dev/stdout /var/log/nginx…   22B                 
<missing>           21 months ago       /bin/sh -c echo "deb http://nginx.org/packag…   59.1MB              
<missing>           21 months ago       /bin/sh -c set -e;  NGINX_GPGKEY=573BFD6B3D8…   4.9kB               
<missing>           21 months ago       /bin/sh -c #(nop)  ENV NGINX_VERSION=1.11.13…   0B                  
<missing>           21 months ago       /bin/sh -c #(nop)  MAINTAINER NGINX Docker M…   0B                  
<missing>           21 months ago       /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B                  
<missing>           21 months ago       /bin/sh -c #(nop) ADD file:4eedf861fb567fffb…   123MB

新的映象定製好後,我們來執行這個映象

[root@server ~]# docker run --name web1 -d -p 81:80 nginx:v1  #基於上面新建的nginx:v1啟動一個名字為web1的容器

當我們訪問宿主機IP:81時候,其內容和之前修改後的 webServer一樣

至此,完成了一個定製映象,使用的是 docker commit 命令,手動給舊的映象添加了新的一層,形成了新的映象,對映象多層儲存應該有了很直觀的感受。

謹慎使用docker commit

使用 docker commit 命令雖然可以比較直觀的幫助理解映象分層儲存的概念,但是實際環境中很少這樣使用。

首先, 從上面的 docker diff webServer 的結果中,可以發現除了真正想要修改的 /usr/share/nginx/html/index.html 檔案外,由於命令的執行,還有很多檔案被改動或添加了。這還只是最簡單的操作,如果安裝軟體包、編譯構建,那麼有大量的無關內容被新增進來,如果不小心清理,將會導致映象為臃腫。

此外,使用docker commit 意味著所有對映象的操作都是黑箱操作,生成的映象也被稱為黑箱映象,換句話說,就是除了製作映象的人知道執行過什麼命令、怎麼生成的映象,別人根本無法從知。雖熱docker diff 或許可以告訴得到一些線索,但是遠遠不到可以確保生成一致映象的地步。這種黑箱映象的維護工作是非常痛苦的。

而且,除當前層外,之前的每一層都是不會發生改變的,也就是說,任何修改的結果僅僅是在當前層進行標記、新增、修改,而不會改動上一層。如果使用 docker commit 製作映象,以及後期修改的話,每次一次修改都會讓映象更加臃腫一次,所刪除的上一層的東西並不會丟失,會一直如影隨形的跟著這個映象,即使根本無法訪問到。這會讓映象更加臃腫。