初學者指南:什麼是 Dockerfile?—— 以實際範例解析

更新日期: 2025 年 3 月 5 日

如果你剛開始學習 Docker,可能會聽到「Dockerfile」這個詞。

簡單來說,Dockerfile 是用來建立 Docker 映像檔(Image)的腳本,它定義了如何建構一個容器環境,使得應用程式能夠在任何環境中保持一致地運行。

本文將以一個 Dockerfile 實際範例來說明它的各個指令,並幫助初學者了解 Dockerfile 的運作方式。


Dockerfile 是什麼?

想像一下,你要在一台新的電腦上安裝一個應用程式,比如 Django 網站,你通常會做什麼?

你可能需要:

  1. 安裝作業系統(例如 Ubuntu)
  2. 設定時區、環境變數
  3. 安裝 Python、Django 和其他必需的工具
  4. 把你的應用程式的程式碼放到對應的目錄
  5. 安裝應用程式所需的套件
  6. 最後,啟動 Django 伺服器,讓網站跑起來

這些步驟如果要手動做,每次換電腦、換環境時都要重來一遍,非常麻煩。

Dockerfile 就是用來幫你 自動化這些步驟 的一個設定檔!

Dockerfile 是怎麼工作的?

Dockerfile 就像是一張 烹飪食譜,告訴 Docker 該如何一步步「製作」出一個能執行你應用程式的環境。

當你執行 docker build 這個指令時,Docker 會按照 Dockerfile 上的步驟,自動建立一個新的映像檔(Image)

這個映像檔就像是安裝好所有必要環境的「模擬電腦」,之後你可以用它來快速啟動應用程式。

graph TD;
    A["開始"] --> B["撰寫 Dockerfile"]
    B --> C["執行 docker build"]
    C --> D["建立 Docker 映像檔 (Image)"]
    D --> E["執行 docker run 或 docker-compose up"]
    E --> F["啟動容器 (Container)"]
    F --> G["應用程式開始運作"]

Dockerfile 通常包含哪些內容?

Dockerfile 裡,我們會寫下一些「指令」,來讓 Docker 知道該做哪些事情,例如:

  1. 基礎映像(Base Image):要用什麼作業系統?(如 Ubuntu、Alpine、Debian)
  2. 執行環境設定:設定時區、環境變數
  3. 安裝必要套件:Python、Django、資料庫等
  4. 設定工作目錄:告訴 Docker 哪裡是應用程式的「家」
  5. 複製應用程式檔案:把你的專案程式碼放進 Docker 裡
  6. 安裝應用程式的套件:透過 pip 安裝 requirements.txt 內的套件
  7. 執行應用程式的指令:告訴 Docker 啟動 Django 伺服器

簡單來說,Dockerfile 就是讓你 一次寫好設定,之後自動建立環境,這樣就不用每次都手動設定環境了!

接下來,我們用一個 實際的 Dockerfile 來解析,讓你更容易理解。


Dockerfile 解析:以 Django 應用為例

以下是範例 Dockerfile 內容:

# 使用 Ubuntu 20.04 作為基礎映像
FROM ubuntu:20.04

# 環境變數:自動設定時區,避免 tzdata 提示交互式輸入
ENV TZ=Asia/Taipei
RUN apt update && apt install -y tzdata

# 安裝 Python 和必要套件
RUN apt update && apt install -y python3 python3-pip python3-venv

# 設定工作目錄
WORKDIR /app

# 複製專案檔案
COPY . .

# 安裝 Django 和依賴套件
RUN pip3 install --no-cache-dir -r requirements.txt

# 預設啟動 Django 伺服器
CMD ["python3", "manage.py", "runserver", "0.0.0.0:8000"]

這個 Dockerfile 是用來建立一個 Ubuntu 20.04 環境,並運行 Django 應用程式的容器。

接下來我們會一行行解析這些指令。


Dockerfile 指令解析

接下來,我們將逐步拆解 Dockerfile 內的每一行指令,讓你能清楚了解它們的作用,並學會如何根據需求修改 Dockerfile

指定基礎映像

FROM ubuntu:20.04
  • FROM 指令是 Dockerfile 的第一行,負責定義基礎映像(Base Image)
  • 這行的意思是:我們的容器環境會以 Ubuntu 20.04 作為基礎,這代表我們的應用程式會運行在 Ubuntu 20.04 系統上。

