使用 save / export 分享 image
不久前,曾聽到一個神奇的需求:希望在無網路的環境下使用 Docker。這種需求我還是第一次聽到。
第二階段的最後一天,來說明如何在無網路的環境下分享 Docker image 與啟動 container。
安裝 Docker
第一步就是麻煩事了,我會使用 Vagrant 包 Docker box 再到機器上匯入,接著啟動 VM 後,如果搞砸了,只要 VM 砍掉重練即可。
Vagrant 有安裝檔案,另外再配上 VirtualBox 安裝檔,即可完成虛擬機環境的準備。
再來是 Vagrant Box 準備,參考安裝 Docker 環境提到的 Vagrant 環境建置。使用 vagrant up
建好 VM 後,再使用 vagrant package
指令打包成 .box 檔:
$ vagrant package |
這個動作跟
docker commit
非常像。
到目前為止會有三份檔案如下:
- Vagrant 安裝檔
- VirtualBox 安裝檔
- Docker VM 檔(package.box)
接著放入隨身碟後,就可以移架到主機上安裝 Vagrant 與 VirtualBox 了。
匯入 box 檔
Docker VM 檔是 .box 格式,匯入 Vagrant 使用 vagrant box add
指令:
$ vagrant box add --name docker ./package.box |
完成匯入後,因 box 名稱不同,因此要換一個名字。依上面的範例,要使用 docker
這個 box 名稱:
Vagrant.configure("2") do |config| |
這裡要注意的是,forwarded_port
與之前提到的 Port forwarding 概念完全相同,只是 container 換成了 VM。以下是設定範例參考:
Image | Container port | Docker Run | Vagrantfile | Host port |
---|---|---|---|---|
httpd | 80 | 8080:80 | guest: 8080, host: 8080 | 8080 |
mysql | 3306 | 3306:3306 | guest: 3306, host: 3306 | 3306 |
registry | 5000 | 443:5000 | guest: 443, host: 1443 | 1443 |
當調整完設定後,只要下 vagrant reload
即可重載設定。
再來就是 Docker image 檔該如何產生與匯入了,Docker 提供兩種方法可以產生與匯入 tar 檔,以下簡單做說明。
docker save
與 docker load
昨天有說明如何把 Docker image push 到 registry 上。類似的原理,image 的內容是可以被打包起來的。這裡準備了一個簡單的 Dockerfile 來實驗:
FROM alpine |
# 使用上面的 Dockerfile build image |
Build image 後,使用 docker save
可以將 image 內容輸出成 tar 檔:
# 確認 image 的 SHA256 為 bcdbe56cd759 |
這裡可以看到 SHA256 完全一致,這代表 image 內容有被完整保存下來的,而且大小是很接近的:
$ ls -lh vim.tar |
Docker 有提供 docker history
指令可以查看 image layer 的資訊:
$ docker history vim |
最上面很明顯是 Vim 的,而下面兩行 missing 即為 Alpine 的 layer,可以用同樣的指令查 Alpine 會更清楚:
$ docker history alpine |
這裡再做另一個實驗,把 Vim image 與 Alpine image 都移除,再匯入 vim.tar
:
# 移除 image |
這代表匯出的 vim.tar
會完整地包含所有 FROM 的 image 資訊。
為什麼要特別確認這件事,因為下一個指令會不一樣。
docker export
與 docker import
一樣是輸出 tar 檔,但 docker export
的目標是 container,它能將 container 輸出成 tar 檔:
# 執行一個 container,注意這裡沒有 --rm |
最後的 docker import
可以發現,執行兩次的 digest 是不一樣的。這代表 docker export
產出的 tar 檔,其實是沒有包含 FROM image 資訊的。
docker history
資訊如下:
$ docker history vim |
只有一層 layer,Alpine 的檔案系統已經被包含在這裡面了。
save
v.s. export
docker save
與 docker export
的目的都一樣是把 Docker 的系統保存成檔案,但結果是不大一樣的。以下做個簡單的比較:
docker save |
docker export |
---|---|
將 image 打包 | 將 container 打包 |
完整保留 image layer 資訊 | 只會有一層 layer |
可以保存多個 image 在一個 tar 檔裡 | 只能保存一個 container 在一個 tar 檔裡 |
使用上,docker save
用途很明確是分享 image。而 docker export
比較像是想把目前運作中的 container 狀態保存下來,拿到別台機器上做別的用途,比方說 debug 等。
上面的範例是有把 container 停止才下
docker export
指令,實際上也可以用在執行中的 container。
指令補充說明
docker save
把 image 使用 tar 打包輸出。預設會使用標準輸出(STDOUT),用法:
docker save [OPTIONS] IMAGE [IMAGE...] |
因為是使用標準輸出,所以會使用導出(>
)的方法輸出檔案,也可以使用下面這個參數來取代導出:
-o|--output
不使用標準輸出,改使用輸出檔案,後面接檔案名稱即可
docker load
把打包的 tar 檔載入到 Docker repository 裡。預設會使用標準輸入(STDIN),用法:
docker image load [OPTIONS] |
類似 save,只是它是使用導入(<
)來讀取檔案內容,一樣可以使用參數來取代導入:
-i|--input
不使用標準輸入,改成直接指定檔案
docker export
把 container 的檔案系統使用 tar 打包輸出。預設會使用標準輸出(STDOUT),用法:
docker export [OPTIONS] CONTAINER |
與 docker save
類似,也有使用導出(>
)的方法輸出檔案,也有參數可以取代導出:
- -o|–output 不使用標準輸出,改使用輸出檔案,後面接檔案名稱即可
docker import
把打包的 tar 檔的檔案系統導入到 Docker repository 裡。預設會使用標準輸入(STDIN),用法:
docker image import [OPTIONS] file|URL|- [REPOSITORY[:TAG]] |
與 docker load
類似,使用導入(<
)來讀取檔案內容,但它沒有選項可以取代導入,而是改成使用參數的方法。下面是使用導入與不使用的對照範例:
docker image import myimage < my-export.tar |
今日自我回顧
基本操作 container 的方法,與 build image 的方法在這二十天裡已說明完了,這樣已可應付八成開發上遇到的問題。
明天會開始說明更詳細的部分,包括各元件的細節,或是維運相關的功能等。