National Yunlin University of Science and Technology
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 62 26°C PM2.5 12
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 08

建立、測試與發布映像檔

docker image build、build cache、執行測試與 push
Interaction導覽 20 minute(s)

Learning Objectives

  • 用 docker image build -t 依 Dockerfile 建立映像檔,說明最後那個「.」(建置目錄)的意思
  • 看懂建置快取(build cache),把很少變動的步驟放前面、常改的放後面
  • 用 -d -p 執行映像檔,再用 container port、top 與瀏覽器測試
  • 用 docker login 與 docker image push 把映像檔上傳到 Docker Hub,並用 image rm 清理本機

從 Dockerfile 到別人也能用的映像檔

上一課寫好了 Dockerfile,這一課把它變成真正的映像檔,測試它,再放上 Docker Hub 讓別人(或另一台電腦上的你)一個 pull 就能用。

Dockerfile ──docker image build──▶ 本機映像檔 ──docker container run──▶ 測試
                                        │
                                        └──docker image push──▶ Docker Hub ──docker image pull──▶ 其他電腦

專案目錄沿用上一課的 static_web:

static_web/
├── Dockerfile
└── index.html

docker image build

在專案目錄裡執行:

cd ~/static_web
docker image build -t ncuedu/static_web .
部分 意思
-t ncuedu/static_web 為映像檔取名(tag);沒寫標籤就是 ncuedu/static_web:latest,也可以寫 -t ncuedu/static_web:1.0
ncuedu/ Docker Hub 的帳號名稱;之後要 push,這裡必須是你自己的帳號
最後的 . 建置目錄(build context):目前所在的目錄。Docker 會把這個目錄的內容交給建置程序,COPY 只能從這裡拿檔案,預設也在這裡找 Dockerfile

最常見的錯誤是漏打最後的點,會出現 requires 1 argument 之類的訊息。Dockerfile 放在別處或叫別的名字時,用 -f 指定: docker image build -t ncuedu/static_web -f docker/Dockerfile .。

建置目錄裡的所有檔案都會送進建置程序,目錄太大會拖慢建置。可以在專案目錄放一個 .dockerignore,列出不需要的檔案或目錄(例如 .git、node_modules),寫法類似 .gitignore。

建好之後檢查:

指令 作用 舊寫法
docker image ls ncuedu/static_web 列出這個映像檔 docker images ncuedu/static_web
docker image history ncuedu/static_web 看每一層是由 Dockerfile 的哪一行產生、多大 docker history ncuedu/static_web

建置快取:為什麼第二次 build 快很多

Dockerfile 的每一行會產生一層(LABEL、EXPOSE、CMD 這類設定只記在映像檔資訊裡,不產生檔案)。 Docker 建置時會逐行檢查:這一行和它之前的每一行都沒變(COPY 還會比對檔案內容),就直接沿用上次的結果,這就是建置快取。

規則只有一條:某一行一旦需要重做,它後面的每一行都要重做。

修改 index.html 之後再建置一次:

FROM ubuntu:24.04                                 沿用快取
LABEL maintainer="[email protected]"                沿用快取
RUN apt-get update && apt-get install -y nginx    沿用快取(最花時間的一步省下來了)
COPY index.html /var/www/html/                    檔案變了,重做
EXPOSE 80                                         在重做的那行後面,重做
CMD ["nginx", "-g", "daemon off;"]                在重做的那行後面,重做

所以安排順序的原則是:很少變動的步驟放前面,常常修改的放後面。安裝套件放前面,複製自己的程式放最後。 如果把 COPY index.html 放在 RUN apt-get install 前面,每改一次網頁就要重新下載安裝 nginx。

Python 專案常見的寫法也是同一個道理:先只複製套件清單並安裝,最後才複製全部的程式碼。

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]

只改程式、沒改 requirements.txt 時,pip install 那一層會沿用快取。

輸出的寫法:目前的 Docker(BuildKit)在沿用快取的步驟前面標 CACHED;舊版的建置程式則顯示 ---> Using cache。 想強制全部重做時加 --no-cache。

互動練習:建置、快取與發布

左邊已經放好上一課的 Dockerfile。依下面的任務操作:先按 docker image build 建置;按「修改 index.html」把網頁改成第 2 版,再 build 一次,看終端機裡哪幾步出現 Using cache、哪幾步重做;接著按 docker container run -d -p 7777:80,確認瀏覽器顯示的是第 2 版;最後按 docker image push 上傳。可以試試看:改了 index.html 卻沒有重新 build 就 run,會看到哪一版?

執行與測試

docker container run -d -p 7777:80 --name static_web ncuedu/static_web
部分 意思
-d 在背景執行,網頁伺服器可以一直開著
-p 7777:80 主機的 7777 埠對應到容器的 80 埠(nginx 在容器裡聽 80)
--name static_web 容器名稱

檢查容器:

指令 作用
docker container ls PORTS 欄會顯示 0.0.0.0:7777->80/tcp
docker container port static_web 只看這個容器的埠號對應
docker container top static_web 看容器裡執行中的程序,應該有 nginx 的 master 與 worker

