您好,登錄后才能下訂單哦!
本篇文章為大家展示了怎樣進行Docker 鏡像管理的分析,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
直接下載鏡像并啟動容器,這里選擇alpine版的:
$ docker run --name web1 -p 8001:80 -d nginx:alpine Unable to find image 'nginx:alpine' locally alpine: Pulling from library/nginx e7c96db7181b: Downloading 3fb6217217ef: Download complete alpine: Pulling from library/nginx e7c96db7181b: Pull complete 3fb6217217ef: Pull complete Digest: sha256:17bd1698318e9c0f9ba2c5ed49f53d690684dab7fe3e8019b855c352528d57be Status: Downloaded newer image for nginx:alpine 01c17a72e943e93d71b56b433bea7a3d6ffa1f848dc3947f2adaf2bb2e3e7fee $
啟動參數(shù)說明:
-d,表示啟動容器后在宿主機的后臺運行。
-p,端口映射,將宿主機的8001端口,映射到容器內(nèi)部的80端口。端口映射是network的內(nèi)容,之后會詳細說明。
查看啟動的容器:
$ docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f57cd5f9d50f nginx:alpine "nginx -g 'daemon of…" 13 minutes ago Up 12 minutes 0.0.0.0:8001->80/tcp web1 $
可以看到端口和端口映射的情況。
這里主要關(guān)注COMMAND,上面的顯示被截斷了:
$ docker container ls --no-trunc --format '{{.Command}}' "nginx -g 'daemon off;'" $
這里啟動nginx加了參數(shù),daemon off 字面的意思就是關(guān)閉守護進程。這是為了讓nginx在前臺運行。
如果是nginx默認的啟動方式,那么nginx程序?qū)⒃诤笈_運行,一旦nginx啟動完就沒有任何程序了,結(jié)果容器也就退出了。
在容器中執(zhí)行任何程序或服務(wù),一定不能在容器中運行在后臺。只要運行在后臺,一啟動就會終止。
既然Nginx已經(jīng)啟動,就可以直接用瀏覽器訪問了。并且做了端口映射,所以可以直接通過宿主機的端口來進行訪問:http://[宿主機的IP地址]:8001
。
容器的日志
每一個容器的目的只是為了運行一個程序,這個程序就是容器的主進程PID=1。傳統(tǒng)的程序的日志一般是保存在日志文件中的,但是容器中沒有這個必要。因為現(xiàn)在整個容器就只為了運行一個進程,日志就可以直接打印在控制臺上了,就是程序直接在前臺運行的效果。
使用下面的命令可以查看日志:
$ docker container logs web1
查看后,訪問幾次頁面再看下是否有訪問日志刷新。
首先,直接啟動一個redis:
$ docker container run --name redis -d redis:alpine
容器啟動后,依然是停留在宿主機的命令行界面。
進入容器內(nèi)部
現(xiàn)在需要進入到容器內(nèi)部進行操作,就像之前的busybox那樣。但是,這次容量內(nèi)部運行的是一個 redis-server 的程序,并且一個容器內(nèi)部一般只運行一個程序。所以容器里并沒有shell。
這里和之前的busybox容器的情況不同,在busybox容器內(nèi)部就有一個shell。所以直接進入是沒有任何終端界面的。這里需要啟動一個shell然后進入:
$ docker container exec -it redis /bin/sh /data # ps PID USER TIME COMMAND 1 redis 0:00 redis-server 12 root 0:00 /bin/sh 23 root 0:00 ps /data #
進入并且執(zhí)行命令查看當前容器內(nèi)的進程。
這里看到,除了ps命令,還有原本的 redis-server 以及進入容器時啟動的shell。所以在容器內(nèi)部運行多個進程也是可以的,現(xiàn)在就是這個情況。不過一般也就這在這種場景下需要在容器中運行多個進程。
執(zhí)行其他操作
既然都進來了,就運行些命令??聪孪到y(tǒng)的時間:
/data # date Tue Jul 16 13:03:05 UTC 2019 /data #
時間沒問題,不過時區(qū)不對,這個略過。
查看端口監(jiān)聽情況:
/data # netstat -tnl Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN tcp 0 0 :::6379 :::* LISTEN /data #
使用 redis-cli 命令:
/data # redis-cli 127.0.0.1:6379> set age 23 OK 127.0.0.1:6379> set name Adam OK 127.0.0.1:6379> keys * 1) "name" 2) "age" 127.0.0.1:6379> exit /data # exit $
這里看到 redis-cli 自帶用戶界面,所以不用啟動 /bin/sh 也能直接進來:
$ docker container exec -it redis redis-cli 127.0.0.1:6379> exit $
Docker鏡像的基礎(chǔ)知識。
docker鏡像含有啟動容器所需要的文件系統(tǒng)及其內(nèi)容,因此,其用于創(chuàng)建并啟動docker容器。
采用分層構(gòu)建機制,最底層為bootfs,次之為rootfs:
bootfs: 用于系統(tǒng)引導的文件系統(tǒng),包括bootloader和kernel,容器啟動完成后會被卸載以節(jié)約內(nèi)存資源
rootfs: 位于bootfs之上,表現(xiàn)為docker容器的根文件系統(tǒng):
傳統(tǒng)模式中,系統(tǒng)啟動之時,內(nèi)核掛載rootfs時會首先將其掛載為“只讀”模式,完整性自檢完成后將其重新掛載為讀寫模式
docker中,rootfs由內(nèi)核掛載為“只讀”模式,而后通過"聯(lián)合掛載“技術(shù)額外掛載一個”可寫“層
啟動一個busybox容器,命令ls查看容器內(nèi)部,擁有完整意義上的文件系統(tǒng):
$ docker container run --name shell -it busybox / # ls bin dev etc home proc root sys tmp usr var / # exit $
分層構(gòu)建的鏡像:
位于下層的鏡像為父鏡像(parent image),最底層的稱為基礎(chǔ)鏡像(base image)
最上層為"可讀寫”層,其下的均為"只讀“層
如圖,是一個Apache鏡像。最底層是一個 Debian 的基礎(chǔ)鏡像,一個純凈的操作系統(tǒng)。在系統(tǒng)之上,添加了一個 emacs,這是一個代碼編輯器。再然后添加了一個 Apache。這里每添加一個軟件都是一個獨立的層次。
最最下面的bootfs,在容器啟動時,一旦引導完rootfs就會被卸載并移除(從內(nèi)存中移除)。
對于一個容器,所有寫操作,只能在最上層的可讀寫層進行。如果容器刪除了,這個最上面的可讀寫層也會一起被刪除。
關(guān)于Linux操作系統(tǒng)的基礎(chǔ)鏡像,可以參考下表來選擇合適的基礎(chǔ)鏡像:
busybox: 臨時測試用
alpine: 主要用于測試,也可用于生產(chǎn)環(huán)境
centos: 主要用于生產(chǎn)環(huán)境,支持CentOS/Red Hat,常用于追求穩(wěn)定性的企業(yè)應(yīng)用
ubuntu: 主要用于生產(chǎn)環(huán)境,常用于人工智能計算和企業(yè)應(yīng)用
debian: 主要用于生產(chǎn)環(huán)境
推薦使用Alpine鏡像,因為它被嚴格控制并保持最小尺寸(目前小于5MB),但它仍然是一個完整的發(fā)行版。
alpine的好處主要是小,并且基本功能全。用于測試是非常方便的,而且生產(chǎn)上也是可以用。雖然不建議這么做,主要是因為缺少調(diào)試工具。
busybox的鏡像比alpine更小,它并不是一個系統(tǒng)發(fā)行版。最初這個工具是為了在一張軟盤上創(chuàng)建一個可引導的 GNU/Linux 系統(tǒng),這可以用作安裝盤和急救盤。它是一個集成了三百多個最常用Linux命令和工具的軟件。所以如果是需要啟動一個容器并運行一些系統(tǒng)的工具和命令,那么可以使用這個作為基礎(chǔ)鏡像。
另外3個就是常用的Linux發(fā)行版,推薦在生產(chǎn)系統(tǒng)上用。鏡像大也不是什么問題,因為容器是分層構(gòu)建的,所以本地的多個鏡像理論上是共用同一個基礎(chǔ)鏡像。
Docker鏡像的分層構(gòu)建和聯(lián)合掛載依賴于它的專有文件系統(tǒng)。
aufs
在早期這個文件系統(tǒng)是aufs(advanced multi-layered unification filesystem), 高級多層統(tǒng)一文件系統(tǒng)。
overlayfs
aufs的競爭產(chǎn)品是overlayfs,overlayfs在3.18版本開始被合并到Linux內(nèi)核。使用docker info
命令可以找到當前使用的文件系統(tǒng):
Storage Driver: overlay2 Backing Filesystem: xfs Supports d_tpe: true Native Overlay Diff: true
overlay2是一種抽象的二級文件系統(tǒng),它需要建構(gòu)在本地文件系統(tǒng)之上。上面的信息顯示,這里作為基礎(chǔ)的本地文件系統(tǒng)是xfs。
其他文件系統(tǒng)
docker的分層鏡像,除了aufs,還支持btrfs,devicemapper和vfs等。早期默認支持的文件系統(tǒng):
Ubuntu系統(tǒng),默認使用aufs
CentOS系統(tǒng),默認使用devicemapper
Device Mapper 是 Linux2.6 內(nèi)核中支持邏輯卷管理的通用設(shè)備映射機制,它為實現(xiàn)用于存儲資源管理的塊設(shè)備驅(qū)動提供了一個高度模塊化的內(nèi)核構(gòu)架。
最著名的 Registry 就是Docker Hub: https://hub.docker.com/
其他的和有比如這個Quay: https://quay.io/
啟動容器時,會先試圖從本地獲取相關(guān)的鏡像。如果本地鏡像不存在,再從Registry中下載鏡像并保存到本地。
一個Registry通常由2部分組成:
Repository
Index
Repository,由特定的docker鏡像的所有迭代版本組成的鏡像倉庫。一個Registry中可以存在多個Repository。每個倉庫可以包含多個Tag(標簽),每個標簽對應(yīng)一個鏡像。
Repository可分為頂層倉庫和用戶倉庫,用戶倉庫名稱格式為“用戶名/倉庫名”。使用docker search
命令看一下:
$ docker search --limit 3 nginx NAME DESCRIPTION STARS OFFICIAL AUTOMATED nginx Official build of Nginx. 11704 [OK] jwilder/nginx-proxy Automated Nginx reverse proxy for docker con… 1628 [OK] bitnami/nginx Bitnami nginx Docker Image 69 [OK] $
這里顯示了3個,第一個是沒有用戶名的屬于頂層倉庫。后面是用戶倉庫,可以看到分別屬于的用戶名。
Idxex的作用:
維護用戶賬戶、鏡像的校驗以及公共命名空間的信息
相當于為Registry提供了一個完成用戶認證功能的檢索接口
這里只是簡單的提一下這個概念,主要是程序配置文件的問題。
鏡像的使用有一個問題,就是鏡像內(nèi)部使用的配置信息。配置信息可以直接注入在鏡像里,但是這樣就要為不同的配置生成好多個不同版本的鏡像。
云原生是一種為了云計算環(huán)境運行而生的應(yīng)用程序,并且可以解決不同配置的信息的問題。
以Nginx為例,傳統(tǒng)的開發(fā)運行在服務(wù)器上的程序,使用配置文件來管理配置。如果把它托管到容器云上運行,就會有諸多不便之處,最大的問題就是修改配置文件。
而那些云原生開發(fā)的程序,會使用對于云計算場景方便的接口來提供配置邏輯。具體到容器,相當于為應(yīng)用程序加了一層外殼,再去操作里面的數(shù)據(jù)是不方便的。有一種做法是向容器傳入環(huán)境變量來傳遞配置信息,而配置則可以從環(huán)境變量加載自動注入到配置中。
云原生的大量配置都可以直接通過環(huán)境變量來獲取。
使用命令docker commint
會把容器最上面的可寫層,單獨創(chuàng)建為一個鏡像層,生成一個新的鏡像。
其他制作鏡像的方法,并且是制作鏡像的最主要的方法是,基于Dockerfile制作鏡像。這部分內(nèi)容很重要也很多,需要單獨再寫一篇。
基于busybox,添加一個httpd的服務(wù)。
$ docker run --name httpd -it busybox / # echo "<h2>Hello world. Busybox httpd.</h2>" > /var/www/index.html / # cat /var/www/index.html <h2>Hello world. Busybox httpd.</h2> / #
在容器內(nèi)部進行修改
現(xiàn)在創(chuàng)建好了一個html文件,但是下次docker再啟動這個容器時這個文件是不會有的?,F(xiàn)在需要做的是將之前做的改變保存好。
保存對容器的修改,生成新的鏡像
要保持這個容器的運行狀態(tài),那就再另外開一個會話執(zhí)行commit命令:
$ docker commit -p httpd sha256:5bd093efd84001a2f7412292431ead5c760acef8f4e3a2298abf9f28aa7b3cd7 $
這里的-p參數(shù)是將容器處于暫停狀態(tài),這樣可以防止鏡像制作過程中可能會有操作來改變?nèi)萜鞯膬?nèi)容,建議-p參數(shù)都加上。
查看鏡像信息,新制作完成的鏡像信息如下:
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE <none> <none> 5bd093efd840 2 minutes ago 1.22MB busybox latest e4db68de4ff2 4 weeks ago 1.22MB $
由于制作的時候沒有指明倉庫名和標簽名,所以都是空。這兩個字段是允許為空的,這樣只能通過鏡像的ID來指明這個鏡像。
添加標簽信息
為了引用時方便,還是把倉庫名和標簽名加上吧:
$ docker image tag 5bd093efd840 myimg/httpd:v1 $ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE myimg/httpd v1 5bd093efd840 9 minutes ago 1.22MB busybox latest e4db68de4ff2 4 weeks ago 1.22MB $
一個鏡像可以有多個標簽,再加一個latest標簽:
$ docker image tag myimg/httpd:v1 myimg/httpd:latest $ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE myimg/httpd latest 5bd093efd840 11 minutes ago 1.22MB myimg/httpd v1 5bd093efd840 11 minutes ago 1.22MB busybox latest e4db68de4ff2 4 weeks ago 1.22MB $
這里可以確認下,2個標簽的鏡像的ID是一樣的,所以這里是一個鏡像,只是為這個鏡像添加了2個標簽。
刪除標簽
沒有刪除標簽的命令,要刪除某個標簽,就直接用刪除鏡像的命令:
$ docker image tag myimg/httpd:v1 myimg/httpd:tmp1 $ docker image rm myimg/httpd:tmp1 Untagged: myimg/httpd:tmp1 $
這里又添加了一個標簽,然后再把這個標簽給刪除,命令執(zhí)行結(jié)果顯示只是把指定的標簽去掉了。所以同一個鏡像打了多個標簽,本地存的只有一份。刪除某個標簽的鏡像,只是把這個標簽從鏡像標簽的列表里去除。之后刪除最后一個標簽的時候才是真正的刪除了一個鏡像。
使用 inspect 命令可以查看docker對象的底層信息。這里要找的是鏡像的底層信息中的默認啟動的命令,具體如下:
$ docker image inspect busybox "Cmd": [ "sh" ], $
啟動時運行的命令是sh,這個也是busybox鏡像默認啟動時運行的命令,因為制作新鏡像的時候沒有指定這個內(nèi)容。
重新制作一版新的鏡像,這次要指定默認啟動時運行的命令:
$ docker commit -c 'CMD ["httpd", "-f", "-h", "/var/www/"]' -p httpd myimg/httpd:v2 sha256:850da6d87c65a2c6084cdbfcabbeeeaf6c13ddbb9fbb984fec5ca05cab38830d $
參數(shù)-c不是用來指定命令的,而是指定所有要做的修改,當然這里只要修改啟動的命令。
httpd命令參數(shù)說明
關(guān)于啟動命令httpd -f -h /var/www/
,這個具體可以去看httpd的參數(shù)說明。-f表示作為守護進程也就是在前臺運行,而-h參數(shù)則是指定首頁的路徑。
帶參數(shù)啟動鏡像:
$ docker container run --name httpd2 -d -p 8002:80 myimg/httpd:v2 80522bb422e16dae4ea052bcb36e51203f4d7b023fefdf3de4114598b3e95b29 $
鏡像啟動后,可以使用瀏覽器訪問宿主機的IP地址加上映射的端口號來打開這個頁面,比如:http://192.168.24.170:8002/
可以在已有鏡像的主機上把鏡像打包,將打包的文件復制到另外一臺主機上再把鏡像導入,就可以在主機之間傳遞鏡像了。這種方法不需要連接鏡像倉庫。
導出鏡像就是將鏡像導出到一個tar包:
$ docker image save -o httpd.tar myimg/httpd
這條命令省略了Tag標簽,這樣就會把整個倉庫打包,就是打包所有的版本。
save命令僅有一個參數(shù)-o,就是指定導出的位置。如果沒有-o參數(shù),那就是輸出到終端。不過也不能直接輸出到終端,這樣的做法是再通過輸出重定向來把內(nèi)容保存起來。所以這條命令的效果是一樣的:
$ docker image save myimg/httpd > httpd2.tar
可以加上標簽信息,就可以指定打包對應(yīng)的Tag的鏡像。鏡像的參數(shù)可以傳入多個,就打包多個鏡像:
$ docker image save -o httpd3.tar myimg/httpd:v1 myimg/httpd:v2
導出為tar文件
導入的文件名可以任意指定,不過建議使用tar擴展名。這確實是一個tar包,使用tar命令來查看tar包內(nèi)部的文件列表:
$ tar -tvf httpd.tar -rw-r--r-- 0/0 1491 2019-07-18 15:10 25079c1e47bf896a028e55d715dc06e251f3efe53ca655ad63f6085ce6a465a8.json -rw-r--r-- 0/0 1464 2019-07-18 15:05 7f36d8e3488df22381081d68c7f2215750167250114abd0b2f31d99e81a7bfd7.json drwxr-xr-x 0/0 0 2019-07-18 15:05 957ac2430f81aaa485efe07e872a460156d73e48f53f31a9743ed0d5f0fa44d7/ -rw-r--r-- 0/0 3 2019-07-18 15:05 957ac2430f81aaa485efe07e872a460156d73e48f53f31a9743ed0d5f0fa44d7/VERSION -rw-r--r-- 0/0 1081 2019-07-18 15:05 957ac2430f81aaa485efe07e872a460156d73e48f53f31a9743ed0d5f0fa44d7/json -rw-r--r-- 0/0 4608 2019-07-18 15:05 957ac2430f81aaa485efe07e872a460156d73e48f53f31a9743ed0d5f0fa44d7/layer.tar drwxr-xr-x 0/0 0 2019-07-18 15:10 a24e93a2c2b0548055a10d18f0c88dc138c57ee6f13020538bf80da2bfefc59f/ -rw-r--r-- 0/0 3 2019-07-18 15:10 a24e93a2c2b0548055a10d18f0c88dc138c57ee6f13020538bf80da2bfefc59f/VERSION -rw-r--r-- 0/0 1107 2019-07-18 15:10 a24e93a2c2b0548055a10d18f0c88dc138c57ee6f13020538bf80da2bfefc59f/json -rw-r--r-- 0/0 4608 2019-07-18 15:10 a24e93a2c2b0548055a10d18f0c88dc138c57ee6f13020538bf80da2bfefc59f/layer.tar drwxr-xr-x 0/0 0 2019-07-18 15:05 dea411b43d1b59da62f22c37c8507e7757c2dd9a5467a523f92e612d88e83ae8/ -rw-r--r-- 0/0 3 2019-07-18 15:05 dea411b43d1b59da62f22c37c8507e7757c2dd9a5467a523f92e612d88e83ae8/VERSION -rw-r--r-- 0/0 406 2019-07-18 15:05 dea411b43d1b59da62f22c37c8507e7757c2dd9a5467a523f92e612d88e83ae8/json -rw-r--r-- 0/0 1441280 2019-07-18 15:05 dea411b43d1b59da62f22c37c8507e7757c2dd9a5467a523f92e612d88e83ae8/layer.tar -rw-r--r-- 0/0 579 1970-01-01 08:00 manifest.json -rw-r--r-- 0/0 238 1970-01-01 08:00 repositories $
從IMAGE ID可以看出,這里確實是將2個版本的鏡像到打包了。
導出并壓縮
用下面的方法完成導出并壓縮:
$ docker save myimage:latest | gzip > myimage_latest.tar.gz
使用load命令可以方便的將鏡像導入:
$ docker image load -i httpd3.tar 6194458b07fc: Loading layer [==================================================>] 1.441MB/1.441MB dd0dd7cb79c9: Loading layer [==================================================>] 4.608kB/4.608kB Loaded image: myimg/httpd:latest Loaded image: myimg/httpd:v1 698704828883: Loading layer [==================================================>] 4.608kB/4.608kB Loaded image: myimg/httpd:v2 $ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE myimg/httpd v2 25079c1e47bf 30 minutes ago 1.22MB myimg/httpd latest 7f36d8e3488d 35 minutes ago 1.22MB myimg/httpd v1 7f36d8e3488d 35 minutes ago 1.22MB $
上面最后一次打包的文件是 httpd3.tar。執(zhí)行打包命令的時候指定了v1和v2標簽,并沒有指定latest標簽。不過這里能看到所有的3個標簽。所以標簽只是一個標簽,一個鏡像可以有多個標簽,但是不同標簽的鏡像是同一個鏡像。
不使用-i參數(shù)的話,默認從標準輸出導入,用下面的方法也是一樣的:
$ docker image load < httpd3.tar
導入壓縮文件
Load an image or repository from a tar archive (even if compressed with gzip, bzip2, or xz) from a file or STDIN. It restores both images and tags.
導入鏡像可以從tar文件,也可以從幾種壓縮文件直接導入。操作起來都一樣,程序會自己識別。應(yīng)該是通過文件名后綴吧。
上述內(nèi)容就是怎樣進行Docker 鏡像管理的分析,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。