🔹 為什麼要選擇基礎映像?

  • 基礎映像就像是作業系統的安裝包,例如 ubuntu:20.04alpine:latestpython:3.9 等。
  • 選擇適當的映像可以減少我們需要手動安裝的套件,讓開發更輕鬆。

設定環境變數

ENV TZ=Asia/Taipei
RUN apt update && apt install -y tzdata

🔹 ENV 指令

ENV TZ=Asia/Taipei
  • ENV 指令用來設定環境變數,在這裡我們設定 TZAsia/Taipei,確保時區正確。
  • 這樣做可以避免 Docker 在安裝 tzdata 時出現手動選擇時區的交互操作。

🔹 RUN 指令

RUN apt update && apt install -y tzdata
  • RUN 指令執行 Linux 指令,在這裡用來安裝 tzdata(時區套件)
  • apt update:更新 apt 軟體套件庫,確保我們安裝的是最新版本的套件。
  • apt install -y tzdata:自動安裝 tzdata-y 參數代表自動同意安裝。

📌 這樣做的好處

  1. 避免安裝 tzdata 時需要手動選擇時區,提升自動化程度。
  2. 確保容器內的時間與主機同步,對於需要時間資訊的應用(如 Django log)非常重要。

補充:APT 軟體套件庫是什麼?

什麼是 APT?

APT(Advanced Package Tool)是 DebianUbuntu 等 Linux 系統用來管理軟體套件的工具。它負責:

  • 下載 軟體
  • 安裝 軟體
  • 更新 軟體
  • 移除 軟體

在 Linux 中,我們不需要像 Windows 一樣手動去官網下載 .exe 檔案來安裝軟體,而是透過 APT 來自動處理這些事情。例如:

sudo apt install python3

這行指令會幫你下載並安裝 python3,而且還會自動處理所有它需要的其他依賴套件(dependencies)。

那「APT 軟體套件庫」是什麼?

APT 軟體套件庫(APT Package Repository)是一個 儲存軟體的雲端伺服器,APT 會從這裡下載所需的軟體。

可以把它想像成:

  • App StoreGoogle Play:當你要安裝 App 時,不是自己去找安裝檔,而是透過應用商店下載。
  • APT 軟體套件庫 就像 Linux 的應用商店,裡面有各種可以安裝的軟體,APT 會從這裡抓取最新版本的套件。

當你執行:

sudo apt update

這個指令的意思就是:「去看看 Linux 軟體倉庫裡,有沒有軟體的新版本!」

當你執行:

sudo apt install vim

這個指令的意思是:「從 Linux 軟體倉庫下載並安裝 vim 這個軟體。」

為什麼 apt update 很重要?

在 Dockerfile 或 Linux 系統中,你常會看到:

RUN apt update && apt install -y python3

這裡 apt update 是用來更新 APT 軟體套件庫的索引,確保安裝的軟體是最新的。

如果沒有先 apt update,可能會遇到:

  1. 安裝到舊版本的軟體,因為系統還在用舊的索引檔案。
  2. 找不到軟體,因為新的軟體可能已經更新了,但系統不知道。

所以,良好的習慣是在安裝軟體前,先執行:

sudo apt update

這樣可以確保你下載的是最新的版本。

安裝 Python 和相關套件

RUN apt update && apt install -y python3 python3-pip python3-venv

這行指令的作用是安裝 Python 3 及其相關工具。

  • apt update:先更新 apt 軟體套件庫,確保能安裝最新的軟體版本。
  • apt install -y python3 python3-pip python3-venv
    • python3:安裝 Python 3,讓我們能夠執行 Python 程式。
    • python3-pip:安裝 pip,這是 Python 的套件管理工具,方便安裝 Django 及其他依賴。
    • python3-venv:安裝 venv,這是 Python 的虛擬環境管理工具,可用來管理專案內的 Python 套件,避免與系統套件衝突。

📌 為什麼要安裝 python3-venv

  • venv 可用來建立獨立的 Python 環境,確保應用程式的 Python 版本與依賴不會與系統環境混淆。
  • 但在 Docker 容器中,由於容器本身已經是獨立的環境,venv 通常不是必要的,但如果你的應用需要它,還是可以安裝。

設定工作目錄