測試方式有兩種:

  1. 經由主機的埠號:瀏覽器開 http://localhost:7777(在遠端主機上就用主機的 IP,例如 http://192.168.88.100:7777),或在終端機用 curl http://localhost:7777。
  2. 從另一個容器連過去:投影片的做法是查出 static_web 的 IP(例如 172.17.0.2),再從 alpine 容器執行 wget -qO - http://172.17.0.2。容器之間怎麼互相找到,第 09 課會用更好的方法(自訂網路、用名字連線)。

在真的終端機走一次:build、run、push

下面是在 Ubuntu 主機上的完整流程。映像檔 ID、大小與時間都是示意,你的畫面數字會不同。ncuedu 是投影片用的帳號名稱,請換成你自己的 Docker Hub 帳號。

  1. 1

    準備專案目錄

    建立 static_web 目錄,寫好 index.html 與上一課的 Dockerfile。用 cat 確認內容。

  2. 2

    建置映像檔

    注意最後的 .。每一行 Dockerfile 對應一個步驟,第一次建置時 RUN 那一步要下載安裝 nginx,最花時間。

  3. 3

    檢查映像檔與它的層

    history 由上往下是由新到舊:最上面幾行是你的 Dockerfile 產生的,下面是 ubuntu 基底映像檔原本的層。LABEL、EXPOSE、CMD 的大小是 0B,因為它們只是設定。

  4. 4

    執行容器並檢查

    -d 讓容器在背景執行,Docker 只印出完整的容器 ID。用 ls、port、top 確認它正常運作。

  5. 5

    測試網頁

    用 curl 連主機的 7777 埠,應該看到自己的網頁。在有桌面的電腦上也可以直接用瀏覽器開 http://localhost:7777。

  6. 6

    修改網頁並重新建置:看快取

    只改了 index.html,所以 FROM 與 RUN 都沿用快取(標 CACHED),只有 COPY 重做,幾秒就完成。舊容器跑的還是舊映像檔,要先移除再用新映像檔建立。

  7. 7

    登入 Docker Hub 並上傳

    先到 Docker Hub 網站註冊帳號,映像檔名稱的前半段必須和帳號相同。密碼建議改用 Docker Hub 帳號設定裡產生的存取權杖(access token)。上傳時,ubuntu 基底的層 Docker Hub 上本來就有,只會上傳你自己做出來的層。

  8. 8

    清理本機,再從 Docker Hub 拿回來

    映像檔還有容器在用時不能刪,所以先移除容器。刪掉本機映像檔後,再用 pull 從 Docker Hub 下載回來,證明它真的上傳成功;其他電腦也是用同樣的方式取得。

這段導覽完成了

上傳時要注意的事

情況 說明
denied: requested access to the resource is denied 映像檔名稱的帳號不是你登入的帳號,或還沒 docker login。可以用 docker image tag ncuedu/static_web 你的帳號/static_web 另取一個名字再 push
想保留多個版本 建置時加版本標籤 -t 你的帳號/static_web:1.0,push 時也指定標籤;只用 latest 時,新版會蓋掉舊版
公開或私人 Docker Hub 上的儲存庫可以設成公開或私人,公開的任何人都能 pull
不要放進映像檔的東西 密碼、API 金鑰、個人資料。映像檔的每一層都拿得出來,即使後面的步驟把檔案刪掉,前面那層還在

清理本機用 docker image rm(舊寫法 docker rmi)。映像檔還有容器(包括已停止的)在用時會拒絕刪除,先 docker container rm 再刪。

想一想:建置與快取

1.

docker image build -t ncuedu/static_web . 最後的 . 代表什麼?

2.

Dockerfile 依序是 FROM、RUN(安裝 nginx)、COPY index.html、CMD。只修改了 index.html 再建置,哪些步驟會沿用快取?

3.

為了讓建置比較快,下面哪一種順序比較好?

第 1 次作答

想一想:測試與發布

1.

用 docker container run -d -p 7777:80 ncuedu/static_web 啟動後,在主機上要用哪個網址看網頁?

2.

docker image push ncuedu/static_web 出現 requested access to the resource is denied,最可能的原因是?

第 1 次作答

重點精華回顧

  • docker image build -t 帳號/名稱 . 依 Dockerfile 建立映像檔;最後的 . 是建置目錄,COPY 只能從這裡拿檔案。
  • 用 docker image ls 與 docker image history 檢查映像檔與每一層的來源。
  • 建置快取:某一行沒變就沿用,一旦有一行重做,後面全部重做;很少變的步驟放前面,常改的放後面。
  • 用 docker container run -d -p 7777:80 執行,再以 container port、container top、瀏覽器或 curl 測試;改了映像檔要用新映像檔重新建立容器。
  • docker login 後用 docker image push 上傳;映像檔名稱的帳號必須是你自己的。不要把密碼或金鑰放進映像檔。
  • docker image rm 刪除本機映像檔前,要先移除使用它的容器。
這一課完成了!
Next lesson:埠號、容器網路與 Entrypoint
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。