深入理解Docker Volume(一)
生活随笔
收集整理的這篇文章主要介紹了
深入理解Docker Volume(一)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本文講的是深入理解Docker Volume(一),【編者的話】本文主要介紹了Docker Volume的原理以及使用方式,是Docker入門教程的延伸。作者通過從數據的共享、數據容器、備份、權限以及刪除Volume五方面深入介紹了Volume的工作原理,從實戰中幫助讀者了解Volume。
從Docker IRC頻道以及stackoverflow的問題來看,很多人還不是很明白Docker Volume的工作原理。在這篇文章中,我會盡最大的努力來解釋Volume是如何工作的,并展示一些最佳實踐。這篇文章主要是針對那些對Volume不了解的Docker用戶,當然有經驗的用戶也可以通過本文了解一些Volume的細節。
想要了解Docker Volume,首先我們需要知道Docker的文件系統是如何工作的。Docker鏡像是由多個文件系統(只讀層)疊加而成。當我們啟動一個容器的時候,Docker會加載只讀鏡像層并在其上(譯者注:鏡像棧頂部)添加一個讀寫層。如果運行中的容器修改了現有的一個已經存在的文件,那該文件將會從讀寫層下面的只讀層復制到讀寫層,該文件的只讀版本仍然存在,只是已經被讀寫層中該文件的副本所隱藏。當刪除Docker容器,并通過該鏡像重新啟動時,之前的更改將會丟失。在Docker中,只讀層及在頂部的讀寫層的組合被稱為Union File System(聯合文件系統)。
為了能夠保存(持久化)數據以及共享容器間的數據,Docker提出了Volume的概念。簡單來說,Volume就是目錄或者文件,它可以繞過默認的聯合文件系統,而以正常的文件或者目錄的形式存在于宿主機上。
我們可以通過兩種方式來初始化Volume,這兩種方式有些細小而又重要的差別。我們可以在運行時使用-v來聲明Volume:
$?docker?run?-it?--name?container-test?-h?CONTAINER?-v?/data?debian?/bin/bash root@CONTAINER:/#?ls?/data root@CONTAINER:/#?
上面的命令會將/data掛載到容器中,并繞過聯合文件系統,我們可以在主機上直接操作該目錄。任何在該鏡像/data路徑的文件將會被復制到Volume。我們可以使用docker inspect命令找到Volume在主機上的存儲位置:
$?docker?inspect?-f?{{.Volumes}}?container-test
你會看到類似的輸出:
map[/data:/var/lib/docker/vfs/dir/cde167197ccc3e138a14f1a4f...b32cec92e79059437a9]?
這說明Docker把在/var/lib/docker下的某個目錄掛載到了容器內的/data目錄下。讓我們從主機上添加文件到此文件夾下:
$?sudo?touch?/var/lib/docker/vfs/dir/cde167197ccc3e13814f...b32ce9059437a9/test-file
進入我們的容器內可以看到:
$?root@CONTAINER:/#?ls?/data test-file
只要將主機的目錄掛載到容器的目錄上,那改變就會立即生效。我們可以在Dockerfile中通過使用VOLUME指令來達到相同的目的:
FROM?debian:wheezy VOLUME?/data
但還有另一件只有-v參數能夠做到而Dockerfile是做不到的事情就是在容器上掛載指定的主機目錄。例如:
$?docker?run?-v?/home/adrian/data:/data?debian?ls?/data
該命令將掛載主機的/home/adrian/data目錄到容器內的/data目錄上。任何在/home/adrian/data目錄的文件都將會出現在容器內。這對于在主機和容器之間共享文件是非常有幫助的,例如掛載需要編譯的源代碼。為了保證可移植性(并不是所有的系統的主機目錄都是可以用的),掛載主機目錄不需要從Dockerfile指定。當使用-v參數時,鏡像目錄下的任何文件都不會被復制到Volume中。(譯者注:Volume會復制到鏡像目錄,鏡像不會復制到卷)
$?docker?run?-it?-h?NEWCONTAINER?--volumes-from?container-test?debian?/bin/bash root@NEWCONTAINER:/#?ls?/data test-file root@NEWCONTAINER:/#
值得注意的是不管container-test是否運行,它都會起作用。只要有容器連接Volume,它就不會被刪除。
$?docker?run?--name?dbdata?postgres?echo?"Data-only?container?for?postgres"
該命令將會創建一個已經包含在Dockerfile里定義過Volume的postgres鏡像,運行echo命令然后退出。當我們運行docker ps命令時,echo可以幫助我們識別某鏡像的用途。我們可以用-volumes-from命令來識別其它容器的Volume:
$?docker?run?-d?--volumes-from?dbdata?--name?db1?postgres
使用數據容器的兩個注意點:
$?docker?run?--rm?--volumes-from?dbdata?-v?$(pwd):/backup?debian?tar?cvf?/backup/backup.tar?/var/lib/postgresql/data
該示例應該會將Volume里所有的東西壓縮為一個tar包(官方的postgres Dockerfile在/var/lib/postgresql/data目錄下定義了一個Volume)
FROM?debian:wheezy RUN?useradd?foo VOLUME?/data RUN?touch?/data/x RUN?chown?-R?foo:foo?/data
該Docker file不能按預期那樣運行,我們本來希望touch命令在鏡像的文件系統上運行,但是實際上它是在一個臨時容器的Volume上運行。如下所示:
FROM?debian:wheezy RUN?useradd?foo RUN?mkdir?/data?&&?touch?/data/x RUN?chown?-R?foo:foo?/data VOLUME?/data
Docker可以將鏡像中Volume下的文件掛載到Volume下,并設置正確的權限。如果你指定Volume的主機目錄將不會出現這種情況。
如果你沒有通過RUN指令設置權限,那么你就需要在容器啟動時使用CMD或ENTRYPOINT指令來執行(譯者注:CMD指令用于指定一個容器啟動時要運行的命令,與RUN類似,只是RUN是鏡像在構建時要運行的命令)。
Volume只有在下列情況下才能被刪除:
即使用以上兩種命令,也只能刪除沒有容器連接的Volume。連接到用戶指定主機目錄的Volume永遠不會被docker刪除。
除非你已經很小心的,總是像這樣來運行容器,否則你將會在/var/lib/docker/vfs/dir目錄下得到一些僵尸文件和目錄,并且還不容易說出它們到底代表什么。
另外,我們可以期待不久的將來會更多的有關處理volumes的工具:
原文鏈接:Understanding Volumes in Docker(翻譯:田浩浩?審校:李穎杰)
===========================
譯者介紹
田浩浩,悉尼大學USYD碩士研究生,目前在珠海從事Android應用開發工作。業余時間專注Docker的學習與研究,希望通過DockerOne把最新最優秀的譯文貢獻給大家,與讀者一起暢游Docker的海洋。
原文發布時間為:2015-01-06 本文作者:田浩浩? 本文來自云棲社區合作伙伴DockerOne,了解相關信息可以關注DockerOne。 原文標題:深入理解Docker Volume(一)
從Docker IRC頻道以及stackoverflow的問題來看,很多人還不是很明白Docker Volume的工作原理。在這篇文章中,我會盡最大的努力來解釋Volume是如何工作的,并展示一些最佳實踐。這篇文章主要是針對那些對Volume不了解的Docker用戶,當然有經驗的用戶也可以通過本文了解一些Volume的細節。
想要了解Docker Volume,首先我們需要知道Docker的文件系統是如何工作的。Docker鏡像是由多個文件系統(只讀層)疊加而成。當我們啟動一個容器的時候,Docker會加載只讀鏡像層并在其上(譯者注:鏡像棧頂部)添加一個讀寫層。如果運行中的容器修改了現有的一個已經存在的文件,那該文件將會從讀寫層下面的只讀層復制到讀寫層,該文件的只讀版本仍然存在,只是已經被讀寫層中該文件的副本所隱藏。當刪除Docker容器,并通過該鏡像重新啟動時,之前的更改將會丟失。在Docker中,只讀層及在頂部的讀寫層的組合被稱為Union File System(聯合文件系統)。
為了能夠保存(持久化)數據以及共享容器間的數據,Docker提出了Volume的概念。簡單來說,Volume就是目錄或者文件,它可以繞過默認的聯合文件系統,而以正常的文件或者目錄的形式存在于宿主機上。
我們可以通過兩種方式來初始化Volume,這兩種方式有些細小而又重要的差別。我們可以在運行時使用-v來聲明Volume:
$?docker?run?-it?--name?container-test?-h?CONTAINER?-v?/data?debian?/bin/bash root@CONTAINER:/#?ls?/data root@CONTAINER:/#?
上面的命令會將/data掛載到容器中,并繞過聯合文件系統,我們可以在主機上直接操作該目錄。任何在該鏡像/data路徑的文件將會被復制到Volume。我們可以使用docker inspect命令找到Volume在主機上的存儲位置:
$?docker?inspect?-f?{{.Volumes}}?container-test
你會看到類似的輸出:
map[/data:/var/lib/docker/vfs/dir/cde167197ccc3e138a14f1a4f...b32cec92e79059437a9]?
這說明Docker把在/var/lib/docker下的某個目錄掛載到了容器內的/data目錄下。讓我們從主機上添加文件到此文件夾下:
$?sudo?touch?/var/lib/docker/vfs/dir/cde167197ccc3e13814f...b32ce9059437a9/test-file
進入我們的容器內可以看到:
$?root@CONTAINER:/#?ls?/data test-file
只要將主機的目錄掛載到容器的目錄上,那改變就會立即生效。我們可以在Dockerfile中通過使用VOLUME指令來達到相同的目的:
FROM?debian:wheezy VOLUME?/data
但還有另一件只有-v參數能夠做到而Dockerfile是做不到的事情就是在容器上掛載指定的主機目錄。例如:
$?docker?run?-v?/home/adrian/data:/data?debian?ls?/data
該命令將掛載主機的/home/adrian/data目錄到容器內的/data目錄上。任何在/home/adrian/data目錄的文件都將會出現在容器內。這對于在主機和容器之間共享文件是非常有幫助的,例如掛載需要編譯的源代碼。為了保證可移植性(并不是所有的系統的主機目錄都是可以用的),掛載主機目錄不需要從Dockerfile指定。當使用-v參數時,鏡像目錄下的任何文件都不會被復制到Volume中。(譯者注:Volume會復制到鏡像目錄,鏡像不會復制到卷)
數據共享
如果要授權一個容器訪問另一個容器的Volume,我們可以使用-volumes-from參數來執行docker run。$?docker?run?-it?-h?NEWCONTAINER?--volumes-from?container-test?debian?/bin/bash root@NEWCONTAINER:/#?ls?/data test-file root@NEWCONTAINER:/#
值得注意的是不管container-test是否運行,它都會起作用。只要有容器連接Volume,它就不會被刪除。
數據容器
常見的使用場景是使用純數據容器來持久化數據庫、配置文件或者數據文件等。官方的文檔上有詳細的解釋。例如:$?docker?run?--name?dbdata?postgres?echo?"Data-only?container?for?postgres"
該命令將會創建一個已經包含在Dockerfile里定義過Volume的postgres鏡像,運行echo命令然后退出。當我們運行docker ps命令時,echo可以幫助我們識別某鏡像的用途。我們可以用-volumes-from命令來識別其它容器的Volume:
$?docker?run?-d?--volumes-from?dbdata?--name?db1?postgres
使用數據容器的兩個注意點:
- 不要運行數據容器,這純粹是在浪費資源。
- 不要為了數據容器而使用“最小的鏡像”,如busybox或scratch,只使用數據庫鏡像本身就可以了。你已經擁有該鏡像,所以并不需要占用額外的空間。
備份
如果你在用數據容器,那做備份是相當容易的:$?docker?run?--rm?--volumes-from?dbdata?-v?$(pwd):/backup?debian?tar?cvf?/backup/backup.tar?/var/lib/postgresql/data
該示例應該會將Volume里所有的東西壓縮為一個tar包(官方的postgres Dockerfile在/var/lib/postgresql/data目錄下定義了一個Volume)
權限與許可
通常你需要設置Volume的權限或者為Volume初始化一些默認數據或者配置文件。要注意的關鍵點是,在Dockerfile的VOLUME指令后的任何東西都不能改變該Volume,比如:FROM?debian:wheezy RUN?useradd?foo VOLUME?/data RUN?touch?/data/x RUN?chown?-R?foo:foo?/data
該Docker file不能按預期那樣運行,我們本來希望touch命令在鏡像的文件系統上運行,但是實際上它是在一個臨時容器的Volume上運行。如下所示:
FROM?debian:wheezy RUN?useradd?foo RUN?mkdir?/data?&&?touch?/data/x RUN?chown?-R?foo:foo?/data VOLUME?/data
Docker可以將鏡像中Volume下的文件掛載到Volume下,并設置正確的權限。如果你指定Volume的主機目錄將不會出現這種情況。
如果你沒有通過RUN指令設置權限,那么你就需要在容器啟動時使用CMD或ENTRYPOINT指令來執行(譯者注:CMD指令用于指定一個容器啟動時要運行的命令,與RUN類似,只是RUN是鏡像在構建時要運行的命令)。
刪除Volumes
這個功能可能會更加重要,如果你已經使用docker rm來刪除你的容器,那可能有很多的孤立的Volume仍在占用著空間。Volume只有在下列情況下才能被刪除:
- 該容器是用docker rm -v命令來刪除的(-v是必不可少的)。
- docker run中使用了--rm參數
即使用以上兩種命令,也只能刪除沒有容器連接的Volume。連接到用戶指定主機目錄的Volume永遠不會被docker刪除。
除非你已經很小心的,總是像這樣來運行容器,否則你將會在/var/lib/docker/vfs/dir目錄下得到一些僵尸文件和目錄,并且還不容易說出它們到底代表什么。
延伸閱讀
以下資源更深入的探究了Volumes機制(譯注:以下譯文稍后奉上):- 瘋狂Docker之純數據容器
- 深入Docker:Volumes(已譯)
- 容器數據管理
另外,我們可以期待不久的將來會更多的有關處理volumes的工具:
- Docker提議 #8484
原文鏈接:Understanding Volumes in Docker(翻譯:田浩浩?審校:李穎杰)
===========================
譯者介紹
田浩浩,悉尼大學USYD碩士研究生,目前在珠海從事Android應用開發工作。業余時間專注Docker的學習與研究,希望通過DockerOne把最新最優秀的譯文貢獻給大家,與讀者一起暢游Docker的海洋。
原文發布時間為:2015-01-06 本文作者:田浩浩? 本文來自云棲社區合作伙伴DockerOne,了解相關信息可以關注DockerOne。 原文標題:深入理解Docker Volume(一)
總結
以上是生活随笔為你收集整理的深入理解Docker Volume(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 通过Maven构建打包Spring bo
- 下一篇: 大数据是如何助德国队打进欧洲杯半决赛的?