轉自 https://www.jianshu.com/p/ef0f24fd0674
Docker的數據持久化主要有兩種方式:
- bind mount
- volume
Docker的數據持久化即是數據不隨着container的結束而結束,數據存在於host機器上——要么存在於host的某個指定目錄中(使用bind mount),要么使用docker自己管理的volume(/var/lib/docker/volumes下)。
bind mount
bind mount自docker早期便開始為人們使用了,用於將host機器的目錄mount到container中。但是bind mount在不同的宿主機系統時不可移植的,比如Windows和Linux的目錄結構是不一樣的,bind mount所指向的host目錄也不能一樣。這也是為什么bind mount不能出現在Dockerfile中的原因,因為這樣Dockerfile就不可移植了。
將host機器上當前目錄下的host-data目錄mount到container中的/container-data目錄:
docker run -it -v $(pwd)/host-dava:/container-data alpine sh
有幾點需要注意:
- host機器的目錄路徑必須為全路徑(准確的說需要以
/
或~/
開始的路徑),不然docker會將其當做volume而不是volume處理 - 如果host機器上的目錄不存在,docker會自動創建該目錄
- 如果container中的目錄不存在,docker會自動創建該目錄
- host機器目錄無論有沒文件,都會覆蓋container掛載目錄
volume
將my-volume掛載到container中的/mydata目錄:
docker run -it -v my-volume:/mydata alpine sh
然后可以查看到給my-volume的volume:
docker volume inspect my-volume [ { "CreatedAt": "2018-03-28T14:52:49Z", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/my-volume/_data", "Name": "my-volume", "Options": {}, "Scope": "local" } ]
可以看到,volume在host機器的目錄為 /var/lib/docker/volumes/my-volume/_data 。此時,如果my-volume不存在,那么docker會自動創建my-volume,然后再掛載。
也可以不指定host上的volume:
docker run -it -v /mydata alpine sh
此時docker將自動創建一個隨機名稱的volume,並將其掛載到container中的/mydata目錄。匿名volume在host機器上的目錄路徑類似於var/lib/docker/volumes/300c2264cd0acfe862507eedf156eb61c197720f69e7e9a053c87c2182b2e7d8/_data。
除了讓docker幫我們自動創建volume,我們也可以自行創建:
docker volume create my-volume-2
然后將這個已有的my-volume-2掛載到container中:
docker run -it -v my-volume-2:/mydata alpine sh
Dockerfile中的VOLUME
在Dockerfile中,我們也可以使用VOLUME指令來申明contaienr中的某個目錄需要映射到某個volume:
#Dockerfile
VOLUME /foo
Dockerfile中的VOLUME使每次運行一個新的container時,都會為其自動創建一個匿名的volume,如果需要在不同container之間共享數據,那么我們依然需要通過 docker run -it -v my-volume:/foo 的方式將/foo中數據存放於指定的my-volume中。
因此,VOLUME /foo在某些時候會產生歧義,如果不了解的話將導致問題。