1. 前言
什麼是Docker和Dockerfile?
近年來,作為提升開發環境建置和應用程式部署效率的方法,Docker迅速普及。Docker能將應用程式及其相依環境封裝為單一「容器」,具備「隨處可運行、環境一致」的特性。
建立Docker容器時,需要一份稱為Dockerfile的藍圖。Dockerfile是一種用來描述基礎OS映像、安裝軟體與設定環境變數的純文字文件。開發者可藉由撰寫此檔案,自動化建立客製化的開發環境。
選擇Ubuntu作為基礎映像的理由
撰寫Dockerfile時,首先需指定基礎OS映像,其中最受歡迎的就是Ubuntu。Ubuntu是基於Debian的Linux發行版,以易用性和豐富的套件資源著稱,能靈活打造所需開發環境。
以Ubuntu為基礎的Dockerfile具有以下優勢:
- 擁有大量官方及社群文件,學習門檻低
- 絕大多數套件與工具可經APT輕鬆安裝
- 官方提供輕量化Minimal映像(如
ubuntu:20.04
、ubuntu:24.04
等)
本文目的與適合對象
本教學將以「Dockerfile Ubuntu」為主題,深入淺出說明如何打造基於Ubuntu的Dockerfile,適合初學者閱讀。
內容涵蓋Dockerfile基本結構、實際Ubuntu環境建置流程、Python等應用環境安裝範例,以及常見錯誤與解決方案,帶您一次掌握。
推薦給以下讀者:
- 首次想用Dockerfile自動建置開發環境者
- 想在Ubuntu下重現一致開發環境者
- 想學會疑難排解與進階操作者
2. Dockerfile的基本結構
什麼是Dockerfile?了解其角色
Dockerfile就像製作Docker映像的食譜,會以文字檔案形式記錄「採用何種基礎OS、安裝哪些軟體、進行哪些設定」。
根據此檔案,執行docker build
指令,即可輕鬆建立高度可重現的開發或應用運行環境。
使用Dockerfile的好處:
- 自動化建置環境(免除繁瑣手動重複)
- 多人協作時確保環境一致性
- 易於整合進CI/CD流程
Dockerfile常用基本指令(Directive)
Dockerfile包含多種指令,下列為常用指令。這些指令可彈性組合以撰寫Ubuntu基礎的Dockerfile。
指令 | 說明 |
---|---|
FROM | 指定基礎Docker映像,例如FROM ubuntu:24.04 |
RUN | 執行Shell指令,常用於安裝套件 |
COPY | 將本地檔案複製到映像中 |
ADD | 類似COPY,並支援URL下載及解壓縮 |
WORKDIR | 指定工作目錄 |
ENV | 設定環境變數 |
CMD | 定義容器啟動時預設執行的指令(可覆寫) |
ENTRYPOINT | 與CMD類似,但為強制執行的指令 |
Ubuntu基礎Dockerfile最小範例
以下為以Ubuntu為基礎的簡易Dockerfile範例:
FROM ubuntu:24.04
RUN apt-get update && apt-get install -y
curl
vim
CMD ["/bin/bash"]
本範例會以Ubuntu 24.04為基礎,安裝curl
與vim
兩個常用工具,並以bash作為預設執行命令。
如何選擇Ubuntu映像Tag
Ubuntu的Docker映像可於Docker Hub官方倉庫取得。雖然指定ubuntu:latest
即可取得最新版,但建議明確指定版本以確保一致性。
例如:
ubuntu:22.04
(LTS長期支援版,穩定性高)ubuntu:24.04
(最新LTS候選,功能較新)
可依需求選擇穩定或新功能為優先。
3. 實作:建立Ubuntu基礎的Dockerfile
在Ubuntu環境安裝所需套件
利用Dockerfile建置Ubuntu環境時,經常需要安裝額外套件。常見的開發工具有:
curl
:下載檔案或API測試vim
:輕量級文字編輯器git
:版本控制工具build-essential
:C/C++編譯必需工具包
可用RUN
指令一次安裝:
FROM ubuntu:24.04
RUN apt-get update && apt-get install -y
curl
vim
git
build-essential
先執行apt-get update
可確保抓取最新的套件清單,避免安裝時發生找不到套件的問題。
非互動式安裝設定
在Ubuntu中,apt-get install
有時會要求互動式輸入。但在Docker建置過程中,無法進行互動,因此建議加上下列環境變數,以非互動模式執行安裝:
ENV DEBIAN_FRONTEND=noninteractive
這可跳過像是地區設定等互動問題,使安裝流程更順暢。
刪除快取以精簡映像
APT安裝後會產生暫存檔,導致映像變大。建議於安裝結束後即刻清除APT快取:
RUN apt-get update && apt-get install -y
curl
vim
&& rm -rf /var/lib/apt/lists/*
同時,盡量合併多個指令到單一RUN
命令,可減少映像層數,提升建置效率。
最佳實踐:撰寫乾淨的Dockerfile
在實際開發現場,建議遵循以下Dockerfile編寫最佳實踐:
- 盡可能合併
RUN
指令,減少層數 - 利用
ENV
明確指定版本與設定 - 加註註解說明步驟用途
- 刪除不必要檔案、加上
--no-install-recommends
精簡安裝
範例:
RUN apt-get update && apt-get install -y --no-install-recommends
curl
git
&& rm -rf /var/lib/apt/lists/*
如此一來能打造出更輕量、易於維護的Dockerfile。
4. 建構與驗證Docker映像
從Dockerfile建構映像
撰寫完Dockerfile後,下一步是建構Docker映像。在Dockerfile所在目錄執行下列指令:
docker build -t my-ubuntu-image .
-t
選項為映像命名(例如my-ubuntu-image
)。.
代表目前目錄,即Dockerfile所在位置。
執行後,Docker會依照Dockerfile內容,逐步產生新的映像檔。
確認建構完成的映像
映像建構完成後,可用下列指令查看:
docker images
這會列出本機所有Docker映像及其資訊,例如:
- REPOSITORY(映像名稱)
- TAG(標籤)
- IMAGE ID(唯一ID)
- CREATED(建立時間)
- SIZE(大小)
範例輸出:
REPOSITORY TAG IMAGE ID CREATED SIZE
my-ubuntu-image latest abcd1234abcd 5 minutes ago 189MB
確認映像已正確產生。
啟動Docker容器進行驗證
為確認映像功能正常,可啟動容器進行驗證:
docker run -it my-ubuntu-image
-it
選項可進入互動式終端機。- 若成功,會進入容器內的bash環境。
可在容器內執行下列指令確認工具是否可用:
curl --version
vim --version
若顯示正確版本資訊,即代表Dockerfile設定成功。
清理不再需要的映像與容器
重複建構或測試會讓本機堆積不需要的映像與容器,建議定期清理:
- 刪除已停止容器:
docker container prune
- 刪除未使用映像:
docker image prune
- 清理所有未使用資料(謹慎操作):
docker system prune
這些步驟能有效節省硬碟空間與預防異常。
5. 進階應用:構建Python環境
在Ubuntu基礎Dockerfile中安裝Python
利用Dockerfile建置Ubuntu環境時,若能加裝Python執行環境,就能支援開發、測試、機器學習等多種需求。雖然某些Ubuntu映像預設含有Python,但為了方便版本管理與套件控管,通常會自行明確安裝。
使用APT安裝Python的方法
最簡單的作法是直接用APT安裝Python。範例如下:
FROM ubuntu:24.04
RUN apt-get update && apt-get install -y
python3
python3-pip
&& rm -rf /var/lib/apt/lists/*
此方式會安裝系統預設穩定版Python(如Python 3.10或3.12等)。搭配pip
即可額外安裝Python套件。
利用pyenv管理Python版本
若需特定版本或多版本切換,推薦用pyenv。以下為Dockerfile利用pyenv安裝Python 3.11.6的範例:
FROM ubuntu:24.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y
git
curl
make
build-essential
libssl-dev
zlib1g-dev
libbz2-dev
libreadline-dev
libsqlite3-dev
wget
llvm
libncurses5-dev
libncursesw5-dev
xz-utils
tk-dev
libffi-dev
liblzma-dev
&& rm -rf /var/lib/apt/lists/*
# 安裝pyenv
RUN git clone https://github.com/pyenv/pyenv.git ~/.pyenv
ENV PYENV_ROOT="$HOME/.pyenv"
ENV PATH="$PYENV_ROOT/bin:$PATH"
RUN echo 'eval "$(pyenv init --path)"' >> ~/.bashrc
# 安裝指定版本Python
RUN pyenv install 3.11.6 && pyenv global 3.11.6
藉由此法,可靈活自訂Python開發環境。
利用requirements.txt管理Python套件
實際專案多需安裝多個Python函式庫,可用requirements.txt
統一管理。
首先在專案根目錄準備requirements.txt
:
flask==2.3.2
requests>=2.25.1
pandas
然後於Dockerfile中:
COPY requirements.txt /app/requirements.txt
WORKDIR /app
RUN pip install --no-cache-dir -r requirements.txt
如此一來能一鍵安裝所需函式庫,提升環境一致性。
最佳實踐
- 使用Python時建議利用
virtualenv
或venv
建立虛擬環境,以防套件衝突。 - 安裝套件時搭配
--no-cache-dir
,減少映像體積。 - 建議安裝套件前先
pip install --upgrade pip
,可避免安裝時發生錯誤。
6. 常見問題與排解方式
權限(Permission)錯誤
範例:
Permission denied
此錯誤通常為複製進映像檔的檔案無執行權限,或執行用戶設定有誤所致。
解決方法:
- 給檔案執行權限:
RUN chmod +x script.sh
- 必要時變更檔案擁有者:
RUN chown root:root /path/to/file
找不到套件或安裝失敗
範例:
E: Unable to locate package xxx
這通常是未先apt-get update
或套件名稱拼錯造成。
解決方法:
- 務必於
install
前先執行apt-get update
:
RUN apt-get update && apt-get install -y curl
- 再次檢查套件名稱拼寫是否正確
網路連線相關錯誤
範例:
Temporary failure resolving 'deb.debian.org'
這表示建置過程中的DNS解析失敗。
解決方法:
- 重啟Docker daemon可排除問題:
sudo systemctl restart docker
- 調整Docker DNS設定(於
/etc/docker/daemon.json
新增DNS):
{
"dns": ["8.8.8.8", "8.8.4.4"]
}
快取導致未更新(Build Cache)
Docker會自動利用快取提升建置速度,有時會導致修改未反映。
解決方法:
- 使用下列指令強制不使用快取:
docker build --no-cache -t my-image .
容器指令未執行或立即結束
原因:
CMD
或ENTRYPOINT
設定有誤- 若指定
["/bin/bash"]
但未進入互動模式,容器會立即結束
解決方法:
- 可用下列方式啟動容器進行除錯:
docker run -it my-image /bin/bash
- 理解
CMD
與ENTRYPOINT
差異,並依需求正確設定
這些常見錯誤經驗將幫助您大幅提升Dockerfile設計能力。遇到問題時,務必細讀錯誤訊息,逐層檢查指令與環境設定。
7. 總結
重點回顧:如何打造Ubuntu基礎的Dockerfile
本文從基礎到進階,分步說明如何利用Dockerfile建置Ubuntu環境。最後,重點整理如下:
- 理解Dockerfile基本結構是首要步驟
可組合FROM
、RUN
、CMD
、ENV
等指令,自動化建構開發環境。 - Ubuntu作為基礎映像具有高穩定性與靈活性
套件豐富、用戶基礎廣大,LTS版本尤其適合作為開發平台。 - 實用的套件管理讓必要工具和函式庫一鍵安裝
apt-get
的使用訣竅、快取刪除與非互動安裝方式都很重要。 - Python等進階應用環境建置也能藉由Dockerfile實現
pyenv
、pip
、requirements.txt
等工具有助於再現性高的專案環境。 - 面對問題的解決能力直接影響開發效率
如權限、網路、快取等疑難點,事前理解更能避免踩雷。
學習Dockerfile的下一步
熟練Dockerfile後,不僅能加速開發,也方便測試與上線部署。建議可進一步學習:
- Docker Compose:管理多容器協作
- CI/CD工具(GitHub Actions、GitLab CI等):自動化開發流程
- Kubernetes等容器編排平台:大規模運維與自動化部署
官方文件・參考資源
8. FAQ(常見問題)
Q1. Dockerfile中該選哪個Ubuntu版本?
A1. 若重視穩定與長期支援,建議選LTS(Long Term Support)版,如ubuntu:22.04
或ubuntu:20.04
,這類版本多數開發現場採用,並提供5年安全更新。
若需最新軟體版本,也可選ubuntu:24.04
等較新版本,但請事先測試兼容性。
Q2. apt-get install
出現「找不到套件」怎麼辦?
A2. 最常見原因是沒有先執行apt-get update
,導致套件清單未更新,或拼錯套件名稱。
正確範例:
RUN apt-get update && apt-get install -y curl
同時注意是否用錯名稱(如python
已不推薦,應用python3
)。
Q3. Dockerfile要如何設定環境變數?
A3. 可利用ENV
指令設定,於建置與執行階段均有效。
範例:
ENV DEBIAN_FRONTEND=noninteractive
這常用於壓制APT安裝過程中的互動提示,也可設定API金鑰或應用相關環境變數。
Q4. Dockerfile中的CMD
和ENTRYPOINT
有什麼不同?
A4. 兩者都是指定容器啟動時要執行的指令,但用法與行為略有差異:
項目 | CMD | ENTRYPOINT |
---|---|---|
是否可被覆寫 | 可由docker run 時的指令覆蓋 | 一般不會被覆寫(僅可當引數傳遞) |
主要用途 | 設定預設執行指令 | 強制執行特定指令 |
範例:
CMD ["python3", "app.py"]
# vs
ENTRYPOINT ["python3"]
CMD ["app.py"]
第二種寫法下,可用docker run my-image another_script.py
來指定執行其他腳本。
Q5. 修改Dockerfile後卻未見變化,為什麼?
A5. Docker建置時預設會用快取機制,若僅有細微變動,可能還是採用舊快取層。
解決方法:
docker build --no-cache -t my-image .
加上--no-cache
可強制重新建構、確保所有變更都被反映。