在使用docker的過程中,有時(shí)候我們需要在不同的機(jī)器之間共享docker鏡像和容器。一種簡單的方式是將這些鏡像和容器打包為tar文件,然后通過網(wǎng)絡(luò)傳輸?shù)侥繕?biāo)機(jī)器,再解壓縮加載到docker中。但是,即使我們成功地將這些鏡像和容器傳輸?shù)搅四繕?biāo)機(jī)器,卻經(jīng)常會碰到這樣一個(gè)問題:無法加載鏡像或者啟動容器,提示”no space left on device”,即分區(qū)磁盤空間不足,尤其是當(dāng)使用存儲驅(qū)動overlay2時(shí)會更容易遇到這個(gè)問題。
這到底是怎么了呢?我曾經(jīng)遇到類似的問題,經(jīng)過一番排查研究,發(fā)現(xiàn)了其中的原因和解決方法:
- overlay2存儲驅(qū)動的工作原理
Docker的存儲驅(qū)動包括有AUFS、DeviceMapper和OverlayFS等幾種,其中overlay2是較為流行的一種。它以overlayFS文件系統(tǒng)為基礎(chǔ),將多個(gè)鏡像的文件系統(tǒng)疊加在一起,構(gòu)成一個(gè)聯(lián)合掛載點(diǎn),使之看起來是一個(gè)完整的文件系統(tǒng),比如下圖所示:
如圖,藍(lán)色部分為基礎(chǔ)鏡像的文件系統(tǒng),綠色部分為容器層的文件系統(tǒng),紅色部分為只讀層的文件系統(tǒng)。只讀層包含所有鏡像公共的文件系統(tǒng),容器層是每個(gè)容器的文件系統(tǒng),它為每個(gè)容器單獨(dú)創(chuàng)建一個(gè)只讀層,并在此基礎(chǔ)上添加可寫層,這樣每個(gè)容器都可以看作是一個(gè)獨(dú)立的文件系統(tǒng),互相之間互不干擾。
- 分區(qū)空間不足的原因
當(dāng)我們創(chuàng)建Docker容器時(shí), overlay2存儲驅(qū)動會在/var/lib/docker/overlay2目錄下為每個(gè)容器創(chuàng)建一個(gè)獨(dú)立的子目錄,以便存放容器的文件系統(tǒng)。這些子目錄中的文件數(shù)據(jù)全部存儲在基礎(chǔ)鏡像中,所以其大小并不影響存儲驅(qū)動的性能。但是,當(dāng)我們從一個(gè)機(jī)器把Docker鏡像和容器打包并發(fā)送到另一個(gè)機(jī)器時(shí),overlay2存儲驅(qū)動在解包這些數(shù)據(jù)時(shí),卻將其解壓縮到了/var/lib/docker目錄下,導(dǎo)致此目錄下的文件空間占用過大,而/var/lib/docker所在的分區(qū)磁盤空間也相應(yīng)地變小了,下圖以/var/lib/docker目錄為例,反映了這個(gè)問題:
在這張圖片中,/dev/vda1分區(qū)磁盤大小為50GB,/var/lib/docker分區(qū)磁盤大小為21GB,卻因?yàn)閐ocker創(chuàng)建的容器太多,導(dǎo)致/var/lib/docker目錄下的空間不足,只剩下了30.72MB.所以,當(dāng)我們想要從這樣一個(gè)磁盤空間緊缺的機(jī)器上啟動容器時(shí),就會出現(xiàn)啟動失敗的問題了。
- 相關(guān)解決方法有哪些?
針對上述問題,我提供了一些解決辦法:
3.1 擴(kuò)大分區(qū)磁盤空間
這是最常見的一種方法,對于虛擬機(jī)來說,我們可以在虛擬機(jī)管理工具中擴(kuò)大磁盤分區(qū)大小,重啟虛擬機(jī)即可。對于云服務(wù)器來說,多數(shù)云平臺提供了在線擴(kuò)容磁盤的功能,但操作過程相對復(fù)雜,需謹(jǐn)慎操作,以免出現(xiàn)數(shù)據(jù)丟失的情況。
3.2 將/var/lib/docker目錄掛載到較大的數(shù)據(jù)盤上
提前準(zhǔn)備一個(gè)大于21GB的磁盤(如20T)并格式化成ext4格式,掛在到/data目錄下,然后將/var/lib/docker目錄遷移到該數(shù)據(jù)盤中進(jìn)行存儲。具體操作指令如下:
# 制作文件系統(tǒng)格式 mkfs.ext4 /dev/vdb # 掛載 mount /dev/vdb /data # 備份原/var/lib/docker目錄下所有數(shù)據(jù) cp -au /var/lib/docker/* /data/ # 卸載/var/lib/docker目錄 umount /var/lib/docker # 將/var/lib/docker目錄遷移到新的數(shù)據(jù)盤中 echo '/dev/vdb /var/lib/docker ext4 defaults 0 0' >> /etc/fstab mount -a
3.3 刪除不再使用的Docker鏡像和容器
我們可以使用以下命令清理磁盤空間:
# 清理所有停止的容器 docker container prune # 清理所有未被標(biāo)記的鏡像 docker image prune -a # 刪除所有沒有容器使用的鏡像 docker image prune -a --filter "dangling=true"
總結(jié)
在使用Docker時(shí),我們需要時(shí)刻注意存儲驅(qū)動所使用的空間是否足夠,否則可能會導(dǎo)致啟動失敗的問題。為此,可以采取上述三種解決方法之一,我個(gè)人推薦第二種方法,可以在不破壞原有文件系統(tǒng)的情況下快速解決問題。希望我的分享能給你帶來幫助,謝謝閱讀。