iT邦幫忙

2026 iThome 鐵人賽

DAY 8
0
Modern Web

前端來點 AWS 技能樹!系列 第 8 篇

Day8 - Dockerfile: 把自己的頁面做成 image

  • 分享至 

  • xImage
  •  

昨天練習了怎麼啟動 container,也跑了第一個 web server,今天來試著把自己的 html 做成 image ㄅ!

建立自己的 image

首先跟昨天一樣開一個獨立的資料夾放今天的東西,裡面再開一個 site 資料夾放網頁:

mkdir -p ~/ironman-lab/day08/site
cd ~/ironman-lab/day08

把自己的頁面掛進 container

先在 site 裡建一個 index.html,用 VSCode 或終端機都行,內容隨意。我這邊就打:

<!doctype html>
<html lang="zh-Hant">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>Hello from my container</h1>
    <p>這個檔案在我的 Mac 上,nginx 在容器裡。</p>
  </body>
</html>

接著在終端機下:

docker run -d --name web -p 8080:80 -v ~/ironman-lab/day08/site:/usr/share/nginx/html nginx:alpine

https://ithelp.ithome.com.tw/upload/images/20260922/201797936JobUElH0n.png

  • 瀏覽器開 http://localhost:8080 看到自己的頁面。改一下 index.html 存檔,重新整理,直接變。
    https://ithelp.ithome.com.tw/upload/images/20260922/20179793zNeVPidQom.png
  • -v 是 --volume 的縮寫,格式是 -v 外面:裡面,它把 Mac 上的 ~/ironman-lab/day08/site 接到 container 裡的 /usr/share/nginx/html,也就是昨天 ls 看到放 index.html 的那個資料夾。接上之後,container 裡的那個路徑就是你電腦上的資料夾,不是複製一份過去,所以在 Mac 上改檔案,container 裡立刻看得到。方向跟 -p 一樣。
  • 這種接法叫 bind mount。注意這個 -v 是 docker 的參數,跟昨天 node -v 的 -v(版本)長得一樣但完全無關。
    接著我們用 docker images 觀察
docker images        # 沒有新東西
docker rm -f web     # 看完收掉,等一下要用同一個名字

https://ithelp.ithome.com.tw/upload/images/20260922/20179793O9Qtw5hItJ.png

  • 沒有新的 image。剛才只是把 Mac 上的資料夾借給 container 用,頁面還是活在你的電腦裡。這個 container 搬到另一台機器就沒有頁面了。所以要把頁面「包進去」,這就是 Dockerfile。

建第一個 Dockerfile

  1. 在 day08 資料夾裡(不是 site 裡)新增一個檔案,檔名就叫 Dockerfile,沒有副檔名。內容只有兩行:
FROM nginx:alpine
COPY site/ /usr/share/nginx/html/
  • FROM:以哪個 image 當底。昨天跑過的 nginx,這裡用 alpine 版比較小。
  • COPY <外面> <裡面>: 把 site 資料夾裡的東西複製進 image,放到 nginx 放網頁的那個位置。方向還是先寫自己這邊。
  1. 接著把它做成 image ,在終端機執行:
docker build -t my-site:v1 .
docker images

https://ithelp.ithome.com.tw/upload/images/20260922/20179793EjZZRECyBc.png
https://ithelp.ithome.com.tw/upload/images/20260922/20179793XmcSLGlEnl.png

  • docker build:照 Dockerfile 的步驟做出一個 image。
  • -t my-site:v1:給它名字和版本,名字只能小寫。
  • 最後那個 .:告訴 Docker「以現在這個資料夾當範圍」,Dockerfile 和 COPY 的路徑都從這裡算。這個點很常被漏掉,漏了會報錯喔 ~
  1. 我們再用 docker images 觀察,會看到多一個 my-site,大小差不多就是 nginx:alpine 再加幾 KB。
  2. 用自己的 image 跑起來,這次不掛任何資料夾:
docker run -d --name web -p 8080:80 my-site:v1

開 http://localhost:8080,同一個頁面,但這次頁面在 image 裡,不在你電腦的資料夾裡。
https://ithelp.ithome.com.tw/upload/images/20260922/20179793ZsIWVEx6Ua.png

image 是快照,改檔案不會變

現在把 site/index.html 的標題改成「Hello world v2」,存檔,重新整理瀏覽器:沒變,還是原來的字。
https://ithelp.ithome.com.tw/upload/images/20260922/20179793YIU09tjwTU.png
剛才用 -v 掛資料夾時改了會立刻變,這次不會,因為 container 用的是 build 當下複製進 image 的那一份,之後你在電腦上改什麼都跟它無關。image 就是一張快照。
要讓新內容生效,就得再 build 一次,這次給它 v2:

docker build -t my-site:v2 .
docker rm -f web
docker run -d --name web -p 8080:80 my-site:v2
docker images

https://ithelp.ithome.com.tw/upload/images/20260922/20179793h5Z5rVd66U.png
重新整理,變成 「Hello world v2」 了。docker images 裡 my-site 有 v1 和 v2 兩個,v1 沒有被蓋掉。
https://ithelp.ithome.com.tw/upload/images/20260922/201797938ckLtoOCM5.png

這就是用tag 管理版本:冒號後面的 v1、v2 就叫 tag。這次修改內容後,我們用 v2 標記新 image,原本的 v1 也保留下來;如果 v2 出問題,就可以改用 v1 重新建立 container。
不過 tag 可以被重新指定,所以要保留版本,就不要重複拿同一個 tag 標記不同內容。之後部署到 AWS 時,我們會用 Git commit 的編號當 tag,方便追蹤部署的是哪一版程式。

今天做了三件事:把資料夾掛進去、把頁面包進 image、再 build 一次出 v2。掛進去的搬不走,包進去的到哪都能跑,這就是 Dockerfile 存在的理由。

明天把自己的 Next.js 專案做成 image。另外你可能注意到 build 輸出裡的 [1/2]、[2/2],那是建置步驟的編號。這些步驟背後還牽涉到 image 的分層和 cache,明天會講為什麼 Dockerfile 的指令順序會影響 build 速度。

資安小提醒:COPY 會把指定來源裡的檔案包進 image,今天複製的是 site/。明天處理整個專案、使用 COPY . . 時,就要注意別把 .env、金鑰檔或不需要的 node_modules 一起包進去。image 之後還會推到雲端的 registry,所以 build 前要確認複製範圍,並用明天會介紹的 .dockerignore 排除不該帶入的檔案。

參考資料

Dockerfile 官方文件
docker build 官方文件


上一篇
Day7 - 來啟動第一個 Docker Container
下一篇
Day9 - 用多段式 Dockerfile,把 Next.js 打包成 image
系列文
前端來點 AWS 技能樹! 共 20 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言