初學者指南:什麼是 Dockerfile?—— 以實際範例解析
更新日期: 2025 年 3 月 5 日
本文為 Docker 進階介紹 系列文,第 6 篇:
- 初學者指南:深入了解 WSL 2(Windows Subsystem for Linux 2)
- 虛擬機器(VM)是什麼?完整入門指南
- 什麼是核心(Kernel)?初學者完整指南
- Docker vs. 虛擬機器(VM):初學者完整比較指南
- 如何在 WSL 2 + Docker 環境中開發 Django:安裝順序與最佳實踐
- 初學者指南:什麼是 Dockerfile?—— 以實際範例解析 👈進度
- Docker Compose 初學者指南:使用範例解析
- Docker Compose:up vs up -d 的差異與應用
- Linux 常見指令入門:從 sudo 到日常操作
- Linux 解決方案:VSCode 無法儲存檔案權限問題
閱讀本文前,建議先理解 Docker 基本介紹系列文 相關概念。
如果你剛開始學習 Docker,可能會聽到「Dockerfile」這個詞。
簡單來說,Dockerfile
是用來建立 Docker 映像檔(Image)的腳本,它定義了如何建構一個容器環境,使得應用程式能夠在任何環境中保持一致地運行。
本文將以一個 Dockerfile
實際範例來說明它的各個指令,並幫助初學者了解 Dockerfile
的運作方式。
Dockerfile 是什麼?
想像一下,你要在一台新的電腦上安裝一個應用程式,比如 Django 網站,你通常會做什麼?
你可能需要:
- 安裝作業系統(例如 Ubuntu)
- 設定時區、環境變數
- 安裝 Python、Django 和其他必需的工具
- 把你的應用程式的程式碼放到對應的目錄
- 安裝應用程式所需的套件
- 最後,啟動 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 知道該做哪些事情,例如:
- 基礎映像(Base Image):要用什麼作業系統?(如 Ubuntu、Alpine、Debian)
- 執行環境設定:設定時區、環境變數
- 安裝必要套件:Python、Django、資料庫等
- 設定工作目錄:告訴 Docker 哪裡是應用程式的「家」
- 複製應用程式檔案:把你的專案程式碼放進 Docker 裡
- 安裝應用程式的套件:透過 pip 安裝
requirements.txt
內的套件 - 執行應用程式的指令:告訴 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.04
、alpine:latest
、python:3.9
等。 - 選擇適當的映像可以減少我們需要手動安裝的套件,讓開發更輕鬆。
設定環境變數
ENV TZ=Asia/Taipei
RUN apt update && apt install -y tzdata
🔹 ENV 指令
ENV TZ=Asia/Taipei
ENV
指令用來設定環境變數,在這裡我們設定TZ
為Asia/Taipei
,確保時區正確。- 這樣做可以避免 Docker 在安裝
tzdata
時出現手動選擇時區的交互操作。
🔹 RUN 指令
RUN apt update && apt install -y tzdata
RUN
指令執行 Linux 指令,在這裡用來安裝tzdata
(時區套件)。apt update
:更新apt
軟體套件庫,確保我們安裝的是最新版本的套件。apt install -y tzdata
:自動安裝tzdata
,-y
參數代表自動同意安裝。
📌 這樣做的好處:
- 避免安裝
tzdata
時需要手動選擇時區,提升自動化程度。 - 確保容器內的時間與主機同步,對於需要時間資訊的應用(如 Django log)非常重要。
補充:APT 軟體套件庫是什麼?
什麼是 APT?
APT(Advanced Package Tool)是 Debian 和 Ubuntu 等 Linux 系統用來管理軟體套件的工具。它負責:
- 下載 軟體
- 安裝 軟體
- 更新 軟體
- 移除 軟體
在 Linux 中,我們不需要像 Windows 一樣手動去官網下載
.exe
檔案來安裝軟體,而是透過 APT 來自動處理這些事情。例如:sudo apt install python3
這行指令會幫你下載並安裝
python3
,而且還會自動處理所有它需要的其他依賴套件(dependencies)。那「APT 軟體套件庫」是什麼?
APT 軟體套件庫(APT Package Repository)是一個 儲存軟體的雲端伺服器,APT 會從這裡下載所需的軟體。
可以把它想像成:
- App Store 或 Google 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
,可能會遇到:
- 安裝到舊版本的軟體,因為系統還在用舊的索引檔案。
- 找不到軟體,因為新的軟體可能已經更新了,但系統不知道。
所以,良好的習慣是在安裝軟體前,先執行:
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
指令用來指定容器內的工作目錄。- 這行指令表示之後所有的指令(如
COPY
、RUN
、CMD
)都會在/app
這個目錄內執行。 - 這樣可以讓檔案的組織更清楚,避免散落在容器內的不同目錄。
📌 為什麼要設定 WORKDIR
?
- 讓開發者知道應用程式的根目錄在哪裡。
- 確保
COPY
和RUN
指令執行時在正確的目錄內,避免找不到檔案的問題。
複製應用程式到容器
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
,並根據其中的指令來建立映像。
執行後會發生什麼?
- Docker 會讀取
Dockerfile
,並依照其中的指令 一步步 建立映像檔:- 下載 Ubuntu 20.04 基礎映像
- 安裝 Python 3、pip 等工具
- 設定時區
- 複製應用程式到容器
- 安裝
requirements.txt
中的 Python 套件
- 當這些步驟完成後,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 伺服器是有在運行的,只是我們的本機無法連線。
執行後會發生什麼?
- Docker 會根據
my-django-app
映像檔來建立一個新的容器。 - 容器會執行
CMD ["python3", "manage.py", "runserver", "0.0.0.0:8000"]
,啟動 Django 伺服器。 - 因為我們使用了
-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:使用瀏覽器
- 打開瀏覽器,輸入:
http://localhost:8000
- 如果 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 的運作方式有更深刻的理解! 🚀