最強教學!用Dockerfile打造專屬Ubuntu環境-從入門到Python實戰一次學會

目次

1. 前言

什麼是Docker和Dockerfile?

近年來,作為提升開發環境建置和應用程式部署效率的方法,Docker迅速普及。Docker能將應用程式及其相依環境封裝為單一「容器」,具備「隨處可運行、環境一致」的特性。

建立Docker容器時,需要一份稱為Dockerfile的藍圖。Dockerfile是一種用來描述基礎OS映像、安裝軟體與設定環境變數的純文字文件。開發者可藉由撰寫此檔案,自動化建立客製化的開發環境。

選擇Ubuntu作為基礎映像的理由

撰寫Dockerfile時,首先需指定基礎OS映像,其中最受歡迎的就是Ubuntu。Ubuntu是基於Debian的Linux發行版,以易用性和豐富的套件資源著稱,能靈活打造所需開發環境。

以Ubuntu為基礎的Dockerfile具有以下優勢:

  • 擁有大量官方及社群文件,學習門檻低
  • 絕大多數套件與工具可經APT輕鬆安裝
  • 官方提供輕量化Minimal映像(如ubuntu:20.04ubuntu: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為基礎,安裝curlvim兩個常用工具,並以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時建議利用virtualenvvenv建立虛擬環境,以防套件衝突。
  • 安裝套件時搭配--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 .

容器指令未執行或立即結束

原因:

  • CMDENTRYPOINT設定有誤
  • 若指定["/bin/bash"]但未進入互動模式,容器會立即結束

解決方法:

  • 可用下列方式啟動容器進行除錯:
  docker run -it my-image /bin/bash
  • 理解CMDENTRYPOINT差異,並依需求正確設定

這些常見錯誤經驗將幫助您大幅提升Dockerfile設計能力。遇到問題時,務必細讀錯誤訊息,逐層檢查指令與環境設定。

7. 總結

重點回顧:如何打造Ubuntu基礎的Dockerfile

本文從基礎到進階,分步說明如何利用Dockerfile建置Ubuntu環境。最後,重點整理如下:

  • 理解Dockerfile基本結構是首要步驟
    可組合FROMRUNCMDENV等指令,自動化建構開發環境。
  • Ubuntu作為基礎映像具有高穩定性與靈活性
    套件豐富、用戶基礎廣大,LTS版本尤其適合作為開發平台。
  • 實用的套件管理讓必要工具和函式庫一鍵安裝
    apt-get的使用訣竅、快取刪除與非互動安裝方式都很重要。
  • Python等進階應用環境建置也能藉由Dockerfile實現
    pyenvpiprequirements.txt等工具有助於再現性高的專案環境。
  • 面對問題的解決能力直接影響開發效率
    如權限、網路、快取等疑難點,事前理解更能避免踩雷。

學習Dockerfile的下一步

熟練Dockerfile後,不僅能加速開發,也方便測試與上線部署。建議可進一步學習:

  • Docker Compose:管理多容器協作
  • CI/CD工具(GitHub Actions、GitLab CI等):自動化開發流程
  • Kubernetes等容器編排平台:大規模運維與自動化部署

官方文件・參考資源

8. FAQ(常見問題)

Q1. Dockerfile中該選哪個Ubuntu版本?

A1. 若重視穩定與長期支援,建議選LTS(Long Term Support)版,如ubuntu:22.04ubuntu: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中的CMDENTRYPOINT有什麼不同?

A4. 兩者都是指定容器啟動時要執行的指令,但用法與行為略有差異:

項目CMDENTRYPOINT
是否可被覆寫可由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可強制重新建構、確保所有變更都被反映。