National Yang Ming Chiao Tung University
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try a Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

1

Local AI

--

Uedu Code

--

陽明交大 AQI 70 24°C PM2.5 19
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 04

映像檔、層與 Docker Hub

search、pull、tag 與共用的映像檔層
Interaction 20 minute(s)

Learning Objectives

  • 分辨 registry、repository(倉庫)與 tag(標籤),看懂映像檔的完整名稱
  • 分辨官方映像檔與社群使用者的映像檔,判斷可不可以信任
  • 用 docker search 與 docker image pull 搜尋、下載指定版本的映像檔
  • 說明映像檔的分層(layer)與共用,用 image ls、history、rm 管理本機映像檔

映像檔從哪裡來

前兩課跑 hello-world、ubuntu:24.04 時,Docker 都會自動「下載映像檔」。這些映像檔放在哪裡?

名詞 比喻 說明
Registry 圖書館 存放映像檔的服務。預設的公用 registry 是 Docker Hub(hub.docker.com),由 Docker 公司經營
Repository(倉庫) 書架上的一套書 同一個軟體的映像檔放在同一個倉庫,例如 ubuntu 倉庫
Tag(標籤) 第幾版 區分同一個倉庫裡的不同版本,例如 24.04、22.04

所以 ubuntu:24.04 的意思是「ubuntu 倉庫裡標籤為 24.04 的映像檔」。它的完整名稱其實是:

docker.io/library/ubuntu:24.04
└registry┘└命名空間┘└倉庫┘└標籤┘

Docker Hub(docker.io)是預設值,官方映像檔的命名空間是 library,平常都省略不寫。

Docker Hub 不是唯一的 registry:GitHub 有 GitHub Container Registry(ghcr.io)、Red Hat 有 Quay(quay.io), 各家雲端也有自己的 registry;registry 的程式本身是開放原始碼,學校或公司也可以自己架一個私有的。 用別的 registry 時,名稱前面要寫上它的網址,例如 quay.io/jupyter/base-notebook(下一課會用到)。

官方映像檔與社群映像檔:可以信任嗎

Docker Hub 上的倉庫分成兩種命名方式:

類型 名稱長相 誰維護 信任程度
官方映像檔(Official Images,top-level) 只有倉庫名稱:ubuntu、python、mysql Docker 公司與該軟體的維護團隊共同管理(例如 Fedora 團隊提供 fedora) 經過審查,持續更新安全修補
使用者倉庫 使用者名稱/倉庫名稱:ncuedu/static_web 任何註冊 Docker Hub 的人 沒有經過 Docker 驗證,要自己判斷

網站上還會看到 Docker Official Image 與 Verified Publisher(經驗證的軟體公司)等標章。

映像檔裡的程式會在你的電腦上執行,挑選社群映像檔前先檢查:

  • 有沒有對應的官方映像檔或驗證過的發行者?有就優先用
  • 維護者是誰、有沒有公開原始碼或 Dockerfile、最近一次更新是什麼時候
  • 下載次數與星星數只能參考,不代表安全
  • 不要拉來路不明、說明空白的映像檔來處理帳號密碼或重要資料

互動練習:搜尋、下載與共用的層

依右下角的任務操作:先用 docker search python 看看哪一個是官方映像檔;下載 ubuntu:24.04;接著先下載 python:3.12、再下載 python:3.11,注意第二次下載時哪些層顯示 Already exists,「本機映像檔」欄位裡顏色相同的色塊就是共用的層;然後用 docker image history 看 python:3.12 由哪些層組成;最後用 docker image rm 移除用不到的 ubuntu:24.04。過程中隨時可以按 docker image ls 看看本機有哪些映像檔。

下載映像檔與標籤

docker container run 遇到本機沒有的映像檔會自動下載;也可以先用 docker image pull 下載好, 之後啟動容器就不用等:

docker image pull ubuntu:24.04     # 指定標籤
docker image pull alpine           # 沒寫標籤,等於 alpine:latest
Using default tag: latest
latest: Pulling from library/alpine
Status: Downloaded newer image for alpine:latest
docker.io/library/alpine:latest

已經下載過、而且 registry 上沒有更新時,會顯示 Status: Image is up to date for …。

latest 只是一個標籤名稱,不是 Docker 自動幫你挑「最新版」:

  • 沒寫標籤時,Docker 就用 latest 這個名字去找
  • 維護者通常讓 latest 指向最新的穩定版,但這是維護者的習慣,不是規則
  • latest 會隨時間改變指向:今天拉到的和半年後拉到的可能是不同版本

