目錄

Docker 是由 Docker 推出的開放原始碼容器平台,目的在於簡化應用程式的開發、交付與部署流程。
透過「容器化(Containerization)」技術,Docker 能將應用程式與其所有相依套件封裝成可重複執行的單位,確保在任何環境中都能維持一致行為。
對於現代開發與維運(DevOps)團隊而言,Docker 幾乎已成為標準基礎工具。
什麼是容器化(Containerization)?
容器化(Containerization)是一種作業系統層級的虛擬化技術,用來將應用程式與其執行所需的所有元件(包含程式碼、系統函式庫、相依套件與設定檔)一併封裝成獨立的執行單位,稱為「容器(Container)」。
與傳統虛擬機不同,容器不需要為每個應用程式建立完整的作業系統,而是共用主機的核心(Kernel)。這使得容器在啟動速度、資源使用效率與部署彈性上,都遠優於虛擬機架構。
透過容器化,應用程式可以在本機、測試環境、雲端伺服器甚至不同作業系統平台上,以幾乎完全一致的方式執行,有效解決「在我電腦可以跑,但在伺服器不行」的常見問題。
因此,容器化已成為現代軟體開發、微服務架構與雲端部署中的關鍵技術之一。

容器與虛擬機(VM)的差異重點
容器(Container)與虛擬機(Virtual Machine, VM)都能提供應用程式的隔離執行環境,但兩者在架構設計與資源使用方式上有本質上的不同。
虛擬機透過 Hypervisor 在實體硬體上建立多個完整的作業系統,每一個 VM 都包含自己的作業系統核心(Kernel),因此在啟動時間、記憶體與儲存空間使用上,成本相對較高。
相較之下,容器是建立在主機作業系統之上,共用同一個 OS Kernel,只隔離應用程式所需的使用者空間。這使得容器在啟動速度、資源效率與部署彈性上明顯優於虛擬機,特別適合微服務與雲端原生架構。
簡單來說,虛擬機更接近「完整電腦的模擬」,而容器則是「為應用程式量身打造的執行環境」。
項目 | 容器(Container) | 虛擬機(VM) |
|---|---|---|
核心 | 共用主機 OS Kernel | 每台都有完整 Guest OS |
啟動速度 | 秒級 | 分鐘級 |
資源使用 | 極低 | 較高 |
可攜性 | 非常高 | 中等 |
適用情境 | 微服務、CI/CD、雲端部署 | 傳統企業系統 |
容器化的核心特性(Containerization Key Characteristics)
容器化之所以成為現代軟體開發與雲端部署的主流技術,關鍵在於它同時解決了環境一致性、資源效率與部署彈性三個長期存在的問題。以下是容器化最重要的幾項核心特性。
環境一致性(Environment Consistency)
容器將應用程式與其所有相依元件(程式碼、系統函式庫、套件版本、設定檔)一併封裝,確保應用程式在不同環境中皆以相同方式執行。
這代表:
- 開發環境、測試環境與正式環境行為一致。
- 不再因為作業系統、套件版本不同而產生問題。
- 有效解決「在我電腦可以跑,但在伺服器不行」的情況。
對團隊協作與長期維運而言,這種一致性大幅降低了部署風險。
高效率與輕量化(Lightweight & Efficient)
與虛擬機不同,容器不需要為每個應用程式建立完整的作業系統,而是共用主機的 OS Kernel,只隔離使用者空間。
因此容器具備以下優勢:
- 啟動速度快(通常為秒級)
- 記憶體與 CPU 使用效率高
- 同一台主機可承載更多應用實例
這讓容器特別適合高密度部署與雲端環境。
快速部署與彈性擴充(Fast Deployment & Scalability)
由於容器本身就是可重複建立的標準化單位,應用程式可以:
- 快速啟動或銷毀
- 依流量需求即時擴充或縮減
- 與自動化部署(CI/CD)流程高度整合
這種彈性使容器化成為微服務架構與雲端原生(Cloud-Native)應用的核心基礎。
良好的隔離性(Process Isolation)
每個容器都擁有獨立的檔案系統、網路設定與環境變數,即使在同一台主機上執行,也能有效避免:
- 應用程式彼此干擾
- 套件版本衝突
- 設定檔相互影響
這種隔離機制在不犧牲效能的情況下,提供了足夠的安全性與穩定性。
高可攜性(Portability)
只要目標環境支援容器執行(例如 Linux 伺服器、雲端平台或本機環境),同一個容器就能直接執行,無需額外調整。
這讓應用程式能輕鬆在:
- 本機
- 測試環境
- 雲端或實體伺服器
之間移動,大幅提升部署彈性。
為什麼現代應用選擇容器化?
隨著應用程式架構逐漸從單體系統(Monolithic)轉向微服務(Microservices)與雲端原生(Cloud-Native),傳統以作業系統或虛擬機為單位的部署方式,已難以滿足現代系統對彈性、速度與可擴充性的需求。
容器化提供了一種更符合現代應用特性的解決方案。透過將每個服務封裝為獨立容器,應用程式可以被快速部署、獨立更新,並依實際流量需求進行彈性擴充,避免整個系統因單一元件變更而必須全面重啟或重新部署。
此外,現代應用往往需要頻繁更新、快速測試與持續交付(CI/CD)。容器的標準化與可重現特性,使自動化部署流程更容易實作,並顯著降低人為操作錯誤的風險。
對於需要跨環境、跨雲甚至混合雲部署的應用而言,容器化也能有效降低平台差異所帶來的複雜度,讓應用本身不再綁定特定基礎架構。
因此,容器化不只是技術選擇,而是現代應用在速度、穩定性與可維運性之間取得平衡的關鍵架構。
現代應用選擇容器化的關鍵原因
現代軟體架構的演進,並非單一技術選擇的結果,而是來自應用規模、開發速度與營運需求同步提升所帶來的必然轉變。以下是現代應用普遍採用容器化的核心原因。
1. 微服務與雲端原生架構成為主流
傳統單體式(Monolithic)應用將所有功能整合在同一個系統中,只要其中一個模組需要更新,往往就必須重新部署整個應用,風險高、速度慢。
現代應用則傾向採用 微服務(Microservices) 架構,將不同功能拆分為多個獨立服務,各自開發、部署與擴充。
容器化正好符合這種架構需求,因為:
每個微服務都能獨立封裝成一個容器
服務之間彼此隔離,降低相互影響
可針對單一服務進行更新,而不影響整體系統
這也是為什麼雲端原生(Cloud-Native)架構幾乎都以容器作為基礎單位。
2. 需要快速部署與彈性擴充
現代應用往往面臨流量快速變化的情境,例如活動期間、尖峰使用時段或突發需求。
在這樣的環境下,部署速度與擴充能力成為關鍵指標。
由於容器啟動速度快、資源使用效率高,系統可以:
在短時間內啟動多個服務實例
依實際流量需求動態擴充或縮減
避免長時間佈署與資源閒置
相較於虛擬機,容器更適合用於需要頻繁調整規模的應用場景,這也是現代高流量服務普遍採用容器化的原因之一。
3. CI/CD 與自動化維運需求提高
隨著軟體開發節奏加快,企業不再以「半年一次」為更新單位,而是追求持續整合(CI)與持續交付(CD)。
容器化為自動化流程帶來以下優勢:
容器映像檔可作為標準化交付成果
測試、預備與正式環境使用相同映像
自動化部署流程更容易重現與回溯
這讓開發、測試與維運團隊能在同一套標準下協作,大幅降低人為操作錯誤與環境差異風險。
4. 應用需跨環境、跨平台部署
現代應用很少只運行在單一環境,實際情況通常包含:
開發人員本機
測試與預備環境
雲端或實體正式環境
甚至跨雲或混合雲部署
容器化讓應用不再依賴特定作業系統或基礎架構,只要目標環境支援容器執行,應用就能以相同方式運作。
這種高度可攜性,使容器成為跨平台與多環境部署的理想選擇,也大幅降低系統遷移與擴展的複雜度。
為什麼要使用 Docker?
雖然容器化是一種通用技術概念,但在實務應用中,Docker 之所以成為事實標準,關鍵在於它提供了一套完整、成熟且高度一致的工具鏈,讓容器化能真正被廣泛採用。
Docker 不僅定義了容器的封裝格式,也整合了映像檔管理、容器執行、網路與儲存等核心功能,使開發人員與維運團隊能用相同的方式,在本機、測試環境與正式環境中部署應用程式。
換言之,Docker 將原本複雜且零散的容器技術,轉化為一個容易學習、容易操作、容易自動化的標準流程,這正是它被廣泛使用的根本原因。
解決環境不一致問題(Why Docker Fixes “It Works on My Machine”)
在實務開發與部署中,最常見、也最難追的問題之一,就是所謂的 「在我電腦可以跑(It works on my machine)」。這類問題通常不是程式碼本身錯,而是因為執行環境不一致,導致在不同機器或不同階段(開發/測試/正式)出現不同結果。
Docker 能有效解決這個痛點,原因在於它把「環境」變成可版本控制、可重現、可移動的交付成果。
環境不一致通常來自哪些差異?
即使是看似小的差異,都可能造成行為不同或直接無法啟動,例如:
- 作業系統差異:Ubuntu vs Debian vs AlmaLinux,核心版本或預設設定不同
- 語言/Runtime 版本不同:Node 18 vs 20、Python 3.9 vs 3.11、PHP 8.1 vs 8.3
- 系統函式庫與依賴差異:OpenSSL、glibc、libstdc++ 版本不同
- 套件管理器狀態:套件來源、鏡像站、cache 狀態不同
- 環境變數與設定檔差異:
.env、config、feature flags 在不同環境配置不同 外部服務差異:資料庫版本、Redis 設定、時區、編碼(UTF-8 / collation)等
這些差異在傳統部署流程中往往”靠人記、靠文件抄”,很容易失真。
Docker 如何用 映像檔(Image) 把環境標準化?
Docker 的核心做法是:把應用程式與相依環境封裝成 Image。
Image 由 Dockerfile 定義,包含:
- 基底系統(例如
ubuntu:22.04、python:3.11-slim) - 依賴套件安裝方式(apt/pip/npm 等)
- 設定檔、環境變數、工作目錄
啟動命令(CMD / ENTRYPOINT)
一旦 Image 建好,它就成為一個可重現的標準執行環境:
同一個 Image 在任何有 Docker 的地方啟動出來的 Container,行為就會高度一致。
你可以把 Image 想像成「可攜式的執行環境快照」,而不是「手動安裝教學」。
Docker 的一致性帶來哪些實際效益?
開發與部署流程更可靠
開發者在本機驗證通過的 Image,可以直接推送到測試/正式環境使用,減少「交付後才爆炸」。團隊協作成本降低
新同事不用花半天裝環境,只要docker compose up就能跑起來,降低 onboarding 成本。更容易 Debug 與回溯
當某次版本出問題,你可以鎖定是哪個 Image tag(例如v1.2.3)造成,快速回滾。CI/CD 更容易標準化
CI 建出 Image、跑測試、通過後推 registry,再由 CD 拉同一個 Image 部署,流程一致、可追溯。
常見的實例
假設你是 Python 專案:
- 開發者 A 用 Python 3.1
- 正式環境仍是 Python 3.
- 某些套件在 3.9/3.11 行為不同,導致上線後才出現錯誤
用 Docker 後,你會在 Dockerfile 明確固定 runtime:
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]
結果是:
開發、測試、正式環境都跑同一個 Python 3.11 + 同一份依賴,環境差異造成的風險大幅下降。
實務最佳做法(避免看似 Docker 了,還是不一致)
要讓 Docker 真正解決環境不一致,建議做到:
- 固定版本:image tag 盡量不要只用
latest,改用明確版本(如python:3.11.6-slim) - 鎖依賴:npm/pip 使用 lockfile(
package-lock.json、poetry.lock、requirements.txt固定版本) - 一致化設定:用
.env或環境變數管理設定,避免手動改 config - 用 Compose 管多服務:DB、Redis、App 都用同一份
docker-compose.yml定義,減少外部差異 - 把時區/locale 明確化:避免時間、排序、字串比較在不同環境行為不同
提升開發與部署效率(Faster Development & Deployment)
Docker 之所以在現代開發流程中被大量採用,不只因為它能解決環境不一致,更重要的是它能把「建環境、部署、更新」這些原本耗時且容易出錯的工作,轉化為可自動化、可重複、可版本化的流程,進而顯著提升開發與部署效率。
在沒有 Docker 的情況下,團隊往往需要花大量時間處理:
- 新成員加入要安裝一堆 runtime、套件與服務
- 測試環境與正式環境的配置靠文件手動同步
- 每次部署都要重做相同流程,且很難保證一致
- 多服務依賴(DB、Redis、Queue)需要人工啟停與連線設定
Docker 將上述流程「工具化」與「標準化」,讓效率差距在團隊規模變大時會更明顯。
Docker 如何讓開發更快?(Dev Experience)
1. 一鍵啟動整套開發環境(Local Dev)
傳統做法常見痛點是:本機要裝資料庫、快取、訊息隊列、特定版本 runtime。
Docker 搭配 Docker Compose 後,開發者只要一個指令就能啟動整個 stack:
docker compose up -d
這說明:
- 新人 Onboarding 從半天~兩天 縮短為 數分鐘
- 每個人本機環境一致,bug 重現成本大幅下降
- 測試案例與依賴服務更容易被固定與重現
2. 依賴服務(DB/Redis)不再是「外部變因」
開發最常見的效率黑洞是:
「我本機 DB 版本不一樣 / Redis 沒開 / queue 沒起來」
用 Compose 把依賴服務寫死後,整個團隊會得到:
- 固定的版本(例如
postgres:15、redis:alpine) - 固定的連線名稱(service name 當 DNS)
- 固定的資料持久化方式(volume)
Docker 如何讓部署更快?(Release & Delivery)
1. 部署單位從「伺服器設定」變成「映像檔版本」
傳統部署的核心工作是「把伺服器調到能跑」。
Docker 部署的核心工作是「拉一個已驗證過的 image 來跑」。
也就是:
- CI 建出 image → 跑測試
- 測試通過 → 推送到 registry
- 正式環境拉同一個 image → 啟動容器
這個流程的關鍵價值是:
測試跑的是什麼,正式就跑什麼,部署風險顯著降低。
2. 更新與回滾更容易(Rollback-friendly)
當你用版本化 image(例如 myapp:1.2.3)部署,回滾就不再是「重配環境」,而是:
- 把服務切回上一個 image tag
- 或切回上一版 Compose/Stack 配置
這讓事故處理(Incident Response)速度更快,平均修復時間(MTTR)通常能顯著下降。
最直觀的實例:Compose 管理多服務
以下是典型 Web 應用的 Compose 結構:Web + DB + Redis。
你可以把它當成示意範例放文內(不需要完全一模一樣):
services:
web:
build: .
ports:
- "8000:8000"
environment:
DATABASE_URL: postgres://myuser:mypassword@db:5432/mydb
REDIS_HOST: redis
depends_on:
- db
- redis
db:
image: postgres:15
environment:
POSTGRES_USER: myuser
POSTGRES_PASSWORD: mypassword
POSTGRES_DB: mydb
volumes:
- db-data:/var/lib/postgresql/data
redis:
image: redis:alpine
volumes:
db-data:
對應常用操作:
docker compose up -d # 啟動全部服務
docker compose ps # 查看狀態
docker compose logs -f web # 追 web logs
docker compose down # 停止並移除容器(保留 volume)
這種寫法帶來的效率提升是:
- 環境可複製:任何人、任何機器都能啟動同一套
- 服務可追蹤:依賴關係、port、volume 一目了然
- 部署可自動化:能直接接到 CI/CD pipeline
實務最佳做法(避免「Docker 也拖慢」)
要讓 Docker 真正提升效率,建議遵守這些要點:
- 善用快取與 layer 設計:把「變動少」的步驟放前面(例如先 COPY lockfile 再 install)
- 用明確版本 tag:避免
latest導致不可預期更新 - 拆分 dev/prod 設定:開發用 bind mount,正式用 immutable image
- 把敏感設定外部化:用
.env或 secret 管理,避免寫死在 image - 標準化啟動方式:團隊統一用
docker compose up -d/down/logs
1. 不要只用 latest,用明確版本
✅
postgres:15❌
postgres:latest
原因:latest 會讓你「某天突然被升級」,結果不可預期。
2. Dockerfile 讓快取有效(build 速度差很多)
把「變動少」的步驟放前面,例如先 copy lockfile 再 install:
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
3. 開發與正式環境分離
Dev:可以 bind mount(方便即時改碼)
Prod:用 immutable image(確保一致、可回溯)
4. 設定外部化(.env / secrets)
不要把密碼寫死在 image 或 repo;用 .env 或 secret 管理。
5. Volume 做好資料持久化
DB/有狀態服務一定要有 volume,否則容器刪了資料就沒了。
常見誤區(會讓你覺得 Docker 沒比較快)
把所有東西都塞進同一個超大 image → build 慢、pull 慢
沒鎖版本 → 今天能跑明天壞掉
Dockerfile layer 設計不當 → 每次改一行都重新裝依賴
正式環境仍在「ssh 上去手動改」→ 失去 Docker 的一致性價值
5 分鐘快速體驗 Docker 與 Docker Compose(實作示範)
以下是一個最小可運行範例,目標是在 5 分鐘內,讓讀者實際體驗 Docker 如何快速建立、啟動並管理一個應用服務。
實作目標
建立一個簡單 Web 服務
使用 Dockerfile 建立 Image
使用 Docker Compose 一鍵啟動服務
查看 logs、停止並清理環境
Step 1:建立專案目錄
mkdir docker-demo
cd docker-demo
Step 2:建立最小應用程式(以 Python 為例)
建立一個 app.py:
from http.server import BaseHTTPRequestHandler, HTTPServer
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.end_headers()
self.wfile.write(b"Hello from Docker!")
if __name__ == "__main__":
server = HTTPServer(("0.0.0.0", 8000), Handler)
server.serve_forever()
這是一個最簡單的 HTTP 服務,監聽在 8000 port。
Step 3:建立 Dockerfile
在同一個目錄建立 Dockerfile:
FROM python:3.11-slim
WORKDIR /app
COPY app.py .
EXPOSE 8000
CMD ["python", "app.py"]
這個 Dockerfile 做了幾件事:
- 使用固定版本的 Python 環境
- 複製程式碼進容器
- 定義容器啟動時要執行的程式
Step 4:建立 Docker Compose 設定檔
建立 docker-compose.yml:
services:
web:
build: .
ports:
- "8000:8000"
這代表:
- 用目前目錄的 Dockerfile 建立 image
- 把容器的 8000 port 對外開放
Step 5:一鍵啟動服務
在專案目錄執行:
docker compose up -d
看到類似輸出代表啟動成功。
接著打開瀏覽器,進入:
http://localhost:8000
你應該會看到:
Hello from Docker!
#你已經成功用 Docker 跑起一個服務了
Step 6:查看執行狀態與 logs
docker compose ps
docker compose logs -f
這讓你可以:
- 確認容器是否正在運行
- 即時查看服務輸出(debug 非常重要)
Step 7:停止並清理環境
docker compose down
這會:
- 停止容器
- 移除容器
- 保留 image(下次啟動更快)
這個 5 分鐘實作示範在教學上的意義
這個範例清楚示範了 Docker 的核心價值:
- 環境可複製:任何裝有 Docker 的電腦都能跑
- 啟動快:不用手動裝 Python、設定 Port
- 流程一致:開發與部署步驟相同
- 可立即擴展:之後只要加 DB / Redis 即可變成完整應用
對新手來說,這能快速建立「Docker 在做什麼」的直覺
適合微服務與雲端架構(Microservices & Cloud-Native Ready)
在現代系統設計中,「微服務(Microservices)」與「雲端原生(Cloud-Native)」的核心目標,是把應用拆成更小、更可獨立管理的單元,並能在需求變動時快速擴縮、快速更新、快速回復。Docker 之所以在這類架構中成為事實標準,關鍵在於它提供了標準化的封裝格式(Image)與可重現的執行單位(Container),讓服務能以一致方式交付與運行。
微服務為什麼天然適合容器?
微服務架構通常具備以下特徵:
- 每個服務有自己的程式碼、相依套件與部署節奏
- 服務之間透過 API 互相溝通
- 不同服務可能使用不同語言或 runtime(例如 Node + Python + Go)
- 需要獨立擴充(例如只有支付服務流量暴增)
容器正好對應這些需求,因為每個容器都可以:
- 搭載不同 runtime 與相依套件(避免版本衝突)
- 以獨立進程運行並具備隔離性(減少互相干擾)
- 以單一服務為單位部署、更新、回滾(降低變更風險)
換言之,微服務要的是「可拆、可管、可替換」,容器提供的正是「可封裝、可部署、可替換」。
雲端原生(Cloud-Native)在追求什麼?Docker 如何支撐?
雲端原生並不只是「把服務搬到雲上」,而是讓系統具備以下能力:
- 彈性擴縮(Elastic Scaling):依流量快速擴充/縮減
- 高可用(High Availability):某個節點故障不影響整體服務
- 自動化交付(CI/CD):快速且可追溯的版本發佈
- 可觀測性(Observability):容易監控、追蹤、排錯
Docker 的貢獻在於:它把「交付物」變成標準的 Image。
只要你把服務打包成 Image,你就能更容易地在各種雲端環境中:
- 重複部署同一版本
- 做滾動更新與快速回滾
- 搭配監控與日誌系統(logs/metrics/traces)做可觀測性整合
為什麼 Docker 能讓「擴充」與「更新」變得更可靠?
在微服務/雲端架構中,擴充與更新往往是日常。Docker 讓這些行為更可靠的原因是:
- 擴充:新增更多「相同 Image」的容器實例即可
- 更新:用新 tag 的 image 逐步替換舊的容器實例(rolling update)
- 回滾:切回前一版 image tag,避免長時間修復
這比起傳統「在伺服器上就地升級」更安全,因為你不是在改一台正在跑的機器,而是在用一個可控的新版本替換舊版本。
實務案例
假設你有一個典型的微服務應用:
api-gateway:對外 API 入口auth-service:登入與權限order-service:訂單處理payment-service:金流(尖峰流量最高)redis:快取postgres:資料庫
當活動期間支付流量暴增時,你不需要把整套系統都升級,你只要:
- 擴充
payment-service容器實例數 - 其他服務維持原狀
這就是微服務 + 容器的核心價值:針對瓶頸服務獨立擴充,避免整體資源浪費。
與 Kubernetes 的關係
與 Kubernetes 的關係:分工而非競爭
在容器生態系中,Docker 與 Kubernetes 經常被一起提及,但它們解決的是不同層級的問題,並非互相取代的關係。
Docker 的核心職責,是將應用程式及其相依環境封裝為標準化的容器映像檔(Image),確保應用能在任何支援容器的環境中一致執行。這個階段關注的是「如何建置與交付應用」。
Kubernetes 則是一個容器編排(Orchestration)平台,負責在多台主機組成的叢集中,自動化管理大量容器的生命週期。它關注的是「如何在規模化環境中部署、擴充、維持高可用」。
換言之:
- Docker 解決的是 Build & Package
- Kubernetes 解決的是 Deploy & Operate at Scale
Docker 在 Kubernetes 架構中的實際角色
在實務上,多數團隊的流程仍是:
- 使用 Dockerfile 建立應用映像檔
- 將映像檔推送到 Image Registry(如 Docker Hub、私有 Registry)
- 由 Kubernetes 依照設定,拉取這些映像檔並啟動容器
雖然 Kubernetes 目前不再直接使用 Docker Engine 作為底層 runtime,而是改用 containerd、CRI-O 等容器執行環境,但這並不代表 Docker 被淘汰。
重點在於:
- Kubernetes 不負責「如何寫 Dockerfile」
- Kubernetes 不負責「如何建 Image」
- Docker 所定義的 Image 格式,仍然是 Kubernetes 的主流交付標準
因此,「用 Docker 建 Image、用 Kubernetes 跑 Container」仍是業界最常見的組合。
為什麼「先學 Docker,再學 Kubernetes」是正確路線?
從學習與實務角度來看,Docker 是 Kubernetes 的基礎:
- Kubernetes 的 Pod,本質上仍是在執行一個或多個容器
- Deployment、ReplicaSet、Job 等資源,都是在管理「容器實例」
- 如果不理解 Image、Container、Port、Volume、Environment Variable,就很難正確使用 Kubernetes
因此,大多數團隊與教學都遵循以下路徑:
Docker(容器化基礎) → Docker Compose(多服務管理) → Kubernetes(大規模編排)
這不是工具選擇問題,而是系統規模與複雜度的自然演進。
什麼時候「不需要 Kubernetes」?
如果你的應用符合以下情況:
- 單機或少量節點
- 服務數量有限
- 不需要自動擴縮或複雜調度
- 團隊規模較小
那麼 Docker + Docker Compose 往往已經足夠,導入 Kubernetes 反而會增加維運成本。
Kubernetes 的價值,在於:
- 多節點叢集
- 高可用需求
- 自動擴縮
- 複雜服務拓撲
而不是「所有專案都必須用」。
Docker Compose 與 Kubernetes 對照表
Docker Compose 與 Kubernetes 的差異比較
比較項目 | Docker Compose | Kubernetes |
|---|---|---|
核心定位 | 多容器應用的本機 / 單機管理工具 | 大規模容器編排平台 |
解決的問題 | 如何在一台或少量主機上管理多個服務 | 如何在多節點叢集中自動管理大量容器 |
主要使用情境 | 開發環境、測試環境、小型正式環境 | 中大型正式環境、高可用系統 |
設定檔格式 | YAML(docker-compose.yml) | YAML(Deployment / Service / Ingress 等) |
節點數量 | 通常為單機 | 多節點(Cluster) |
自動擴縮 | ❌ 無內建 | ✅ HPA / Auto Scaling |
高可用(HA) | ❌ 需自行處理 | ✅ 原生支援 |
滾動更新 | ❌ 手動 | ✅ 原生支援 |
健康檢查與重啟 | 基本 | 進階、可策略化 |
學習曲線 | 低 | 高 |
維運複雜度 | 低 | 高 |
適合對象 | 個人 / 小團隊 / 初期產品 | 中大型團隊 / 企業系統 |
什麼情況該從 Docker Compose 升級到 Kubernetes?
什麼情況該從 Docker Compose 升級到 Kubernetes?
Docker Compose 並不是「只能用在開發環境的工具」,在許多小型或中期專案中,它已足以支撐正式環境。然而,當系統需求與規模成長到某個程度時,導入 Kubernetes 才會開始顯現實質價值。
以下是實務上常見的升級判斷指標。
適合繼續使用 Docker Compose 的情況
如果你的系統符合以下條件,不需要急著導入 Kubernetes:
- 單機或少量主機即可承載流量
- 服務數量有限(例如 3–10 個服務)
- 不需要自動擴縮
- 容忍短暫重啟或維護時間
- 團隊規模小,維運人力有限
在這種情況下,Compose 的「簡單、可控、低成本」反而是優勢。
應該考慮升級到 Kubernetes 的明確訊號
當你開始遇到以下情況時,代表 Compose 已接近極限:
1. 需要自動擴縮(Auto Scaling)
- 不同時段流量差異大
- 人工調整容器數量已不可行
Kubernetes 的 HPA 才能有效解決。
2. 需要高可用(High Availability)
- 單一節點故障不可接受
- 服務必須自動在其他節點重啟
Compose 無法處理節點層級的失效。
3. 服務數量與依賴快速成長
- 微服務數量超過 10–20 個
- 服務間關係複雜
- 需要 service discovery、內部負載平衡
Kubernetes 的 Service / Ingress 才有系統性解法。
4. 需要零停機更新(Rolling Update)
- 更新不能影響線上使用者
- 需要藍綠部署或滾動更新策略
Kubernetes 原生支援,Compose 不適合。
5. 團隊規模與權限管理需求提升
- 多團隊共用平台
- 需要 RBAC、Namespace、資源配額
這是 Kubernetes 的強項。
實務建議
不要因為「大家都用 Kubernetes」而導入 Kubernetes。
正確的做法是:
先用 Docker 與 Docker Compose 建立穩定的容器化流程,等系統真的需要「自動化管理大量容器」時,再升級到 Kubernetes。
Docker 的核心組成概念(Core Docker Concepts)
Docker 的運作可以拆成一條清楚的鏈路:你用 Dockerfile 定義環境 → 建出 Image → 以 Image 啟動 Container → 由 Docker Engine 管理 → 需要共享與交付時上傳到 Registry(例如 Docker Hub)→ 多服務用 Docker Compose 串起來。理解這個鏈路,就能快速定位問題發生在「建置、交付、執行或編排」哪一層。
Docker Engine(Docker 的執行核心)
Docker Engine 是 Docker 的核心執行環境,負責建立、啟動、停止、刪除容器,以及管理映像檔、網路與儲存等資源。
Docker Engine 的三個關鍵元件
- Docker Daemon(dockerd):常駐背景服務,真正負責容器生命週期與資源管理。
- Docker API:對外提供控制介面,CLI 或其他工具透過 API 下指令。
- Docker CLI(docker):你平常輸入的
docker ps / docker run / docker build等命令工具。
你要記住的一句話
CLI 只是「下指令」,真正做事的是 dockerd。
常用驗證方式
看 Docker 是否正常:
docker info看目前容器:
docker ps、全部容器:docker ps -a
Docker Image(映像檔:可交付的執行環境)
Image 是只讀的模板,包含:
- 基底系統(如 Debian/Alpine)
- 語言 runtime(如 Python/Node/Java)
- 你的程式碼與相依套件
- 預設啟動方式(CMD/ENTRYPOINT)
Image 的「Layer(分層)」概念
Dockerfile 每一個會產生檔案變更的指令(如 RUN/COPY/ADD)通常會形成一層 layer。Docker 會快取 layer,以加速重複建置。
優點:
- 重複建置更快(命中快取)
- 多個 image 可共享底層 layer(省空間)
常見踩雷:
- 你改了 Dockerfile 上方的步驟,下面全部 cache 失效 → build 變慢
- 依賴沒鎖版本、用
latest→ 今天能跑明天可能壞
常用命令
- 列出本機 images:
docker images - 拉取 image:
docker pull nginx:latest - 建置 image:
docker build -t myapp:1.0 .
Docker Container(容器:Image 的可執行實例)
Container 是 Image 的「執行中實例」,本質上是:
- 以 Image 為基礎
- 在其上加一層可寫層(writable layer)
- 以隔離的程序空間執行你的主程式
容器為什麼常被說「可丟棄(ephemeral)」?
容器應該被視為「可隨時重建」的執行單元:
- 應用程式本身可重建
- 資料要放在 Volume(否則容器刪掉資料就沒了)
常用命令
- 啟動容器:
docker run -d --name web nginx - 進入容器:
docker exec -it web sh - 看 logs:
docker logs -f web - 停止/刪除:
docker stop web && docker rm web
常見問題:Container 一啟動就退出
原因通常是:容器主程序結束(CMD/ENTRYPOINT 只跑完就退),或直接崩潰。
處理方式:看 logs、檢查 CMD/ENTRYPOINT、或用 docker run -it 進互動排查。
Dockerfile(建置 Image 的藍圖)
Dockerfile 是一份「可版本控制」的建置腳本,定義 image 要怎麼做出來。它的價值在於:把環境建置流程標準化、可重現化。
最重要的指令與用途(精準版)
- FROM:指定基底映像檔(例如
python:3.11-slim) - WORKDIR:設定工作目錄
- COPY/ADD:把檔案放進 image
- RUN:建置期間執行命令(例如裝套件)
- ENV:設定環境變數
- EXPOSE:宣告容器預期使用的 port(不是自動開 port)
- CMD / ENTRYPOINT:容器啟動時要跑的主程序(最重要)
兩個容易搞混的點
- EXPOSE 不等於開放對外:對外要用
-p或 Compose ports。 - CMD vs ENTRYPOINT:
ENTRYPOINT:更像「固定主程式」
CMD:更像「預設參數/預設命令」
實務上若你要允許使用者覆寫啟動命令,CMD 常更直覺。
