Docker鏡像由多個只讀層疊加而成,啓動容器時,Docker會加載只讀鏡像層並在鏡像棧頂部添加一個讀寫層。
若是運行中的容器修改了現有的一個已經存在的文件,那該文件將會從讀寫層下面的只讀層複製到讀寫層,該文件的只讀版本仍然存在,只是已經被讀寫層中該文件的副本所隱藏,這個就是寫時複製(COW)機制。docker
Docker 容器數據的存儲,存在如下問題:shell
關閉並重啓容器,容器的數據不受影響。但刪除容器會是以前的更改所有丟失。json
解決方案:卷(volume),或者便於區分叫作存儲卷。
卷是容器上的一個或多個目錄,此類目錄可繞過聯合文件系統,與宿主機上的某個目錄綁定(關聯)。數組
Volume在容器初始化之時就會建立,由base image提供的卷中的數據會於此期間完成複製。網絡
Volumn的初衷就是獨立於容器的生命週期實現數據持久化,所以刪除容器之時既不會刪除卷,也不會對哪怕未被引用的卷作垃圾回收操做。ide
卷爲docker提供了獨立於容器的數據管理機制:3d
如今,在建立容器時,加上volumes的相關選項。code
Docker有兩種類型的卷,每種類型都在容器中存在一個掛載點,可是在宿主機上的位置有所不一樣:生命週期
爲docker run命令使用-v選項,便可使用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也直接是由宿主機的文件系統決定。好處是用戶不用額外來管理這個卷,卷內存放的臨時數據會隨着容器的刪除而刪除。適合用於存放臨時性的可是須要在容器外的共享的數據。
使用的參數仍是和以前同樣,可是-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也是同樣的。
共享網絡網絡也能夠共享,即聯盟式網絡。這裏,卷也能夠共享。在有些場景下,兩個或幾個容器有可能須要共享同一個網絡而且共享同一個卷。