【Docker 入門系列】#03 Dockerfile 入門:打包你的應用程式

測驗:Dockerfile 入門

共 5 題,點選答案後會立即顯示結果

1. Dockerfile 的主要用途是什麼?

  • A. 管理 Docker 容器的網路設定
  • B. 定義如何將應用程式打包成映像檔
  • C. 監控容器的執行狀態
  • D. 設定容器之間的通訊規則

2. 在 Dockerfile 中,FROM python:3.11 這行指令的作用是什麼?

  • A. 安裝 Python 3.11 到容器中
  • B. 下載 Python 3.11 原始碼
  • C. 選擇已安裝 Python 3.11 的映像檔作為基底
  • D. 檢查本機是否安裝了 Python 3.11

3. RUNCMD 指令的差異是什麼?

  • A. RUN 在建置時執行,CMD 在容器啟動時執行
  • B. RUN 只能執行一次,CMD 可以執行多次
  • C. RUN 用於 Linux,CMD 用於 Windows
  • D. 兩者功能完全相同,只是名稱不同

4. 執行 docker build -t my-app . 時,-t my-app 的作用是什麼?

  • A. 指定 Dockerfile 的路徑
  • B. 為建置的映像檔命名為 my-app
  • C. 設定建置的超時時間
  • D. 指定要使用的基底映像檔

5. 為什麼在 Dockerfile 中通常先複製 requirements.txt,再執行 pip install,最後才複製其他檔案?

  • A. 這是 Docker 的語法規定,順序不能改變
  • B. 因為其他檔案太大,必須分開複製
  • C. 利用 Docker 快取機制,當相依套件沒變時不用重新安裝
  • D. 避免相依套件覆蓋程式碼檔案

一句話說明

Dockerfile 是一份「安裝說明書」,告訴 Docker 怎麼把你的應用程式打包成映像檔。

為什麼需要 Dockerfile?

在上一篇我們學會用 docker run 執行別人做好的映像檔。但如果是你自己寫的應用程式呢?

這時候你需要 Dockerfile:

  • 打包一次,到處執行:把程式和環境一起包起來
  • 環境一致性:不再有「在我電腦上可以跑」的問題
  • 自動化部署:CI/CD 可以自動建置映像檔

最小範例

假設你有一個簡單的 Python 程式 app.py

print("Hello from Docker!")
Code language: PHP (php)

Dockerfile 這樣寫:

FROM python:3.11
COPY app.py /app.py
CMD ["python", "/app.py"]
Code language: JavaScript (javascript)

三行就完成了!

逐行翻譯

FROM python:3.11
Code language: CSS (css)

「以 python:3.11 映像檔為基底」。就像裝電腦先選作業系統,這裡選擇已經裝好 Python 3.11 的環境。

COPY app.py /app.py

「把本地的 app.py 複製到容器內的 /app.py」。就像把你的程式檔案放進去。

CMD ["python", "/app.py"]
Code language: CSS (css)

「容器啟動時執行 python /app.py」。告訴 Docker 預設要跑什麼指令。

Dockerfile 常用指令

FROM:選擇基底映像檔

FROM python:3.11          # Python 環境
FROM node:20              # Node.js 環境
FROM ubuntu:22.04         # 純 Linux 系統
Code language: CSS (css)

必看懂:每個 Dockerfile 都從 FROM 開始,選擇你需要的執行環境。

COPY:複製檔案

COPY app.py /app.py              # 複製單一檔案
COPY . /app                       # 複製整個目錄
COPY requirements.txt /app/       # 複製到指定目錄
Code language: PHP (php)

翻譯:「把本地的 [來源] 複製到容器內的 [目的地]」

RUN:執行指令

RUN pip install flask                    # 安裝 Python 套件
RUN npm install                          # 安裝 Node.js 套件
RUN apt-get update && apt-get install -y curl   # 安裝系統工具
Code language: PHP (php)

翻譯:「建置時執行這個指令」。通常用來安裝相依套件。

CMD:預設啟動指令

