|NO.Z.00016|——————————|CloudVirtualiZation|——|Cloud&Docker儲存.V01|-------------------------------------|資料儲存|
阿新 • • 發佈:2022-03-27
[CloudVirtualiZation:Cloud&Docker儲存.V01] [Applications.CloudVirtualiZation] [|docker|docker資料儲存|資料卷特性|容器中的資料卷Volume|儲存驅動|overlay]
一、資料卷特性
### --- 資料卷特性 ~~~ #Docker映象由多個只讀層疊加而成,啟動容器時,docker會載入只讀映象層並在 ~~~ #映象棧頂部新增一個讀寫層。 ~~~ 如果執行中的容器修改了現有的一個已經存在的檔案, ~~~ 那麼改檔案將會從讀寫層下面的讀寫層複製到讀寫層,該檔案的只讀版本依然存在, ~~~ 只是已經被讀寫層中改檔案的副本所隱藏,次既“寫時複製”機制。
### --- 資料卷的意義:
~~~ 關閉並重啟容器,器資料不受影響;但刪除docker容器,則其改變將會全部丟失
~~~ # 存在的問題
~~~ 存在於聯合檔案系統中,不易於宿主機訪問
~~~ 容器間資料共享不變
~~~ 刪除容器其資料會丟失
~~~ # 解決方案:“卷”
~~~ “卷”是容器上的一個或多個“目錄”,此類目錄可繞過聯合檔案系統,與宿主機上的某目錄“繫結”
二、容器中的資料卷Volume(yuanjian)~~~ # volume可以在執行容器時即完成創建於繫結操作,當然,前提需要擁有對應的宣告 ~~~ volume的初衷就是資料持久化 ~~~ Bind mount volume ~~~ Docker-managed volume
### --- 容器中的資料卷Volume(yuanjian) docker-managed Volume //1、容器自管理卷 docker run -it --name roc -v MOUNTDIR roc/lamp:v1.0 docker inspect -f {{.Mounts}} roc Bind-mount Volume //2、繫結卷,個人操作的 Docker run -it --name roc -v HOSTDIR:VOLUMEDIR roc/lamp:v1.0 //HOSTDIR:VOLUMEDIR說明需要告訴宿主機的工作目錄和容器的內部目錄 Union Volume //3、聯合卷,既不想借助宿主機的工作目錄,又想實現容器之間的目錄共享解決方案: docker run -it --name roc --volumes-from ContainerName roc/lamp:v1.0
### --- docker-managed Volume:容器自管理卷
[root@hub ~]# docker run --name wordpress -d wordpress
7b7364016246ec2e908253dbed31fe51ecae1d6ff5b0f2419eff5143e2e45f55
[root@hub ~]# docker run --name tomcat -d tomcat:v1.0
[root@hub ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7b7364016246 wordpress "docker-entrypoint..." About a minute ago Up About a minute 80/tcp wordpress
ac2cd6511c27 tomcat:v1.0 "/bin/sh -c '/root..." 3 hours ago Up 8 seconds tomcat
[root@hub ~]# docker inspect tomcat
"Mounts": [], // 當前是空的,意味著當前並沒有用任何的資料在使用,也就是說沒有資料卷的掛載
[root@hub ~]# docker inspect wordpress
"Image": "wordpress",
"Volumes": {
"/var/www/html": {} // Apache的站點,新版的會有掛載資訊
},
"WorkingDir": "/var/www/html",
[root@hub ~]# cd /var/lib/docker/volumes/
[root@hub volumes]# ls
03e24157109b612c13b89c8572aa6b40dffbefa26d0aa80d1c06cf55a54ca449 88bcc0dd06d82b38c178252f25b452140f9e73a99fcc76030caa13ba06f66804
1855483754eb9c1b2722c5b47dfecb4a48828193aca00e46af8f479063012643 a07a07b5fed27f78505618f3c2bfb709fad0809e27fe6e7c34663281bff81678
[root@hub volumes]# docker rm -f $( docker ps -a -q ) // 刪除所有容器,發現我們的管理卷還在,
// 也就說明當我們刪除容器的時候這些管理卷並不會刪除
[root@hub volumes]# rm -rf * // 刪除所有的管理卷
### --- 重新啟動tomcat和WordPress容器
~~~ 啟動了兩個容器只產生了一個管理卷目錄;
~~~ 原因是我們在dockerfile中宣告需要自管理卷的只有WordPress,
~~~ 而tomcat沒有宣告自管理卷。所以它不會建立
[root@hub ~]# docker run --name wordpress -d wordpress
7c94019d4dcfbc09bc9051a72176ba446bfdc098c5ab4b4c1b7b3caf47f36a06
[root@hub ~]# docker run --name tomcat -d tomcat:v1.0
8788994bc479fe7355fddc6a23c60c2e5678fb0886d42e23aefb96096eccae2c
[root@hub ~]# cd /var/lib/docker/volumes/a1b7aff5c6fb9f0fac3ec0a277906b061d22103e0875cb46ff6726a02466b63a/_data/
[root@hub _data]# ls // 裡面的檔案內容為WordPress的網頁檔案
index.php readme.html wp-admin wp-comments-post.php wp-content wp-includes wp-load.php wp-mail.php wp-signup.php xmlrpc.php
license.txt wp-activate.php wp-blog-header.php wp-config-sample.php wp-cron.php wp-links-opml.php wp-login.php wp-settings.php wp-trackback.php
[root@hub _data]# touch yanqi // 標識一下
[root@hub _data]# docker exec -it wordpress /bin/bash
root@7c94019d4dcf:/var/www/html#
root@7c94019d4dcf:/var/www/html# ls
yanqi // 進入容器之後發現我們在宿主機上建立的檔案也會存在
// 說明:如果我們在啟動映象的時候需要使用自管理目錄的時候,就會以為這在啟動容器或者映象的時候它會把目標目錄與/var/lib/docker/volumes/a1b7aff5c6fb9f0fac3ec0a277906b061d22103e0875cb46ff6726a02466b63a/建立的這個隨機目錄與之掛載
root@7c94019d4dcf:/var/www/html# touch {1..100}.txt // 建立100個.txt檔案
[root@hub _data]# docker rm -f wordpress // 刪除WordPress容器後發現100個txt檔案還是存在
wordpress
[root@hub _data]# ls
### --- 自己在編輯映象的時候,怎麼樣達到自管理卷的效果,
~~~ 儲存資料檔案在宿主機的目錄的效果呢?
~~~ 使用centos6.8建立兩個不同的容器
~~~ test1容器使用VOLUME建立掛載點,不生成自管理卷檔案
[root@hub ~]# vim Dockfile
FROM centos:6.8
RUN touch /tmp/1.txt
RUN mkdir /data
CMD tail -f /tmp/1.txt
[root@hub ~]# docker build -t test:v1.0 .
Sending build context to Docker daemon 614.6 MB
Step 1/4 : FROM centos:6.8
---> 82f3b5f3c58f
Step 2/4 : RUN touch /tmp/1.txt
---> Running in 342dc5bed915
---> bb4bdf0ddef4
Removing intermediate container 342dc5bed915
Step 3/4 : RUN mkdir /data
---> Running in e612e66a58b8
---> f901b5f6e1fc
Removing intermediate container e612e66a58b8
Step 4/4 : CMD tail -f /tmp/1.txt
---> Running in 0a86b9a502cc
---> 129c32445f24
Removing intermediate container 0a86b9a502cc
Successfully built 129c32445f24
[root@hub ~]# docker run --name test1 -d test:v1.0
be577d8d058ace68faaa9a9b0c89f03e068ca0a9db8bb81aece56ea870c2da76
[root@hub ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
be577d8d058a test:v1.0 "/bin/sh -c 'tail ..." 19 seconds ago Up 19 seconds test1
[root@hub ~]# docker exec -it test1 /bin/bash
[root@be577d8d058a /]# cd /data/
[root@be577d8d058a data]# touch 1
[root@be577d8d058a data]# ls
1
~~~ 還是隻有一個數據卷,也就意味著建立的這個映象沒有建立一個新的資料卷
[root@hub ~]# cd /var/lib/docker/volumes/
[root@hub volumes]# ls
a1b7aff5c6fb9f0fac3ec0a277906b061d22103e0875cb46ff6726a02466b63a
### --- 我們需要為容器建立掛載點,就是用我們dockerfile中的VOLUME(指定掛載點)
~~~ test2容器使用VOLUME建立掛載點,生成自管理卷檔案
[root@hub ~]# vim Dockerfile
FROM centos:6.8
RUN touch /tmp/1.txt
RUN mkdir /data
VOLUME /data
CMD tail -f /tmp/1.txt
~~~ 帶了容器自管理卷的定義
[root@hub ~]# docker build -t test:v2.0 .
Sending build context to Docker daemon 614.6 MB
Step 1/5 : FROM centos:6.8
---> 82f3b5f3c58f
Step 2/5 : RUN touch /tmp/1.txt
---> Using cache
---> bb4bdf0ddef4
Step 3/5 : RUN mkdir /data
---> Using cache
---> f901b5f6e1fc
Step 4/5 : VOLUME /data
---> Running in 8bd939c63e03
---> 6fdf2c7dff97
Removing intermediate container 8bd939c63e03
Step 5/5 : CMD tail -f /tmp/1.txt
---> Running in dec5d7cab0d5
---> 1c3005cfca5c
Removing intermediate container dec5d7cab0d5
Successfully built 1c3005cfca5c
[root@hub ~]# docker run --name test2 -d test:v2.0
37c8d769a03533432ad3dad8ded3f44afb2c682417d354642152e80850af052f
[root@hub ~]# cd /var/lib/docker/volumes/
~~~ 檢視會多了一個自管理卷目錄檔案
[root@hub volumes]# ls
19f2d88d91c8ac1b70f21bee605f8247f2a713680e9e5e6c6feceacb1549ea39 a1b7aff5c6fb9f0fac3ec0a277906b061d22103e0875cb46ff6726a02466b63a
[root@hub volumes]# cd 19f2d88d91c8ac1b70f21bee605f8247f2a713680e9e5e6c6feceacb1549ea39/
~~~ 進來後發現目錄是空的,因為定義的/data目錄,/data本來就沒有資料,
[root@hub 19f2d88d91c8ac1b70f21bee605f8247f2a713680e9e5e6c6feceacb1549ea39]# ls _data/
### --- 發現容器卷的檔案還是存在,說明子管理卷的檔案沒有刪除
~~~ 這就是怎麼定義容器的自管理卷,以及容器自管理卷的一些特性。
[root@hub ~]# docker exec -it test2 /bin/bash
[root@37c8d769a035 /]# cd data/
[root@37c8d769a035 data]# ls
[root@37c8d769a035 data]# touch {1..66}.txt
[root@hub 19f2d88d91c8ac1b70f21bee605f8247f2a713680e9e5e6c6feceacb1549ea39]# ls _data/
10.txt 13.txt 16.txt // 發現data目錄下已經生成檔案了,說明我們自定義的容器已經被持久化了,生成了自管理檔案
[root@hub ~]# docker rm -f test1 test2 // 刪除test1和test2 容器
test1
test2
[root@hub volumes]# ls
19f2d88d91c8ac1b70f21bee605f8247f2a713680e9e5e6c6feceacb1549ea39 a1b7aff5c6fb9f0fac3ec0a277906b061d22103e0875cb46ff6726a02466b63a
### --- 容器的自管理卷在刪除容器的時候預設不刪除,
~~~ 但我們想刪除容器的時候預設刪除容器的自管理卷設定
~~~ 在我們刪除映象的時候,容器的自管理卷都存在,並且不會刪除;
~~~ 容器的自管理卷我們在定義映象的時候就定義了這個目錄,
~~~ 就代表了這個目錄下的資料是非常重要的,預設不刪除,這是合理選項。
~~~ 但是我想在刪除容器的時候同步刪除容器的自管理卷。
~~~ 刪除容器的時候一起把自管理卷刪除,加上-v選項即可
[root@hub ~]# docker run --name test2 -d test:v2.0 // 啟動一個容器且帶有容器自管理卷
fdf84fc1485d1c0700fb58041e04a03696e885bb8ff0ee61e44643d02782ed11
[root@hub volumes]# ls
19f2d88d91c8ac1b70f21bee605f8247f2a713680e9e5e6c6feceacb1549ea39 cae221727a169860bcca74dde686cc67b40193a77b7caf54fa9dea5ef8bcee30
a1b7aff5c6fb9f0fac3ec0a277906b061d22103e0875cb46ff6726a02466b63a // 產生了一個容器子管理卷檔案
[root@hub ~]# docker rm -f -v test2 // -v同步刪除容器子管理卷
test2
[root@hub volumes]# ls // 自管理卷也會自動刪除,持久化就刪除了。//volumes目錄為空,說明刪除容器的時候同步刪除了宿主機上容器的自管理卷
19f2d88d91c8ac1b70f21bee605f8247f2a713680e9e5e6c6feceacb1549ea39 a1b7aff5c6fb9f0fac3ec0a277906b061d22103e0875cb46ff6726a02466b63a
三、Bind-mount Volume:繫結卷### --- 檢視沒有檔案,這種的是不帶容器子管理卷的。
[root@hub ~]# docker rm -f -v $( docker ps -a -q )
[root@hub ~]# cd /var/lib/docker/volumes/
[root@hub volumes]# rm -rf *
[root@hub volumes]# docker run --name test1 -d test:v1.0
bf7761882c638f52151dee83b1d2ff4ecd7177aa932c8c14e0072ec77bfe02c1
[root@hub volumes]# ls
### --- 像這種情況不帶容器子管理卷,且我們還想讓他用子管理卷,解決方案
~~~ 定義在容器啟動的時候讓宿主機的卷和容器內部的兩個不同的捲進行繫結。
[root@hub volumes]# mkdir /data
[root@hub volumes]# docker run --name test11 -v /data:/data -d test:v1.0 //-v新增子管理卷。/data表示宿主機的子管理卷 :/data表示容器內部的/data
09ccd119260db0689a11eab22dfbd54c688725ee39db755923774701cfda0162
[root@hub data]# touch yanqi // 在宿主機下/data下建立檔案yanqi
[root@hub volumes]# docker exec -it test11 /bin/bash
[root@09ccd119260d /]# ls /data/
yanqi // 有yanqi這個檔案,說明宿主機/data和容器內部/data子管理卷已經完成繫結
### --- 如果在dockerfile中添加了子管理卷定義和在容器啟動的時候
~~~ 又添加了-v自定義了子管理卷的繫結,那個會優先生效,
~~~ test映象已在dockerfile中定義了vloume卷的映象,所以啟動容器時候會有子管理卷出現;
[root@hub volumes]# docker run --name test2 -v /data/:/data/ test:v2.0
### --- 理論上啟動的容器建立的子管理卷不會放在vloume目錄中,
~~~ 會建立對應的目錄與之繫結;現在我們又聲明瞭-v,那麼vloume下的子管理卷還會生效嗎?
~~~ # 說明:我們在dockerfile中定義了vloume卷的某個目錄又在容器啟動的時候加入
~~~ -v選項定義自管理卷的繫結,它在啟動的時候會按照管理員的自繫結捲進行生效,
~~~ 因為-v許可權要高於dockerfile中定義的許可權。
[root@hub volumes]# docker run --name test2 -v /data/:/data/ -d test:v2.0
506baf8aff4be13d048d9dfb4f065a112a58db8b0b516173ecf660ef40953e58
[root@hub volumes]# ls // vloume下沒有生成自管理卷。
[root@hub data]# touch yanqi2 // 在/data下建立yanqi2檔案
[root@hub volumes]# docker exec -it test2 /bin/bash
[root@506baf8aff4b /]# ls /data/
yanqi yanqi2 // 在容器/data目錄下也會建立yanqi2檔案。
### --- 如果我們現在有兩個容器test1和test2;他們想要之間的使用同一個共享子管理卷,怎麼做。
~~~ 實現容器之間目錄之間的共享操作。若有多個目錄,加多個-v即可
[root@hub ~]# docker rm -f -v $( docker ps -a -q )
[root@hub ~]# docker run --name test1 -v /data:/data -d test:v1.0
bc3f877aafc1253a2f20159448da037836cb131e430c7b7548677377ce35902f
~~~ test1yanqi檔案在test2容器/data/目錄下可以檢視到在test1容器建立的test1yanqi檔案。
[root@hub ~]# docker run --name test2 -v /data:/data -d test:v1.0
d1b92fea6940b31f53d2dc34b83060175fd7ff4a1f8933625a9a7438be536545
[root@hub ~]# docker exec -it test1 /bin/bash
[root@bc3f877aafc1 /]# touch /data/test1yanqi
[root@bc3f877aafc1 /]# ls /data/
test1yanqi yanqi yanqi2
[root@hub ~]# docker exec -it test2 /bin/bash
[root@d1b92fea6940 /]# ls /data/
test1yanqi yanqi yanqi2
四、Union Volume:聯合卷### --- 既不想借助宿主機的工作目錄,又想實現容器之間的目錄共享解決方案:
~~~ 意味著在使用第二個容器的時候,要去使用第一個容器的目錄檔案,
~~~ 要依賴於dockerfile中的容器子管理卷
~~~ 如果啟動容器的第一個映象沒有定義那個目錄,需要去持久化,
~~~ 需要使用到union volume的;因為它根本不知道你那個目錄去呼叫
[root@hub ~]# docker rm -f -v $( docker ps -a -q )
[root@hub ~]# cd /var/lib/docker/volumes/ // 裡面是空的,沒有任何子管理卷目錄
[root@hub volumes]# docker run --name test2 -d test:v2.0
f138101b0a89501a4634c2964a5e591730c6147d85cd0173e69dc4c6f12fd843
[root@hub volumes]# ls
1f89c1f445cc68734677d7ee758388162232340377b6b64dcc2197dfe9d39b0f // volumes下出現容器子管理卷的持久化的目錄
[root@hub volumes]# docker run --name test22 --volumes-from test2 -d test:v2.0 //--volumes-from test2 從test2容器裡去
48c0f9a0e6a7f34277623f900da41076a53e7c85a004c712eb111ac628d8020f
[root@hub volumes]# ls // 還是一個子管理卷,而我們在dockerfile中宣告建立一個子管理卷,理論上是應該建立的,而我們在建立容器的時候添加了--volumes-from test2與容器test2持久化子管理容器管理卷與之繫結
1f89c1f445cc68734677d7ee758388162232340377b6b64dcc2197dfe9d39b0f
[root@hub volumes]# docker exec -it test2 /bin/bash
[root@f138101b0a89 /]# touch /data/test2yanqi // 建立test2yanqi檔案
[root@f138101b0a89 /]# ls /data/
test2yanqi
[root@hub volumes]# docker exec -it test22 /bin/bash
[root@48c0f9a0e6a7 /]# ls /data/ // 在test22容器中也可以檢視test2yanqi檔案,
test2yanqi // 這就實現了不借助宿主機,又可以實現容器之間的目錄共享。
===============================END===============================
Walter Savage Landor:strove with none,for none was worth my strife.Nature I loved and, next to Nature, Art:I warm'd both hands before the fire of life.It sinks, and I am ready to depart ——W.S.Landor
來自為知筆記(Wiz)