Docker 存儲卷

爲什麼須要存儲卷

Docker鏡像由多個只讀層疊加而成,啓動容器時,Docker會加載只讀鏡像層並在鏡像棧頂部添加一個讀寫層。
若是運行中的容器修改了現有的一個已經存在的文件,那該文件將會從讀寫層下面的只讀層複製到讀寫層,該文件的只讀版本仍然存在,只是已經被讀寫層中該文件的副本所隱藏,這個就是寫時複製(COW)機制。docker

數據存儲的問題

Docker 容器數據的存儲,存在如下問題:shell

  • 存儲於聯合文件系統中,不易於宿主機訪問
  • 容器間數據共享不便
  • 刪除容器其數據會丟失

關閉並重啓容器,容器的數據不受影響。但刪除容器會是以前的更改所有丟失。json

解決方案:卷(volume),或者便於區分叫作存儲卷。
卷是容器上的一個或多個目錄,此類目錄可繞過聯合文件系統,與宿主機上的某個目錄綁定(關聯)。數組

Data volumes

Volume在容器初始化之時就會建立,由base image提供的卷中的數據會於此期間完成複製。網絡

Volumn的初衷就是獨立於容器的生命週期實現數據持久化,所以刪除容器之時既不會刪除卷,也不會對哪怕未被引用的卷作垃圾回收操做。ide

卷爲docker提供了獨立於容器的數據管理機制:3d

  • 能夠把鏡像想象成靜態文件,例如程序。把卷類比爲動態內容,例如數據。因而,鏡像能夠重用,而卷能夠共享
  • 卷實現了程序(鏡像)和數據(卷)的分離,以及程序(鏡像)和製做鏡像的主機的分離。用戶製做鏡像時無須再考慮鏡像運行的容器所在主機的環境。

在容器中使用volumes

如今,在建立容器時,加上volumes的相關選項。code

Volumes types

Docker有兩種類型的卷,每種類型都在容器中存在一個掛載點,可是在宿主機上的位置有所不一樣:生命週期

  • Bind-mount volume: 容器內的目錄和宿主機上的目錄都須要指定
  • Docker-managed volume: 容器內的目錄須要指定,宿主機上目錄由docker維護

爲docker run命令使用-v選項,便可使用Volume。內存

Docker-managed volume

開一個會話建立容器並綁定volume:

$ docker run --name v1 --rm -it -v /data busybox

在宿主機上操做目錄
在另外一個會話中查詢這個容器的inspect,不過內容比較多。在Volumes裏能看到卷的信息:

"Volumes": {
                "/data": {}
            },

還有掛載點的信息,這裏使用-f參數只看Mounts的內容:

$ docker inspect -f '{{json .Mounts}}' v1
[{"Type":"volume","Name":"bdd48fb729e802b7d3a067da74b748037e83ff770a84f7215c657f6cc2af2c9d","Source":"/var/lib/docker/volumes/bdd48fb729e802b7d3a067da74b748037e83ff770a84f7215c657f6cc2af2c9d/_data","Destination":"/data","Driver":"local","Mode":"","RW":true,"Propagation":""}]
$

宿主機自動分配的卷的路徑在Source字段中,下面的方法直接獲取路徑並調用ls命令:

$ docker inspect -f '{{range .Mounts}}{{.Source}} {{end}}' v1 | xargs ls
$ docker inspect -f '{{with index .Mounts 0}}{{.Source}}{{end}}' v1 | xargs ls

Mounts裏是一個數組,可能有多個掛載點。第一行的命令是遍歷全部的目錄,第二行的命令是隻輸出第一個目錄。
在掛載點的目錄中,容器和宿主機能夠共享數據。容器中對目錄的修改,在宿主機中能夠查看到。反之,在宿主機中對這個目錄的修改,容器也可以查看到。

刪除鏡像
上面建立容器的命令使用了--rm參數,這樣一旦容器中止,該容器也就會自動被刪除。容器刪除後,Docker-managed volume也會一併被刪除。
因此這是一個臨時的卷,卷內存儲的數據依然會隨着容器的刪除而丟失。沒有解決容器內數據持久保存的目的,可是如今容器的數據能夠和宿主機共享,而且數據存儲的I/O也直接是由宿主機的文件系統決定。好處是用戶不用額外來管理這個卷,卷內存放的臨時數據會隨着容器的刪除而刪除。適合用於存放臨時性的可是須要在容器外的共享的數據。

Bind-mount Volme

使用的參數仍是和以前同樣,可是-v參數的內容提供兩部分,宿主機的目錄和卷的目錄,中間用冒號分隔:-v HOSTDIR:VOLUMEDIR

綁定 Bind-mount Volme
開一個會話建立容器並綁定Bind-mount Volme:

$ docker run --name v2 --rm -it -v ~/data/volumes/v2:/data busybox

仍然可使用docker inspect命令來查看詳細信息,這裏就不演示了。
這裏指定的宿主機的路徑若是不存在,docker會自動建立。

刪除容器
容器刪除後,宿主機上的文件會依然存在。這樣就實現了數據在容器刪除後依然可使用。

共享卷

前面說了,docker有兩種類型的卷,兩種都已經說了。這裏的共享卷本質上仍是上面兩種類型中的某一種,只是是實現了容器間共享同一個卷的兩種方法。

多個容器卷使用同一個主機目錄
這個沒什麼問題,主機上同一個目錄是容許被多個容器同時使用的。

複製使用其餘容器的卷
使用--volumes-from選項:

$ docker run --name v3.0 --rm -itd -v /data busybox
e24397fffb44717a7f140010c829ec88f540ed7d95f7c8fb328a35a819becfb0
$ docker run --name v3.1 --rm -itd --volumes-from v3.0 busybox
28543eb6fc13e972a000ab955b9623630ebb9d90c8d3dc37a8b7608f24188926
$ docker container attach v3.0
/ # touch /data/test_v3_0
/ # exit
$ docker container attach v3.1
/ # ls /data
test_v3_0
/ # exit
$

這裏的示例複製的是Docker-managed volume,對於Bind-mount Volme也是同樣的。

共享網絡網絡也能夠共享,即聯盟式網絡。這裏,卷也能夠共享。在有些場景下,兩個或幾個容器有可能須要共享同一個網絡而且共享同一個卷。

相關文章
相關標籤/搜索