Docker進階:容器中的數據管理

如果你不知道Docker,或者不了解Docker的基本用法,建議先讀一下上篇文章:零基礎入門Docker。入門Docker之後,我們繼續了解Docker中比較進階性的知識:容器中的數據管理。

先思考一些場景,如果利用Docker創建了一個N個容器,這些容器之間需要數據共享,此時該怎麼辦?如果我們想在本機了解容器的運行狀態、命令歷史等,此時該怎麼辦?

按照Docker官方文檔的說明,容器中的數據管理有兩種形式:Manage data in containers

數據卷(Data Volumes)

可以將「數據卷」理解為容器中的一個目錄,類似於Linux中mount的概念。創建容器時,可以一併創建數據卷,並且能夠掛載一個主機目錄為數據卷。有點繞口,實例說明一下。

(1)創建mysql容器,不添加任何關於數據卷的參數:

# 這裡假設我們已經pull下mysql鏡像n[root@xx ~]# docker run -d -p 3306:3306 --name mysql01 -e MYSQL_ROOT_PASSWORD=123456 mysql # 創建一個名字為mysql01的容器n

此時並沒有指定關於任何數據卷的參數。-p 3306:3306是將本機的3306埠映射到容器的3306埠。此時利用命令查看容器的基本信息,其中一段為:

[root@xx ~]# docker inspect mysql01n......n"Mounts": [n {n "Name": "6cb3597e2da5......",n "Source": "/var/lib/docker/volumes/6cb3597e2da5....../_data",n "Destination": "/var/lib/mysql",n "Driver": "local",n "Mode": "",n "RW": true,n "Propagation": ""n }n],n......n

這段數據說明該容器自動生成一個數據卷,在容器中的目錄為"/var/lib/mysql",用於存放Mysql數據,同時在本機也有相對應的目錄:"/var/lib/docker/volumes/....../_data"。當你在Mysql中創建資料庫、表時,就會在本機目錄下生成相應的數據。

(2)創建mysql容器,並添加自定義的數據卷:

# 這裡假設我們已經pull下mysql鏡像n[root@xx ~]# docker run -d -p 3307:3306 --name mysql02 -e MYSQL_ROOT_PASSWORD=123456 -v /appdata mysql # 創建一個名字為mysql02的容器n

此時指定了一個-v /appdata的參數,用於在容器中創建一個目錄為/appdata的數據卷。注意-p選項變為了-p 3307:3306,這是因為上一次的容器將本機的3306埠佔用了,需要選擇另外一個埠。此時利用inspect命令查看容器基本信息,其中一段為:

[root@xx ~]# docker inspect mysql02n"Mounts": [n {n "Name": "d95fd2d33.......",n "Source": "/var/lib/docker/volumes/d95fd2d33....../_data",n "Destination": "/appdata",n ........n },n {n "Name": "695e371973......",n "Source": "/var/lib/docker/volumes/695e371973....../_data",n "Destination": "/var/lib/mysql",n ........n }n],n

這個容器中有兩個數據卷,一個是Mysql自建的"/var/lib/mysql",用於存放mysql數據。另外一個是我們自己指定的"/appdata",類似於前者,這個數據卷在本機也有相對應的目錄。這裡的"appdata"數據卷並沒有什麼用,只是作為例子說明一下。

(3)創建mysql容器,並掛載本機目錄作為數據卷

# 這裡假設我們已經pull下mysql鏡像n[root@xx ~]# docker run -d -p 3308:3306 --name mysql03 -e MYSQL_ROOT_PASSWORD=123456 -v /root/mysqldata/:/var/lib/mysql mysqln

此時的-v參數將本機的"/root/mysqldata"目錄掛載到"/var/lib/mysql"。此時查看容器的基本信息,其中一段為:

[root@xx ~]# docker inspect mysql03n"Mounts": [n {n "Source": "/root/mysqldata",n "Destination": "/var/lib/mysql",n "Mode": "",n "RW": true,n "Propagation": "rprivate"n }n],n

這裡只有一個數據卷,應該比較容易理解。注意這裡的"Propagation"參數,官方的解釋為:

