跳至主要内容

4.6 映像檔的唯讀性

映像檔本身是唯讀的,意思就是我們沒辦法更動映像檔內部的檔案系統,那您可能會想說奇怪,Docker 容器篇 還有練習過在 Ubuntu 裡面安裝 curl 這個套件,怎麼會說映像檔的檔案系統是不能更動的呢?

當時有稍微提過可寫層,現在則會更深入的探討。

Docker 在容器啟動時多加一層可寫層在映像檔的上方,所有對於檔案系統的更動都會記錄在可寫層上,且會隨著容器的刪除而一併消失。

而若是更改的內容涉及映像檔原先擁有的檔案,Docker 則會在可寫層上採用 Copy & Write 的方式,使得映像檔最初的檔案系統依舊保持一致,這麼做的理由其實非常簡單,若是每次使用映像檔都會導致其檔案系統受到污染,那就大幅度地降低共同使用的方便性,啟動速度也會大幅度的下降。

利用可寫層來保持唯讀性

Docker 容器篇,我們透過 docker container inspect 的指令來查看容器的細節資料,而映像檔當然也有支援這樣的指令。

讓我們來看看能夠得到什麼有用的資訊!

$ docker image inspect nginx
[
...
"ExposedPorts": {
"80/tcp": {}
},
....
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin...",
"NGINX_VERSION=1.23.1",
"NJS_VERSION=0.7.6",
"PKG_RELEASE=1~bullseye"
],
....
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"nginx\" \"-g\" \"daemon off;\"]"
],
....
"Os": "linux",
...
]

從最上面的 ExposedPorts 就可以看出映像檔在建置的時候就已經設定好了開啟的 port,這也是為何在練習容器操作的章節,我們都不會去更動右邊的 port ( 幫你回憶一下,--publish 的格式長這樣 8080:80 ) ,是因為更動後會和映像檔設定的不同,導致服務對不上。

而第二段的 ENV 則是環境變數,可以在建置映像檔時就放進去的變數,而容器啟動時內部就會有擁有這些環境變數,可以做個測試,先進入 nginx 運行的容器,並且呼叫環境變數。

$ docker container run --interactive --tty nginx bash
root@5ada1085c888:/# echo $NGINX_VERSION
1.23.1
root@5ada1085c888:/# exit

這樣可以稍微理解 映像檔作為啟動容器的說明書以及工具包 這個概念了嗎?

而第三段則是在容器章節就提過的啟動指令,這邊預設是啟動 nginx 的服務。

最後回到前面說過的唯讀性,我們做得這些改變並不會影響到 nginx 這個映像檔本身,即使我們替換了啟動指令,也都是在可寫層的變化,利用 docker image inspect 的指令還是可以查看到映像檔本身並沒有任何改變。

而最後則是 OS,也就是作業系統,可以看到這邊是被設計執行在 Linux 的作業系統上,也呼應到 2-3 容器與虛擬機 中有說過 macOS 本身也是運行了一個迷你的虛擬機在執行 Docker,所以這邊看到的 OS 才不會是 macOS 而是 Linux。