所以作業、專題與正式服務裡,請寫明確的版本標籤(python:3.12、ubuntu:24.04), 這樣環境才會固定,也才能真正解決「在我電腦上可以跑」的問題。

新式寫法 舊寫法
docker image pull ubuntu:24.04 docker pull ubuntu:24.04

映像檔是一層一層疊起來的

映像檔不是一個虛擬硬碟檔,而是由好幾個唯讀的層(layer)疊起來的,每一層記錄「和下面那一層相比改了什麼」。 Docker 用聯合檔案系統(Union File System)把這些層疊在一起,從上面看起來就像一個完整的檔案系統。

投影片的例子,一個資料分析用的映像檔可能是這樣疊的:

層(由下往上) 內容
第 1 層:基底映像檔(base image) Ubuntu 的系統檔案
第 2 層 安裝 Python
第 3 層 安裝 pip
第 4 層 安裝 numpy、pandas、matplotlib
  • 最底層叫基底映像檔(base image),例如 ubuntu、debian、alpine;它上面的每一層都以下面那層為「父層」(parent)。
  • 容器啟動時,Docker 在最上面再加一層可寫入的容器層;容器裡新增或修改檔案都寫在這一層, 要改到下面唯讀層的檔案時,先複製一份上來再改,這叫寫入時複製(Copy-on-Write)。 所以很多個容器可以共用同一個映像檔,彼此不會互相影響。

層可以共用:python:3.12 和 python:3.11 都建立在同一個 Debian 基底上, 下載完 3.12 再下載 3.11 時,相同的層顯示 Already exists,只下載不同的部分,也只佔一份磁碟空間。 也因為這樣,docker image ls 每個映像檔的 SIZE 是「各自完整的大小」,直接加總會比實際用掉的磁碟空間多。

管理本機的映像檔

指令 作用 舊寫法
docker image ls 列出本機映像檔(REPOSITORY、TAG、IMAGE ID、CREATED、SIZE) docker images
docker image ls python 只列出 python 倉庫的映像檔
docker image history python:3.12 看映像檔由哪些層組成、每層是哪個指令建立的、多大 docker history
docker image rm ubuntu:24.04 刪除映像檔 docker rmi
docker image prune 清掉沒有名稱、沒人使用的懸空映像檔

docker image history 的 CREATED BY 欄位會顯示建立該層的指令(例如 ADD file:…、RUN apt-get install …、CMD ["/bin/bash"]), SIZE 為 0B 的層只改了設定、沒有新增檔案。加 -H(human readable,預設已開啟)會用易讀的單位顯示大小與時間。

正在被容器使用的映像檔不能刪,即使那個容器已經停止:

$ docker image rm ubuntu:24.04
Error response from daemon: conflict: unable to remove repository reference "ubuntu:24.04"
(must force) - container a3f9c2e1b7d4 is using its referenced image

要先用 docker container rm 移除相關的容器,再刪映像檔。這也呼應第 02 課的生命週期: 容器的「結束」(rm)在前,映像檔的「消失」(image rm)在後。

想一想:倉庫與標籤

1.

執行 docker image pull nginx(沒有寫標籤),Docker 會下載哪一個?

2.

下面哪一個名稱是 Docker Hub 的使用者倉庫,而不是官方映像檔?

3.

為什麼做專題時建議寫 python:3.12 而不是 python:latest?

第 1 次作答

想一想:層與刪除

1.

已經下載 python:3.12,再下載 python:3.11 時,有幾層顯示 Already exists,代表什麼?

2.

docker image rm ubuntu:24.04 出現 container … is using its referenced image 的錯誤,應該怎麼做?

第 1 次作答

重點精華回顧

  • 映像檔放在 registry 的倉庫裡,用標籤區分版本;完整名稱是 registry/命名空間/倉庫:標籤,預設 registry 是 Docker Hub。
  • 只有倉庫名稱的是官方映像檔;使用者/倉庫 是社群上傳的,使用前檢查維護者、原始碼與更新時間。
  • docker search 找倉庫、docker image pull 下載;沒寫標籤就是 latest,但 latest 只是標籤名稱,正式使用請寫明確版本。
  • 映像檔由唯讀的層疊成,最底層是基底映像檔;容器在最上面加一層可寫入的層(寫入時複製)。
  • 相同的層可以共用,下載時顯示 Already exists,磁碟上只存一份。
  • docker image ls、history、rm 管理本機映像檔;有容器在用的映像檔要先移除容器才能刪。
這一課完成了!
Next lesson:挑一個映像檔來用
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。