您好,登錄后才能下訂單哦!
本篇文章為大家展示了怎樣進行Docker 鏡像管理的分析,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
直接下載鏡像并啟動容器,這里選擇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 $
啟動參數說明:
-d,表示啟動容器后在宿主機的后臺運行。
-p,端口映射,將宿主機的8001端口,映射到容器內部的80端口。端口映射是network的內容,之后會詳細說明。
查看啟動的容器:
$ 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 $
可以看到端口和端口映射的情況。
這里主要關注COMMAND,上面的顯示被截斷了:
$ docker container ls --no-trunc --format '{{.Command}}' "nginx -g 'daemon off;'" $
這里啟動nginx加了參數,daemon off 字面的意思就是關閉守護進程。這是為了讓nginx在前臺運行。
如果是nginx默認的啟動方式,那么nginx程序將在后臺運行,一旦nginx啟動完就沒有任何程序了,結果容器也就退出了。
在容器中執行任何程序或服務,一定不能在容器中運行在后臺。只要運行在后臺,一啟動就會終止。
既然Nginx已經啟動,就可以直接用瀏覽器訪問了。并且做了端口映射,所以可以直接通過宿主機的端口來進行訪問:http://[宿主機的IP地址]:8001
。
容器的日志
每一個容器的目的只是為了運行一個程序,這個程序就是容器的主進程PID=1。傳統的程序的日志一般是保存在日志文件中的,但是容器中沒有這個必要。因為現在整個容器就只為了運行一個進程,日志就可以直接打印在控制臺上了,就是程序直接在前臺運行的效果。
使用下面的命令可以查看日志:
$ docker container logs web1
查看后,訪問幾次頁面再看下是否有訪問日志刷新。
首先,直接啟動一個redis:
$ docker container run --name redis -d redis:alpine
容器啟動后,依然是停留在宿主機的命令行界面。
進入容器內部
現在需要進入到容器內部進行操作,就像之前的busybox那樣。但是,這次容量內部運行的是一個 redis-server 的程序,并且一個容器內部一般只運行一個程序。所以容器里并沒有shell。
這里和之前的busybox容器的情況不同,在busybox容器內部就有一個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 #
進入并且執行命令查看當前容器內的進程。
這里看到,除了ps命令,還有原本的 redis-server 以及進入容器時啟動的shell。所以在容器內部運行多個進程也是可以的,現在就是這個情況。不過一般也就這在這種場景下需要在容器中運行多個進程。
執行其他操作
既然都進來了,就運行些命令。看下系統的時間:
/data # date Tue Jul 16 13:03:05 UTC 2019 /data #
時間沒問題,不過時區不對,這個略過。
查看端口監聽情況:
/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鏡像的基礎知識。
docker鏡像含有啟動容器所需要的文件系統及其內容,因此,其用于創建并啟動docker容器。
采用分層構建機制,最底層為bootfs,次之為rootfs:
bootfs: 用于系統引導的文件系統,包括bootloader和kernel,容器啟動完成后會被卸載以節約內存資源
rootfs: 位于bootfs之上,表現為docker容器的根文件系統:
傳統模式中,系統啟動之時,內核掛載rootfs時會首先將其掛載為“只讀”模式,完整性自檢完成后將其重新掛載為讀寫模式
docker中,rootfs由內核掛載為“只讀”模式,而后通過"聯合掛載“技術額外掛載一個”可寫“層
啟動一個busybox容器,命令ls查看容器內部,擁有完整意義上的文件系統:
$ docker container run --name shell -it busybox / # ls bin dev etc home proc root sys tmp usr var / # exit $
分層構建的鏡像:
位于下層的鏡像為父鏡像(parent image),最底層的稱為基礎鏡像(base image)
最上層為"可讀寫”層,其下的均為"只讀“層
如圖,是一個Apache鏡像。最底層是一個 Debian 的基礎鏡像,一個純凈的操作系統。在系統之上,添加了一個 emacs,這是一個代碼編輯器。再然后添加了一個 Apache。這里每添加一個軟件都是一個獨立的層次。
最最下面的bootfs,在容器啟動時,一旦引導完rootfs就會被卸載并移除(從內存中移除)。
對于一個容器,所有寫操作,只能在最上層的可讀寫層進行。如果容器刪除了,這個最上面的可讀寫層也會一起被刪除。
關于Linux操作系統的基礎鏡像,可以參考下表來選擇合適的基礎鏡像:
busybox: 臨時測試用
alpine: 主要用于測試,也可用于生產環境
centos: 主要用于生產環境,支持CentOS/Red Hat,常用于追求穩定性的企業應用
ubuntu: 主要用于生產環境,常用于人工智能計算和企業應用
debian: 主要用于生產環境
推薦使用Alpine鏡像,因為它被嚴格控制并保持最小尺寸(目前小于5MB),但它仍然是一個完整的發行版。
alpine的好處主要是小,并且基本功能全。用于測試是非常方便的,而且生產上也是可以用。雖然不建議這么做,主要是因為缺少調試工具。
busybox的鏡像比alpine更小,它并不是一個系統發行版。最初這個工具是為了在一張軟盤上創建一個可引導的 GNU/Linux 系統,這可以用作安裝盤和急救盤。它是一個集成了三百多個最常用Linux命令和工具的軟件。所以如果是需要啟動一個容器并運行一些系統的工具和命令,那么可以使用這個作為基礎鏡像。
另外3個就是常用的Linux發行版,推薦在生產系統上用。鏡像大也不是什么問題,因為容器是分層構建的,所以本地的多個鏡像理論上是共用同一個基礎鏡像。
Docker鏡像的分層構建和聯合掛載依賴于它的專有文件系統。
aufs
在早期這個文件系統是aufs(advanced multi-layered unification filesystem), 高級多層統一文件系統。
overlayfs
aufs的競爭產品是overlayfs,overlayfs在3.18版本開始被合并到Linux內核。使用docker info
命令可以找到當前使用的文件系統:
Storage Driver: overlay2 Backing Filesystem: xfs Supports d_tpe: true Native Overlay Diff: true
overlay2是一種抽象的二級文件系統,它需要建構在本地文件系統之上。上面的信息顯示,這里作為基礎的本地文件系統是xfs。
其他文件系統
docker的分層鏡像,除了aufs,還支持btrfs,devicemapper和vfs等。早期默認支持的文件系統:
Ubuntu系統,默認使用aufs
CentOS系統,默認使用devicemapper
Device Mapper 是 Linux2.6 內核中支持邏輯卷管理的通用設備映射機制,它為實現用于存儲資源管理的塊設備驅動提供了一個高度模塊化的內核構架。
最著名的 Registry 就是Docker Hub: https://hub.docker.com/
其他的和有比如這個Quay: https://quay.io/
啟動容器時,會先試圖從本地獲取相關的鏡像。如果本地鏡像不存在,再從Registry中下載鏡像并保存到本地。
一個Registry通常由2部分組成:
Repository
Index
Repository,由特定的docker鏡像的所有迭代版本組成的鏡像倉庫。一個Registry中可以存在多個Repository。每個倉庫可以包含多個Tag(標簽),每個標簽對應一個鏡像。
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提供了一個完成用戶認證功能的檢索接口
這里只是簡單的提一下這個概念,主要是程序配置文件的問題。
鏡像的使用有一個問題,就是鏡像內部使用的配置信息。配置信息可以直接注入在鏡像里,但是這樣就要為不同的配置生成好多個不同版本的鏡像。
云原生是一種為了云計算環境運行而生的應用程序,并且可以解決不同配置的信息的問題。
以Nginx為例,傳統的開發運行在服務器上的程序,使用配置文件來管理配置。如果把它托管到容器云上運行,就會有諸多不便之處,最大的問題就是修改配置文件。
而那些云原生開發的程序,會使用對于云計算場景方便的接口來提供配置邏輯。具體到容器,相當于為應用程序加了一層外殼,再去操作里面的數據是不方便的。有一種做法是向容器傳入環境變量來傳遞配置信息,而配置則可以從環境變量加載自動注入到配置中。
云原生的大量配置都可以直接通過環境變量來獲取。
使用命令docker commint
會把容器最上面的可寫層,單獨創建為一個鏡像層,生成一個新的鏡像。
其他制作鏡像的方法,并且是制作鏡像的最主要的方法是,基于Dockerfile制作鏡像。這部分內容很重要也很多,需要單獨再寫一篇。
基于busybox,添加一個httpd的服務。
$ 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> / #
在容器內部進行修改
現在創建好了一個html文件,但是下次docker再啟動這個容器時這個文件是不會有的。現在需要做的是將之前做的改變保存好。
保存對容器的修改,生成新的鏡像
要保持這個容器的運行狀態,那就再另外開一個會話執行commit命令:
$ docker commit -p httpd sha256:5bd093efd84001a2f7412292431ead5c760acef8f4e3a2298abf9f28aa7b3cd7 $
這里的-p參數是將容器處于暫停狀態,這樣可以防止鏡像制作過程中可能會有操作來改變容器的內容,建議-p參數都加上。
查看鏡像信息,新制作完成的鏡像信息如下:
$ 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 $
這里又添加了一個標簽,然后再把這個標簽給刪除,命令執行結果顯示只是把指定的標簽去掉了。所以同一個鏡像打了多個標簽,本地存的只有一份。刪除某個標簽的鏡像,只是把這個標簽從鏡像標簽的列表里去除。之后刪除最后一個標簽的時候才是真正的刪除了一個鏡像。
使用 inspect 命令可以查看docker對象的底層信息。這里要找的是鏡像的底層信息中的默認啟動的命令,具體如下:
$ docker image inspect busybox "Cmd": [ "sh" ], $
啟動時運行的命令是sh,這個也是busybox鏡像默認啟動時運行的命令,因為制作新鏡像的時候沒有指定這個內容。
重新制作一版新的鏡像,這次要指定默認啟動時運行的命令:
$ docker commit -c 'CMD ["httpd", "-f", "-h", "/var/www/"]' -p httpd myimg/httpd:v2 sha256:850da6d87c65a2c6084cdbfcabbeeeaf6c13ddbb9fbb984fec5ca05cab38830d $
參數-c不是用來指定命令的,而是指定所有要做的修改,當然這里只要修改啟動的命令。
httpd命令參數說明
關于啟動命令httpd -f -h /var/www/
,這個具體可以去看httpd的參數說明。-f表示作為守護進程也就是在前臺運行,而-h參數則是指定首頁的路徑。
帶參數啟動鏡像:
$ 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命令僅有一個參數-o,就是指定導出的位置。如果沒有-o參數,那就是輸出到終端。不過也不能直接輸出到終端,這樣的做法是再通過輸出重定向來把內容保存起來。所以這條命令的效果是一樣的:
$ docker image save myimg/httpd > httpd2.tar
可以加上標簽信息,就可以指定打包對應的Tag的鏡像。鏡像的參數可以傳入多個,就打包多個鏡像:
$ docker image save -o httpd3.tar myimg/httpd:v1 myimg/httpd:v2
導出為tar文件
導入的文件名可以任意指定,不過建議使用tar擴展名。這確實是一個tar包,使用tar命令來查看tar包內部的文件列表:
$ 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。執行打包命令的時候指定了v1和v2標簽,并沒有指定latest標簽。不過這里能看到所有的3個標簽。所以標簽只是一個標簽,一個鏡像可以有多個標簽,但是不同標簽的鏡像是同一個鏡像。
不使用-i參數的話,默認從標準輸出導入,用下面的方法也是一樣的:
$ 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文件,也可以從幾種壓縮文件直接導入。操作起來都一樣,程序會自己識別。應該是通過文件名后綴吧。
上述內容就是怎樣進行Docker 鏡像管理的分析,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。