By default bind mounted volumes are private. That means any mounts done inside container will not be visible on host and vice-a-versa. One can change this behavior by specifying a volume mount propagation property. Making a volume shared mounts done under that volume inside container will be visible on host and vice-a-versa. Making a volume slave enables only one way mount propagation and that is mounts done on host under that volume will be visible inside container but not the other way around.nTo control mount propagation property of volume one can use :[r]shared, :[r]slave or :[r]private propagation flag. Propagation property can be specified only for bind mounted volumes and not for internal volumes or named volumes. For mount propagation to work source mount point (mount point where source dir is mounted on) has to have right propagation properties. For shared volumes, source mount point has to be shared. And for slave volumes, source mount has to be either shared or slave.n

(4)創建容器,並掛載本機文件作為數據卷。

除了能掛載本機的目錄外,同樣可以掛載本機文件。官網上給出的例子是:

$ docker run --rm -it -v ~/.bash_history:/root/.bash_history ubuntu /bin/bashn

這裡將本機的.bash_history文件掛載到容器的.bash_history文件上。根據數據卷的特性,這樣在本機就能看到容器中的操作歷史了。

(5)刪除數據卷。數據卷是被用來持久化數據的,它獨立於容器存在。當我們刪除容器時,並不會自動刪除數據卷,同時Docker也沒有垃圾回收機制可以回收無用的數據卷。但是我們可以在刪除容器時,連同數據卷一併刪除,比如:docker rm -v mysql02。

數據卷容器(Data Volumes Container)

如果你有一些需要持續更新,並且需要在容器之間共享的數據,建議創建數據卷容器。數據卷容器其實就是一個容器,專門用來提供數據卷供其他容器掛載。

(1)首先建立一個數據卷容器,用於存放數據。

[root@xx ~]# docker run -d -p 3306:3306 --name store -v /data/ -e MYSQL_ROOT_PASSWORD=123456 mysqln

(2)接著你就能使用--volumes-from選項在其他容器中掛載/data/目錄。

[root@xx ~]# docker run -d -p 3307:3306 --name u1 --volumes-from store -e MYSQL_ROOT_PASSWORD=123456 mysqln[root@xx ~]# docker run -d -p 3308:3306 --name u2 --volumes-from store -e MYSQL_ROOT_PASSWORD=123456 mysqln

此時容器u1和u2中都有/data/目錄,並且和容器store中的該目錄共用。即當我們在容器u1中新建、更改、刪除文件時,容器u2同樣能得到對應的操作。

注意,這裡的數據卷容器store並不需要一直處於運行的狀態。

(3)刪除數據卷容器。這裡刪除容器u1、u2或store都不會刪除數據卷,需要在刪除最後一個容器時使用-v選項來刪除數據卷。這裡建議刪除每一個時都帶有-v選項。

[root@xx ~]# docker rm -v u1n[root@xx ~]# docker rm -v u2n[root@xx ~]# docker rm -v storen

數據卷的備份、恢復和遷移

比較簡單,直接查看官方文檔即可。地址:Manage data in containers

數據拷貝

在容器和主機之間,可以利用命令docker cp進行數據拷貝。

[root@xx ~]# docker cp CONTAINER:SRC_PATH DEST_PATHn[root@xx ~]# docker cp SRC_PATH CONTAINER:DEST_PATHn

數據拷貝和數據卷之間的區別在於:數據卷掛載後,數據卷中的數據實際上是存放在主機上的,相當於建立了一個軟連接。而數據拷貝之後,容器中是存在數據的,當把容器commit成一個鏡像時,鏡像中也是存在該數據的。

=============================================================

作者主頁:笑虎(Python愛好者,關注爬蟲、數據分析、數據挖掘、數據可視化等)

作者專欄主頁:擼代碼,學知識 - 知乎專欄

作者GitHub主頁:擼代碼,學知識 - GitHub

歡迎大家拍磚、提意見。相互交流,共同進步!

==============================================================


推薦閱讀:

Docker的一個簡單示例
基於Docker、NodeJs實現高可用的服務發現
Docker從入門到部署-初識Docker
如何使用OpenDroneMap對航拍圖像快速建模

TAG:Docker | 虚拟化 | 编程 |