做者:匿蟒
原文:https://note.qidong.name/2018...docker
已經部署的容器化服務,也不是不須要維護的。並且,因爲生產環境每每有這樣那樣的嚴格要求,每每須要些很是規操做。Image(鏡像)、Container(容器)和Volume(數據卷)的遷移,就是一類有用的很是規操做。 微信
如下鏡像,均以最簡單的Alpine爲例。網絡
鏡像的遷移,適用於離線環境。app
通常離線環境,都會自建Docker Registry。不管官方的,仍是最近流行的Harbor,都是不錯的選擇。可是,這個世界上就是有些環境,或者說一些環境在某些時期,沒有外網,也沒有內部的Registry。這個時候要部署Docker的服務,怎麼辦?ssh
只能經過鏡像的遷移。實際上,Harbor的offline installer,就是採用這種形式。spa
# use stdout docker save alpine > /tmp/alpine.tar # or write to a file directly docker save alpine -o /tmp/alpine.tar
推薦使用-o
的形式,由於利用stdout的作法雖然直觀,但在某些場景下無效,好比利用ssh
遠程執行命令。插件
# use stdout docker load < /tmp/wekan.tar # or read from a file directly docker load -i /tmp/wekan.tar
容器的遷移,適用於已經上線,且狀態複雜、從零開始啓動不能正常工做的服務。容器遷移的包,包含了鏡像。3d
先準備一個正在運行的服務,而且弄髒環境。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
首先,關閉剛纔運行的服務。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
能夠看到,前面建立的文件是存在的,而且時間戳徹底一致。
數據卷的遷移,比較麻煩。Docker並未提供官方的簡單方案。
固然,直接用root
用戶訪問文件系統的Docker數據,好比默認的/var/lib/docker/volumes/
下的文件夾,直接進行打包操做,也不是不行。但這毫無疑問是最糟糕的方案。
目前參考《Use volumes | Docker Documentation》,找到的最佳方案是,用另外一個容器,把數據卷內容打包,而且經過掛載的形式傳遞到宿主機。
首先,準備一個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
的鏡像都是能夠的。
首先,清理剛纔的容器和數據卷。
$ 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須要手動遷移、備份嗎?這須要專業而完善的插件來實現。
若有錯誤之處,敬請指正,也歡迎點贊、轉發支持,更多幹貨文章請關注民工哥微信公衆號,咱們一同成長。