想要了解Docker Volume,首先我們需要知道Docker的文件系統是如何工作的.Docker鏡像是由多個文件系統(只讀層)疊加而成.當我們啟動一個容器的時候,Docker會加載鏡像層並在其上添加一個讀寫層.如果運行中的容器修改了現有的一個已存在的文件,那該文件將會從讀寫層下的只讀層復制到讀寫層,該文件的只讀版本仍然存在,只是已經被讀寫層中該文件的副本所隱藏.當刪除Docker容器,並通過該鏡像重新啟動時,之前的更改將會丟失.在Docker中,只讀層以及在頂部的讀寫層的組合被稱為Union FIle System(聯合文件系統).
為了能夠保存(持久化)數據以及共享容器間的數據,Docker提出了Volume的概念.簡單來說,Volume就是目錄或者文件,它可以繞過默認的聯合文件系統,而以正常的文件或者目錄的形式存在於宿主機上.
我們可以通過兩種方式來初始化Volume,這兩種方式有些細小而又重要的差別.我們可以在運行時使用-v來聲明Volume:
root@syx-VB:/home/syx# docker run -it --name container-test -h CONTAINER -v /data ubuntu /bin/bash root@CONTAINER:/# ls /data/ root@CONTAINER:/#
上面的命令會將/data掛載到容器中,並繞過聯合文件系統,我們可以在主機上直接操作該目錄.任何在該鏡像/data路徑的文件的文件都會被復制到Volume.我們可以使用docker inspect命令找到Volume在主機上的存儲位置:
$docker inspect container-test "Mounts": [ { "Name": "6407cbb6700a4076cdeeef60629f1748ff34310102480a3f702fd3fee9e69134", "Source": "/var/lib/docker/volumes/6407cbb6700a4076cdeeef60629f1748ff34310102480a3f702fd3fee9e69134/_data", "Destination": "/data", "Driver": "local", "Mode": "", "RW": true } ],
這說明Docker把在/var/lib/docker下的某個目錄掛載到了容器內的/data目錄下.讓我們從主機添加文件都此文件夾下:
root@syx-VB:~# touch /var/lib/docker/volumes/6407cbb6700a4076cdeeef60629f1748ff34310102480a3f702fd3fee9e69134/_data/test-file
進入容器
root@syx-VB:~# docker attach container-test root@CONTAINER:/# ls /data/ test-file
只要將主機的目錄掛載到容器的目錄上,那改變就會立即生效.我們可以在Dockerfile中通過使用VOLUME指令來達到相同的目的:
- FROM ubunut VOLUME /data
但是還有另一件只有-v參數能夠做到而Dockerfile是做不到的事情就是在容器上掛載指定的主機目錄.例如:
root@syx-VB:~# docker run -v /home/syx/dockerfile:/data ubuntu ls /data
df_test1
該命令將掛載主機的/home/syx/dockerfile目錄到容器內的/data目錄上.任何在/home/syx/dockerfile目錄下的文件都會出現在容器內.這對於在主機和容器之間共享文件是非常有用的,例如掛載需要編譯的源代碼.為了保證可移植性,掛載主機目錄不需要從Dockerfile指定.當使用-v參數時,鏡像目錄下的任何文件都不會被復制到Volume中.
數據共享
如果要授權一個容器訪問另一個容器的Volume,我們可以使用-volumes-from參數來執行docker run
root@syx-VB:~# docker run -it -h NEWCONTAINER --volumes-from container-test ubuntu /bin/bash root@NEWCONTAINER:/# ls /data/ test-file
值得注意的是,就算你這個時候把container-test停止了,它仍然會起作用.只要有容器連接Volume,他就不會被刪除,如果這個時候你執行:
root@syx-VB:~# docker rm container-test Error response from daemon: Conflict, You cannot remove a running container. Stop the container before attempting removal or use -f Error: failed to remove containers: [container-test]
數據容器
常見的使用場景是使用純數據容器來持久化數據庫,配置文件或者數據文件等.例如:
- $docker run --name dbdate postgres echo “Data-Only container for postgres”
該命令將會創建一個已經包含在Dockerfile里定義過Volume的postgres鏡像,運行echo命令然后退出.當我們運行docker ps命令時,echo可以幫助我們識別某鏡像的用途.我們可以用-volume-from命令來識別其他容器的Volume:
- $docker run -d --volumes-from dadate --name db1 postgres
使用數據容器的兩個注意點:
1.不要運行數據容器,這純屬是在兩非自願
2.不要為了數據容器而使用”最小的鏡像”,如busybox或scratch,只使用數據庫鏡像本身就可以了.你已經擁有了該鏡像,所以不需要占用額外的空間.
備份
如果你在用數據容器,那做備份是相當容易的.
- root@syx-VB:~# docker run --rm --volumes-from dbdate -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /var/lib/postgresql/data
該命令會將Volume里所有的東西壓縮為一個tar包(官方的postgres Dockerfile在/var/lib/postgresql/data目錄下定義了一個Volume).
- root@syx-VB:~# ls
- backup.tar
刪除Volumes
這個功能太重要了,如果你已經使用docker run來刪除你的容器,那可能會有很多孤立的Volume仍在占用着空間.
Voulume可以被刪除的條件:
1.該容器可以用docker rm -v來刪除且沒有其他容器連接到該Volume(以及主機目錄是也沒被指定為Volume).注意,-v是必不可少的.
2.docker run中使用rm參數.