WORKDIR /app
  • WORKDIR 指令用來指定容器內的工作目錄
  • 這行指令表示之後所有的指令(如 COPYRUNCMD都會在 /app 這個目錄內執行
  • 這樣可以讓檔案的組織更清楚,避免散落在容器內的不同目錄。

📌 為什麼要設定 WORKDIR

  1. 讓開發者知道應用程式的根目錄在哪裡。
  2. 確保 COPYRUN 指令執行時在正確的目錄內,避免找不到檔案的問題。

複製應用程式到容器

COPY . .
  • COPY 指令負責將本機端的檔案複製到容器內的目標目錄。
  • COPY . . 代表將當前目錄(包含所有應用程式的檔案)複製到 /app(因為我們前面已經設定了 WORKDIR /app)。

📌 這樣做的目的

  • 把應用程式的程式碼和設定檔案複製到容器中,讓容器能夠執行我們的應用程式。

安裝 Django 及相關依賴

RUN pip3 install --no-cache-dir -r requirements.txt
  • pip3 install -r requirements.txt:使用 pip3 安裝 requirements.txt 中列出的所有 Python 套件。
  • --no-cache-dir:避免儲存快取,減少 Docker 映像的大小,確保容器不會留下不必要的安裝檔案。

📌 這樣做的目的

  • requirements.txt 內通常會列出 Django 和其他依賴的套件,例如:
django>=3.2,<4.0
djangorestframework
gunicorn
  • 這樣就能確保應用程式在 Docker 容器內的 Python 環境與本機相同。

設定預設啟動指令

CMD ["python3", "manage.py", "runserver", "0.0.0.0:8000"]
  • CMD 指令用來指定容器啟動時執行的命令
  • 這行指令等同於執行:
python3 manage.py runserver 0.0.0.0:8000
  • 它會啟動 Django 內建的開發伺服器,並監聽 0.0.0.0:8000,允許外部存取。

📌 為什麼 CMD 這麼重要?

  • CMD 定義了「當容器啟動時,應該做什麼」。
  • 如果沒有 CMD,容器可能會在啟動後立刻結束,因為沒有任何進程在執行。

📌 為什麼要監聽 0.0.0.0

  • 0.0.0.0 代表「監聽所有網路介面」,這樣我們才能從本機(localhost)或其他裝置存取 Django 應用程式。

如何使用這個 Dockerfile

現在我們已經了解 Dockerfile 的內容,接下來我們要實際使用它來 建立 Docker 映像檔(Image)並啟動容器(Container)

請按照以下步驟來運行 Django 應用程式。

建立 Docker 映像檔(Image)

Dockerfile 所在的目錄,打開終端機(Terminal)或命令提示字元(Command Prompt),執行:

docker build -t my-django-app .

指令解析

  • docker build:告訴 Docker 要建立一個新的映像檔。
  • -t my-django-app:給這個映像檔取名為 my-django-app,讓我們之後可以方便管理。
  • -t 代表 tag(標籤),用來給 Docker 映像檔取一個名字,讓我們之後可以更容易管理和使用這個映像檔。
  • .(點):代表 Dockerfile 所在的目錄,Docker 會在這個目錄內尋找 Dockerfile,並根據其中的指令來建立映像。

執行後會發生什麼?

  1. Docker 會讀取 Dockerfile,並依照其中的指令 一步步 建立映像檔:
    • 下載 Ubuntu 20.04 基礎映像
    • 安裝 Python 3、pip 等工具
    • 設定時區
    • 複製應用程式到容器
    • 安裝 requirements.txt 中的 Python 套件
  2. 當這些步驟完成後,Docker 會產生一個名為 my-django-app 的映像檔,這是一個可以運行 Django 應用的完整環境

🔹 你可以用以下指令查看已建立的映像檔:

docker images

你應該會看到類似這樣的輸出:

REPOSITORY        TAG       IMAGE ID       CREATED          SIZE
my-django-app     latest    abc12345       5 minutes ago    500MB

這代表 my-django-app 映像檔已經建立完成!

啟動 Docker 容器(Run Container)

當我們有了映像檔後,就可以使用它來啟動一個新的容器,讓 Django 伺服器運行起來。執行:

docker run -p 8000:8000 my-django-app

指令解析

  • docker run:這是用來啟動容器的指令。
  • -p 8000:8000:將本機的 8000 端口映射到容器內的 8000 端口,這樣我們就能從瀏覽器訪問 Django 應用程式。
  • my-django-app:這是我們剛剛建立的映像檔名稱,Docker 會根據這個映像檔來建立並啟動一個容器。

容器內的 8000 端口跟本機的 8000 端口之間的關係?

當你啟動一個 Docker 容器時,它是在一個獨立的環境內運行的,類似於一台虛擬機。

因此,容器內部的端口 預設是無法直接被外部(你的電腦)存取的,這時候我們就需要使用 -p 參數來進行端口映射。

-p 8000:8000 是什麼意思?

當你執行:

docker run -p 8000:8000 my-django-app

它的作用是:

  • 左邊的 8000(本機端口):這是你電腦(Host)上的端口。
  • 右邊的 8000(容器內端口):這是容器內部的端口。

這樣做的結果是 把你的本機 8000 端口,映射到容器內的 8000 端口,所以當你在瀏覽器打開:

http://localhost:8000

瀏覽器會請求 本機的 8000 端口,而這個端口已經被映射到容器內部的 8000,因此請求會成功傳遞到容器內部的 Django 伺服器,然後返回結果。

如果不用 -p 8000:8000,會發生什麼事?

假設你直接執行:

docker run my-django-app

這樣不會對外開放任何端口,所以即使 Django 伺服器在容器內的 8000 端口運行,你的本機完全無法連線

🔹 測試方式 如果你這樣運行:

docker run my-django-app

然後試著打開:

http://localhost:8000

你會發現 連不上,因為容器內的 8000 端口並沒有對外開放。

這時候,你可以用以下方式來確認容器內的服務是否真的有在 8000 端口運行:

docker exec -it <CONTAINER_ID> netstat -tulnp

如果 8000 端口有開啟,代表 Django 伺服器是有在運行的,只是我們的本機無法連線。

執行後會發生什麼?

  1. Docker 會根據 my-django-app 映像檔來建立一個新的容器
  2. 容器會執行 CMD ["python3", "manage.py", "runserver", "0.0.0.0:8000"],啟動 Django 伺服器。
  3. 因為我們使用了 -p 8000:8000,所以可以透過 localhost:8000 訪問這個應用程式。

🔹 查看目前運行中的容器 如果你想確保容器已經成功啟動,可以執行:

docker ps

你應該會看到類似這樣的輸出:

CONTAINER ID   IMAGE           COMMAND                  STATUS          PORTS                    NAMES
abcd1234       my-django-app   "python3 manage.py ..." Up 5 minutes    0.0.0.0:8000->8000/tcp   determined_torvalds

這表示容器已經成功運行,並且 8000 端口已經對外開放。


測試應用程式

現在你的 Django 應用應該已經在 Docker 容器內運行了,讓我們來測試看看。

方式 1:使用瀏覽器

  1. 打開瀏覽器,輸入: http://localhost:8000
  2. 如果 Django 成功啟動,你應該會看到 Django 的歡迎畫面或你的應用首頁。

方式 2:使用 cURL 測試

如果你的應用程式是 API,可以執行:

curl http://localhost:8000

如果返回了 HTML 或 JSON 內容,代表應用成功啟動。

停止與刪除容器

如果你想停止目前運行中的容器,可以執行:

docker ps

找到對應的 CONTAINER ID,然後執行:

docker stop <CONTAINER_ID>

例如:

docker stop abcd1234

如果你想刪除這個容器(停止後才能刪除),執行:

docker rm <CONTAINER_ID>

例如:

docker rm abcd1234

使用 Docker Compose 啟動 Django

如果你的 Django 應用程式還需要資料庫(如 PostgreSQL、MySQL),你可能會需要 docker-compose.yml 來管理多個容器。這時候可以用:

docker-compose up -d

這樣就可以同時啟動 Django 伺服器和資料庫,讓你的應用更完整!


總結

這篇文章解析了 Dockerfile 的基本概念,並透過一個 Django 應用的 Dockerfile 來說明各個指令的作用。我們學到了:

  • FROM 指定基礎映像
  • ENV 設定環境變數
  • RUN 執行指令(安裝套件等)
  • WORKDIR 設定工作目錄
  • COPY 複製檔案到容器
  • CMD 設定預設啟動指令

透過 Dockerfile,我們能快速建立一致的開發與部署環境,讓應用程式更容易維護和擴展。

如果你是 Docker 初學者,建議你親自動手試試這個 Dockerfile,會對 Docker 的運作方式有更深刻的理解! 🚀

Similar Posts