Docker筆記(八):數據管理
- 2019 年 10 月 3 日
- 筆記
前面(哪個前面我也忘了)有說過,如果我們需要對數據進行持久化保存,不應使其存儲在容器中,因為容器中的數據會隨著容器的刪除而丟失,而因通過將數據存儲於宿主機文件系統的形式來持久化。在Docker容器中管理數據主要有數據卷、宿主機目錄掛載兩種方式。
1. 數據卷的方式
數據卷是一個特殊的文件目錄(或文件),具備如下特性:
-
可以在容器之間共享和重用
- 對數據卷的修改會立馬生效
- 數據卷的更新,不會影響到鏡像
- 數據卷默認會一直存在,不會隨容器的刪除而消亡
1.1 創建數據卷
可以使用docker volume create 數據卷名稱
的命令來創建一個數據卷,
[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker volume create volume1
volume1
1.2 查看數據卷
創建完後,這個數據卷具體對應宿主機哪個文件目錄在上面是沒法得知的,可以通過 docker volume inspect 數據卷名稱
來查看,
[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker volume inspect volume1 [ { "CreatedAt": "2019-08-12T19:43:47+08:00", "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/volume1/_data", "Name": "volume1", "Options": {}, "Scope": "local" } ]
可以看到數據卷volume1對應的文件目錄是“/var/lib/docker/volumes/volume1/_data”。
docker inspect xxx
這個命令挺有用的,不論是查看鏡像相關資訊(docker image inspect 鏡像名/鏡像ID
),還是查看容器相關資訊(docker container inspect 容器名/容器ID
),都可以使用,其中的image,container,volume是可以省略的,只要xxx部分不衝突就行。
可以通過docker volume ls
命令來查看所有數據卷,
[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker volume ls DRIVER VOLUME NAME local volume1
1.3 使用數據卷
可以在啟動容器時通過 -v 或 –mount 的方式將一個數據卷掛載到容器的某個目錄
[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker run -dit --name ubuntu1 -v volume1:/vol1 ubuntu:18.04 b060e793d44de2ca871da257b47598334658952943a13d1c478df5c3ae91a01c
按照 -v 數據卷名:容器目錄
的格式,也可以使用 –mount 按照 --mount source=數據卷名,target=容器目錄
的格式,如我們再啟動一個掛載相同數據卷的容器 ubuntu2,
[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker run -dit --name ubuntu2 --mount source=volume1,target=/vol2 ubuntu:18.04 b30971f8a4bbadee10774fce0b4568b5b7b1c9cde36f4bf84ac911a4cdaf6c8d
可以在數據卷所在目錄中創建一個文件來看看效果,先創建文件 hello.txt
[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# cd /var/lib/docker/volumes/volume1/_data [root@iZwz9dbodbaqxj1gxhpnjxZ _data]# touch hello.txt [root@iZwz9dbodbaqxj1gxhpnjxZ _data]# ls hello.txt
然後通過docker exec
來查看容器ubuntu1目錄/vol1,及容器ubuntu2目錄/vol2的內容
[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker exec -it ubuntu1 ls /vol1 hello.txt [root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker exec -it ubuntu2 ls /vol2 hello.txt
可以看到通過掛載目錄 /vol1, /vol2 都可以訪問到數據卷volume1對應目錄下的內容。這就像linux的軟鏈接一樣,將容器目錄鏈接到了數據卷目錄。並且上述示例也說明,同一個數據卷是可以在被多個容器共享的。
數據卷的共享也可以通過 volumes-from 容器名稱/容器ID
參數來實現,如
[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker run -dit --name ubuntu3 --volumes-from ubuntu2 ubuntu:18.04 bb5c6d61a1e6eeb18ba8c889e471b2f3215f97efca79b311eeca5968b2700df8 [root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker exec -it ubuntu3 ls /vol2 hello.txt
通過--volumes-from ubuntu2
來直接使用ubuntu2掛載的容器配置。
1.4 刪除數據卷
數據卷不會隨著容器的刪除而自動刪除。如果一個數據卷還被某個容器使用,則不能刪除;如果一個數據卷只被一個容器使用,則可在刪除容器時通過指定 -v
參數同時刪除其掛載的數據卷;
[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker rm -v ubuntu3 ubuntu3
可以通過 docker volume rm 數據卷名稱
來刪除某個數據卷;
可以通過 docker volume prune
清理掉所有未被任何容器使用的數據卷。
2. 宿主機目錄掛載方式
在容器啟動時,使用 -v 宿主機目錄:容器目錄
或 --mount type=bind,source=宿主機目錄,target=容器目錄
的參數格式指定將宿主機目錄掛載到容器目錄上。宿主機目錄必須是絕對路徑。兩者之間的區別是 -v
如果在宿主機目錄不存在時會自動創建目錄,而--mount
不會。如,
[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker run -dit --name ubuntu1 -v /root/v1:/vol1 ubuntu:18.04 25c91911709eebc9290b47b483666f7b7be840df947117f7cad323583905b9f1 [root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker run -dit --name ubuntu2 --mount type=bind,source=/root/v2,target=/vol1 ubuntu:18.04 docker: Error response from daemon: invalid mount config for type "bind": bind source path does not exist: /root/v2. See 'docker run --help'. [root@iZwz9dbodbaqxj1gxhpnjxZ ~]# mkdir /root/v2 [root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker run -dit --name ubuntu2 --mount type=bind,source=/root/v2,target=/vol1 ubuntu:18.04 5a57285e9261d048dc71cf0476055a290f80538afff2cefd2a24f8b4468b5171
/root/v1,/root/v2都沒有事先創建,用 -v
不會報錯,會自動創建; --mount
則會報錯,目錄必須先存在。docker不僅支援目錄的掛載,也支援文件的掛載,如,
[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker run --rm -it -v $HOME/.bash_history:/root/.bash_history ubuntu:18.04 bash root@3ae4ed4e687d:/# history 1 ll webapps/ 2 ll confluence/images/
通過將宿主機當前用戶的歷史操作文件掛載到容器的root用戶下的歷史操作文件,可在容器中通過history
命令查看到宿主機的操作歷史。可通過 docker inspect
來查看容器的掛載情況
[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker inspect ubuntu1 --省略了其它資訊-- "Mounts": [ { "Type": "bind", "Source": "/root/v1", "Destination": "/vol1", "Mode": "", "RW": true, "Propagation": "rprivate" } ], --省略了其它資訊--
可在“Mounts”部分看到掛載資訊。
3. 只讀控制
有時候,為了數據安全,我們不允許容器對掛載目錄的內容進行修改,即對容器來說,掛載目錄是只讀的,這可以通過在掛載參數後面加限制實現。
[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker run -dit --name ubuntu3 -v /root/v1:/vol1:ro ubuntu:18.04 25eca348ed307afcbef92bc03f0a1304b31b52e6db1fa07772b5dbd1040ff7b6 [root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker exec -it ubuntu3 bash root@25eca348ed30:/# touch /vol1/hello.txt touch: cannot touch '/vol1/hello.txt': Read-only file system
-v
是在後面加ro
(read-only),--mount
則是形如--mount type=bind,source=宿主機目錄,target=容器目錄,read only
的格式,可自行試驗。
加了read only的掛載我們再通過docker inspect
命令查看,可看到兩者之間的差異 —— Mode與RW的值。
"Mounts": [ { "Type": "bind", "Source": "/root/v1", "Destination": "/vol1", "Mode": "ro", "RW": false, "Propagation": "rprivate" } ],
4. 總結
如果要對數據進行持久化管理或在容器之間共享數據,則需要將數據通過數據卷或宿主機目錄(或文件)掛載的方式來將數據存儲於宿主機上,使得數據的生命周期獨立於容器的生命周期。這類似於我們不要把重要文件放在系統盤,而應放在其它數據盤一樣,因為系統盤會由於重裝系統或系統故障導致文件丟失。本文對Docker的數據管理進行了整理,後續對Docker的網路配置管理部分進行整理,歡迎持續關注。
相關閱讀
Docker筆記(一):什麼是Docker
Docker筆記(二):Docker管理的對象
Docker筆記(三):Docker安裝與配置
Docker筆記(四):Docker鏡像管理
Docker筆記(五):整一個自己的鏡像
Docker筆記(六):容器管理
Docker筆記(七):常用服務安裝——Nginx、MySql、Redis
本文發表於微信公眾號:“空山新雨的技術空間”
作者:空山新雨
歡迎關注,轉發,推薦,你的支援是我持續創作的動力