基于已有容器構建自己的 Docker 鏡像
通過前面的介紹,我們知道了Docker 鏡像是多個基于 UnionFS 的鏡像層依次掛載的結果,而容器的文件系統則是在以只讀方式掛載鏡像后增加的一個可讀可寫的文件系統復合而成。
Docker 中為我們提供了將容器中的這個可讀可寫的環境持久化為一個鏡像層的方法,即docker commit
。 docker commit
將容器修改的內容保存為鏡像,我們可以把它理解為提交容器的更改。
1.生成變更后的鏡像
我們以上一節的 busybox 為例:
# 重新創建一個busybox容器
docker run --name busybox -d -i busybox
# 進入容器
docker exec -it busybox sh
# 做些更改,新建個文件
echo 'something' > something
# 查看變更后的目錄和文件
ls
exit
退出容器后,使用docker commit
進行提交變更
[root@centos8 ~]# docker commit -m 'something' busybox
sha256:19da0182bca9305944f6a66b1331ff7394a915bc8982cf520660a883484699fc
-m
參數進行提交的注釋,用法類似 git。
執行 docker commit
將容器記錄成鏡像層的時候,會先暫停容器的運行,以保證容器內的文件系統處于一個相對穩定的狀態,確保數據的一致性。提交鏡像更新后,docker images
從本地鏡像列表中找到它。
2. 為鏡像命名
在上面的例子里,我們發現提交容器更新后產生的鏡像并沒有 REPOSITORY 和 TAG 的內容,也就是說,這個新的鏡像還沒有名字。 Docker 為我們提供了一個為鏡像取名的命令,也就是 docker tag
命令。
docker tag 19da0182bca9 mybusybox:1.0
使用 docker tag
也能夠對已有的鏡像創建一個新的別名副本(舊的鏡像與名稱也會保留)。
docker tag mybusybox:1.0 mybusybox:latest
當然,我們可以在提交變更的時候同時命名鏡像
docker commit -m 'something' busybox mybusybox2:latest
3. 遷移鏡像
在我們將更新導出為鏡像后,我們還可以開始遷移鏡像。
由于 Docker 是以集中的方式管理鏡像的,所以在遷移之前,我們要先從 Docker 中取出鏡像。docker save
命令可以將鏡像輸出,提供了一種讓我們保存鏡像到 Docker 外部的方式。
# 將 something:latest鏡像,導出到something-latest.tar
docker save -o ./something-latest.tar something:latest
-o
選項,用來指定輸出文件
在鏡像導出之后,我們就可以找到已經存儲鏡像內容的 something-latest.tar 這個文件了。如果使用解壓軟件查看其中的內容,會看到里面其實就是鏡像所基于的幾個鏡像層的記錄文件。
我們可以通過很多種方式將導出的鏡像文件復制到另一臺機器上,在這么操作之后,我們就要將鏡像導入到這臺新機器中運行的 Docker 中。
導入鏡像用 docker load
命令即可。
Tips: 我們并不真的需要一臺新的機器,把當前環境中 Docker something 鏡像刪掉即可
docker image rm something:latest
docker load -i something-latest.tar
鏡像導入后,我們就可以通過 docker images
看到它了,導入的鏡像會延用原有的鏡像名稱。
4. 從容器直接導出到鏡像壓縮包
使用 docker export
命令我們可以直接導出容器,我們可以把它理解為 docker commit
與 docker save
的結合體。
下面我們從容器 busybox 中直接導出鏡像包:
docker export -o ./something-export.tar busybox
需要注意的是,這種方式導出的鏡像壓縮包不能使用docker load
的方式導入,而應該使用 docker import
。使用 docker import
并非直接將容器導入,而是將容器運行時的內容以鏡像的形式導入。所以導入的結果其實是一個鏡像,而不是容器。在 docker import
的參數里,我們需要給這個鏡像命名。
docker import ./something-export.tar something:export
5. 小結
這一節我們介紹了如何通過 docker commit
工具,從容器快速生成 Docker 鏡像,在開發的過程中,使用 docker save
和 docker load
,或者是使用 docker export
和 docker import
都可以達到遷移容器或者鏡像的目的。但這種方式可維護性較差,后面的章節我們會學習如何使用 Dockerfile,從基礎鏡像來構建新的鏡像,這也是 Docker 官方推薦的方式。