前言
上一篇文章中簡單總結了一下docke的基礎使用方法,這次我來總結一下有關docker存儲方面的相關知識。本文同樣建立在CloudMan的系列教程之上,有興趣的可以直接移步。
有些人可能覺得這個很簡單,存儲就是硬盤嘛,docker容器既然也是操作系統,那就直接存在他的容器的文件系統里就好了。看似沒錯,但問題在於docker的容器是無狀態的,當容器重啟的時候里面的數據會全部清除,如果是一些靜態的數據,我們可以在build鏡像的時候直接寫死,但是對於數據庫、日志等數據實時變化的鏡像我們就不能通過這種方式來保存數據。所以本文來談談不同的存儲方式。
一、Docker的兩種存儲資源
根據上述分析可以知道,Docker為容器起碼提供了兩種存放數據的資源,確實如此,分別是:
- 由storage driver管理的鏡像層和容器層,即鏡像內文件系統。
- Data Volume,宿主機文件系統。
1.1 storage driver
對於某些容器,直接將數據放在由storage driver維護的層中是很好的選擇,比如那些無狀態的應用。無狀態意味着容器沒有需要持久化的數據,隨時可以從鏡像直接創建。比如busybox,它是一個工具箱,我們啟動busybox是為了執行諸如wget,ping之類的命令,不需要保存數據供以后使用,使用完直接退出,容器刪除時存放在容器層中的工作數據也一起被刪除,下次再啟動新容器時又是一個干凈如初的內部文件系統。
通過上一篇文章可以知道使用Dockerfile build鏡像的時候,可以通過COPY或ADD命令來向鏡像中添加數據。如下:
COPY將文件從宿主機復制到鏡像。
COPY支持兩種形式:
COPY src destCOPY ["src", "dest"]
注意:src只能指定宿主機中的文件或目錄。
ADD與COPY類似,從宿主機復制文件到鏡像。不同的是,如果src是歸檔文件(tar,zip,tgz,xz等),文件會被自動解壓到dest。
1.2 data vloume
有些容器需要保存狀態,如數據庫容器等,這些就需要使用Data Volume,即將內部數據映射到外部宿主機的文件系統上。
Data Volume 有以下特點:
- Data Volume是目錄或文件,而非沒有格式化的磁盤(塊設備)。
- 容器可以讀寫volume中的數據。
- volume數據可以被永久的保存,即使使用它的容器已經銷毀。
1.2.1 bind mount
bind mount的意思是掛載宿主機中固定目錄,啟動容器的時候執行:
docker run -d -p 80:80 -v src:dst httpd
-v的格式為
1.2.2 docker managed volume
docker managed volume的意思是由docker自動映射目錄。啟動容器的時候執行:
docker run -d -p 80:80 -v dst httpd
此處-v的格式為
它與bind mount的區別在於,managed volume不需要指定宿主機上的mount目錄,docker會自動在宿主機/var/lib/docker/volumes下為其生成一個隨機目錄。
docker managed volume的創建過程:
- 容器啟動時,簡單的告訴docker:我需要一個volume存放數據,幫我mount到目錄/abc(鏡像內目錄)。
- docker在宿主機/var/lib/docker/volumes中生成一個隨機目錄作為mount源。
- 如果/abc已經存在,則將數據復制到 mount源。
- 將volume(宿主機)mount到/abc(鏡像)。
1.2.3 兩種方式對比
| 類型 | bind mount | docker managed volume |
|---|---|---|
| volume 位置 | 可任意指定 | /var/lib/docker/volumes/... |
| 對已有mount point 影響 | 隱藏並替換為 volume | 原有數據復制到 volume |
| 是否支持單個文件 | 支持 | 不支持,只能是目錄 |
| 權限控制 | 可設置為只讀,默認為讀寫權限 | 無控制,均為讀寫權限 |
| 移植性 | 移植性弱,與host path綁定 | 移植性強,無需指定host目錄 |
二、容器與宿主機之間以及容器之間數據共享
由於docker的設計目的就是為了互相不干擾,相互獨立,但是有時候我們又不得不在容器與宿主機之間或者容器之間共享數據,以實現某些功能。
2.1 容器與host共享數據
-
使用docker cp命令可以在容器和host之間拷貝數據,與scp相似。
-
將鏡像的某一目錄掛載到host path也是一種共享方式。
2.2 容器之間共享數據
2.2.1 共享host目錄
只需要將同一個host目錄掛載到不同的容器即可。
2.2.2 用volume container共享數據
volume container是專門為其他容器提供volume的容器。它提供的卷的類型可以是bind mount,也可以是docker managed volume。通過下面的命令創建一個volume container:
docker create --name vc_data -v ~/htdocs:/usr/local/apache2/htdocs -v /other/useful/tools busybox
此處只需要create即可,不需要run,因為其他容器只需獲取到他的這個掛載點,並不需要他的數據。
其他容器啟動的時候可以通過--volumes-from參數使用vc_data這個volume container容器的掛載點,命令如下:
docker run --name web1 -d -p 80 --volumes-from vc_data httpd
docker run --name web2 -d -p 80 --volumes-from vc_data httpd
這樣web1、web2就有了相同的掛載點。
volume container 的特點:
- 與 bind mount 相比,不必為每一個容器指定host path,所有path都在 volume container中定義好了,容器只需與volume container關聯。實現了容器與host的解耦。
- 使用volume container的容器其mount point是一致的,有利於配置的規范和標准化,但也帶來一定的局限,使用時需要綜合考慮。
2.2.3 data-packed volume container
這種場景是將數據先放到鏡像中,build此鏡像,然后create此鏡像,其他容器的--volumes-from設置為此容器。這樣run出來的容器都會共享同一份數據。
我們用下面的 Dockfile 構建鏡像:
FROM busybox
ADD htdocs /usr/local/apache2/htdocs
VOLUME /usr/local/apache2/htdocs
ADD命令將靜態文件添加到容器目錄/usr/local/apache2/htdocs。
VOLUME 的作用與-v等效,用來創建docker managed volume,mount point 為usr/local/apache2/htdocs,因為這個目錄就是ADD添加的目錄,所以會將已有數據拷貝到volume中。用下面的命令build詞鏡像:
docker build -t datapacked .
創建此鏡像的容器:
docker create --name vc_data datapacked
此處不再需要-v,因為datapacked的鏡像VLOUME已經實現了。
啟動其他容器:
docker run --name web2 -d -p 80 --volumes-from vc_data httpd
這樣也可實現容器之間共享數據,而且此數據保存在datapacked中。這種方式適合只使用靜態文件共享場景。並且datapacked中包含了共享數據,可移植性非常強。
三、volume管理
docker volume ls查看宿主機上所有vloume
docker inspect <container>查看某一容器具體的信息
dcoker vloume rm <iamgeid>刪除某一個volume
如果想批量刪除孤兒 volume,可以執行:
docker volume rm $(docker volume ls -q)
四、總結
本文簡單總結了docker存儲方面的相關知識和用法,包含兩種數據存儲方式、容器與host之間、容器之間共享數據以及volume管理等知識。下一篇總結以下docker網絡的相關知識和用法。
