詳解Docker中Image、Container與 Volume 的遷移


做者:匿蟒
原文:https://note.qidong.name/2018...docker

已經部署的容器化服務,也不是不須要維護的。並且,因爲生產環境每每有這樣那樣的嚴格要求,每每須要些很是規操做。Image(鏡像)、Container(容器)和Volume(數據卷)的遷移,就是一類有用的很是規操做。 微信

如下鏡像,均以最簡單的Alpine爲例。網絡

Image

鏡像的遷移,適用於離線環境。app

通常離線環境,都會自建Docker Registry。不管官方的,仍是最近流行的Harbor,都是不錯的選擇。可是,這個世界上就是有些環境,或者說一些環境在某些時期,沒有外網,也沒有內部的Registry。這個時候要部署Docker的服務,怎麼辦?ssh

只能經過鏡像的遷移。實際上,Harbor的offline installer,就是採用這種形式。spa

Save

# use stdout
docker save alpine > /tmp/alpine.tar
# or write to a file directly
docker save alpine -o /tmp/alpine.tar

推薦使用-o的形式,由於利用stdout的作法雖然直觀,但在某些場景下無效,好比利用ssh遠程執行命令。插件

Load

# use stdout
docker load < /tmp/wekan.tar
# or read from a file directly
docker load -i /tmp/wekan.tar

Container

容器的遷移,適用於已經上線,且狀態複雜、從零開始啓動不能正常工做的服務。容器遷移的包,包含了鏡像。3d

Export

先準備一個正在運行的服務,而且弄髒環境。rest

$ docker run --rm -d --name test alpine tail -f /dev/null
9232f0c1dafe0f29918f281ca37bb41914677e818cb6f252abf3dab3be04fbb2
$ docker exec test touch proof
$ docker exec test ls -hl proof
-rw-r--r-- 1 root root 0 Nov 20 14:33 proof
#執行導出操做:docker export test -o test.tar

Import

首先,關閉剛纔運行的服務。code

$ docker kill test
test

#執行導入操做:
$ docker import test.tar test-img
sha256:e03727eeba7e16dd3acfcc7536f1244762508f9b6b9856e49cc837c1b7ffa444

要注意的是,import後獲得的是一個鏡像,至關因而執行了docker commit後的內容。固然,docker commit不是一個推薦的操做,因此容器的導入、導出,就顯得不是那麼的順眼。

最後,檢查以前建立的文件。

$ docker run --rm -d --name test test-img tail -f /dev/null
ee29cb63bb2d3ed8ac890789ba80c4fe4078b9d5343a8952b6217d64b4dcbe23

$ docker exec test ls -hl proof
-rw-r--r-- 1 root root 0 Nov 20 14:33 proof

能夠看到,前面建立的文件是存在的,而且時間戳徹底一致。

Volume

數據卷的遷移,比較麻煩。Docker並未提供官方的簡單方案。

固然,直接用root用戶訪問文件系統的Docker數據,好比默認的/var/lib/docker/volumes/下的文件夾,直接進行打包操做,也不是不行。但這毫無疑問是最糟糕的方案。

目前參考《Use volumes | Docker Documentation》,找到的最佳方案是,用另外一個容器,把數據卷內容打包,而且經過掛載的形式傳遞到宿主機。

Backup

首先,準備一個Volume。

$ docker run --rm -d --name test -v test-vol:/data test-img tail -f /dev/null
f4ff81f4c31025ff476fbebc2c779a915b43ba5940b5bcc42e3ef9b1379eaeab

$ docker exec test touch /data/proof
$ docker exec test ls -hl proof
-rw-r--r-- 1 root root 0 Nov 20 14:40 proof

執行備份操做:

$ docker run --rm -v test-vol:/volume -v 
$PWD:/backup alpine tar cvf /backup/backup.tar volume
volume/
volume/proof

直接在已運行容器中打包,而後經過docker cp複製出來,也是一個方案。但這會對正在運行的容器有影響,不建議在真正重要的容器中使用。

這裏利用了一個Alpine鏡像來執行操做。實際上,任何一個自帶tar的鏡像都是能夠的。

Restore

首先,清理剛纔的容器和數據卷。

$ docker kill testtest
$ docker volume rm test-voltest-vol

執行還原操做:

docker run --rm -v test-vol:/volume -v 
$PWD:/backup alpine tar xf /backup/backup.tar

最後,檢查還原後的結果。

$ docker run --rm -v test-vol:/data alpine ls -ahl /data
total 8
drwxr-xr-x 2 root root 4.0K Nov 20 14:48 .
drwxr-xr-x 1 root root 4.0K Nov 20 14:50 ..
-rw-r--r-- 1 root root 0 Nov 20 14:40 proof

結論

以上三招六式,其實都不是常規手段。

Image的傳遞,更應該依賴於內部Docker Registry而非tar。(固然,也有例外,好比集羣部署大鏡像的P2P方案,也許能夠借鑑這個手段。)

Container的狀態,應該是可棄的。一個運行了很長時間的Container,應該是能夠restart、甚至kill後再從新run也不影響既有功能的。任何有依賴的狀態,都應該考慮持久化、網絡化,而不能單純地保存在本地文件系統中。

Volume的手動遷移,的確能夠採用上述方式。可是,Volume須要手動遷移、備份嗎?這須要專業而完善的插件來實現。

若有錯誤之處,敬請指正,也歡迎點贊、轉發支持,更多幹貨文章請關注民工哥微信公衆號,咱們一同成長。

相關文章
相關標籤/搜索