CMD ["python", "app.py"]         # 執行 Python
CMD ["npm", "start"]             # 執行 npm start
CMD ["./my-script.sh"]           # 執行腳本
Code language: CSS (css)

翻譯:「容器啟動時預設執行這個指令」。

WORKDIR:設定工作目錄

WORKDIR /app

翻譯:「之後的指令都在 /app 目錄下執行」。類似 cd /app

EXPOSE:宣告對外連接埠

EXPOSE 8080

翻譯:「這個程式會使用 8080 連接埠」。這是文件性質的宣告,方便其他人知道要開哪個連接埠。

常見變化:完整的 Python 應用程式

FROM python:3.11

WORKDIR /app

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .

EXPOSE 5000

CMD ["python", "app.py"]
Code language: JavaScript (javascript)

逐行翻譯

  1. 以 Python 3.11 為基底
  2. 設定工作目錄為 /app
  3. 先複製 requirements.txt(相依套件清單)
  4. 安裝所有相依套件
  5. 複製其他所有檔案
  6. 宣告程式使用 5000 連接埠
  7. 啟動時執行 python app.py

為什麼先複製 requirements.txt 再複製其他檔案?這是為了利用 Docker 的快取機制。如果相依套件沒變,就不用重新安裝。

常見變化:Node.js 應用程式

FROM node:20

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .

EXPOSE 3000

CMD ["npm", "start"]
Code language: JavaScript (javascript)

逐行翻譯

  1. 以 Node.js 20 為基底
  2. 設定工作目錄為 /app
  3. 先複製 package.json 和 package-lock.json
  4. 安裝相依套件
  5. 複製其他所有檔案
  6. 宣告程式使用 3000 連接埠
  7. 啟動時執行 npm start

建置映像檔:docker build

寫好 Dockerfile 後,用 docker build 建置映像檔。

基本用法

docker build -t my-app .

拆解

  • docker build:建置映像檔
  • -t my-app:給映像檔取名為 my-app
  • .:Dockerfile 在目前目錄

指定版本標籤

docker build -t my-app:1.0 .
Code language: CSS (css)

這樣映像檔名稱就是 my-app:1.0。如果不指定,預設是 my-app:latest

建置過程解讀

執行 docker build 時,你會看到類似這樣的輸出:

Step 1/5 : FROM python:3.11
 ---> a1b2c3d4e5f6
Step 2/5 : WORKDIR /app
 ---> Running in 123abc456def
 ---> b2c3d4e5f6a7
Step 3/5 : COPY requirements.txt .
 ---> c3d4e5f6a7b8
Step 4/5 : RUN pip install -r requirements.txt
 ---> Running in 456def789ghi
Successfully built d4e5f6a7b8c9
Successfully tagged my-app:latest

每一個 Step 對應 Dockerfile 的一行指令,每一步完成後都會產生一個中間層(layer)。

從自己的映像檔啟動容器

建置完成後,就可以用你熟悉的 docker run 啟動:

docker run my-app

如果程式需要對外連線(例如 Web 應用程式):

docker run -p 5000:5000 my-app
Code language: CSS (css)

-p 5000:5000 表示把容器的 5000 連接埠對應到本機的 5000 連接埠。

實戰練習

讓我們實際建置一個 Python Web 應用程式。

第一步:建立專案目錄

mkdir my-flask-app
cd my-flask-app

第二步:建立 app.py

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello():
    return 'Hello from Docker!'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
Code language: JavaScript (javascript)

第三步:建立 requirements.txt

flask

第四步:建立 Dockerfile

FROM python:3.11

WORKDIR /app

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .

EXPOSE 5000

CMD ["python", "app.py"]
Code language: JavaScript (javascript)

第五步:建置映像檔

docker build -t my-flask-app .

第六步:啟動容器

docker run -p 5000:5000 my-flask-app
Code language: CSS (css)

打開瀏覽器訪問 http://localhost:5000,你會看到「Hello from Docker!」

必看懂 vs 知道就好

必看懂(會一直出現)

  • FROM:選擇基底映像檔
  • COPY:複製檔案到容器
  • RUN:建置時執行指令
  • CMD:容器啟動指令
  • WORKDIR:工作目錄

知道就好(遇到再查)

  • ENTRYPOINT:類似 CMD 但用於不可變的啟動指令
  • ENV:設定環境變數
  • ARG:建置時的參數
  • VOLUME:宣告資料卷
  • HEALTHCHECK:健康檢查

Vibe Coder 檢查點

當 AI 產生 Dockerfile 時,確認這些:

  1. FROM 是否合理? 有沒有選對程式語言版本
  2. COPY 順序對不對? 相依套件檔案應該先複製
  3. RUN 有沒有安裝必要套件? 檢查有沒有遺漏
  4. CMD 指令對不對? 確認是正確的啟動方式
  5. EXPOSE 連接埠對不對? 確認跟程式實際使用的一致

小結

這篇你學會了:

  • Dockerfile 的用途:把應用程式打包成映像檔
  • 常用指令:FROM、COPY、RUN、CMD、WORKDIR、EXPOSE
  • 如何用 docker build -t 建置映像檔
  • 如何用 docker run 啟動自己建置的映像檔

下一篇我們會介紹如何管理多個容器,以及如何讓資料持久保存。

進階測驗:Dockerfile 入門

測驗目標:驗證你是否能在實際情境中應用所學。
共 5 題,包含情境題與錯誤診斷題。

1. 你正在為一個 Flask Web 應用程式撰寫 Dockerfile。應用程式使用 5000 連接埠,你希望建置時能利用快取加速。以下哪個 Dockerfile 結構最佳? 情境題

  • A. FROM → COPY . . → RUN pip install → CMD
  • B. FROM → WORKDIR → COPY requirements.txt → RUN pip install → COPY . . → CMD
  • C. FROM → CMD → COPY → RUN pip install
  • D. FROM → RUN pip install → COPY . . → CMD

2. 小明執行 docker build 後,想要啟動容器測試,卻發現無法從瀏覽器存取應用程式。 錯誤診斷

docker run my-flask-app

應用程式在容器內的 5000 連接埠運行,但瀏覽器無法存取 localhost:5000。最可能的原因是?

  • A. Dockerfile 中沒有寫 EXPOSE 5000
  • B. 映像檔建置失敗
  • C. 沒有使用 -p 參數對應連接埠
  • D. Flask 應用程式沒有正確啟動

3. 你需要為一個 Node.js 專案建置 Docker 映像檔。專案使用 npm 管理套件,入口點是 npm start。以下 Dockerfile 有什麼問題? 錯誤診斷

FROM node:20 COPY . /app WORKDIR /app CMD [“npm”, “start”]
  • A. WORKDIR 應該在 COPY 之前
  • B. 缺少 RUN npm install 安裝相依套件
  • C. CMD 語法錯誤,應該用 RUN
  • D. 缺少 EXPOSE 宣告

4. 你的同事產生了以下 Dockerfile,你需要確認它是否正確。這個 Dockerfile 會成功建置嗎? 情境題

WORKDIR /app FROM python:3.11 COPY requirements.txt . RUN pip install -r requirements.txt COPY . . CMD [“python”, “app.py”]
  • A. 不會,FROM 必須是第一行指令
  • B. 會成功,順序不影響結果
  • C. 不會,缺少 EXPOSE 指令
  • D. 會成功,但 WORKDIR 會被忽略

5. AI 幫你產生了以下 Dockerfile,你需要驗證它是否適合你的專案。專案是一個監聽 8080 連接埠的 Python FastAPI 應用程式。 情境題

FROM python:3.11 WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . EXPOSE 5000 CMD [“uvicorn”, “main:app”, “–host”, “0.0.0.0”, “–port”, “8080”]

這個 Dockerfile 有什麼問題?

  • A. 應該使用 node 而非 python 作為基底
  • B. CMD 應該改用 RUN
  • C. WORKDIR 位置錯誤
  • D. EXPOSE 5000 與實際使用的 8080 連接埠不一致

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *