Learning Objectives
- 說明應用程式開發與部署方式的轉變:從單體程式到微服務、從實體機到雲端
- 比較虛擬機(Hypervisor)與容器(共用核心)的架構差異與各自的優缺點
- 說明 Docker 是什麼:把程式碼和執行環境一起裝箱
- 初步分辨映像檔(image)與容器(container)
「在我電腦上可以跑啊!」
你可能遇過這種情況:自己電腦上跑得好好的作業,交給助教或同組同學卻跑不起來。 原因通常不是程式本身,而是環境不同:
- Python 版本不一樣(3.12 和 3.9 的語法、套件支援不同)
- 少裝了某個套件,或套件版本不同
- 作業系統不同(Windows 的路徑分隔是
\,Linux 是/) - 缺少系統層級的函式庫或設定檔
寫給自己用的小程式還好;一旦程式要放到伺服器上給很多人用,這個問題就會被放大。 Docker 的想法很直接:既然問題出在環境,那就把程式碼和它需要的整個環境一起打包, 搬到哪裡都用同一包,就不會再有「我這裡可以跑」的爭議。
應用程式正在轉型
過去很多系統是一整包的單體式應用程式(monolith),開發者常遇到這些麻煩:
| 問題 | 說明 |
|---|---|
| 牽一髮動全身 | 只改一小段程式,整個系統就得重新編譯、重新測試 |
| 一處失效,全部停擺 | 某個功能出錯,可能讓整個系統都無法運作 |
| 擴充困難 | 只有「搜尋」這個功能很忙,卻得把整套系統一起複製一份 |
於是出現了兩個趨勢:
- 微服務(Microservices):把應用程式拆成多個獨立的小服務(會員、訂單、搜尋…),各自開發、部署與擴充。
- 12-Factor App:一套撰寫雲端應用程式的原則,強調用標準化流程自動設定、服務彼此獨立、可以搬到不同環境、容易做到高可用。
同時,執行環境也愈來愈多元:實體機(bare metal)、機房裡的虛擬機、公有雲;Linux 與 Windows 並存。 組織分工也跟著改變:開發人員希望自由、快速地建立與部署程式;IT 維運人員則重視標準化、安全與管理。
這就形成投影片說的「挑戰」:N 種軟體組合 × M 種執行環境,每一格都可能出問題。 容器的作用,是在兩者之間放一個標準化的「貨櫃」:不管裡面裝什麼,搬運與執行的方式都一樣。
部署方式的三個時代
1. 傳統部署:一台實體伺服器跑一個應用程式
部署很花時間、要先花大錢買機器,而且機器平常大多閒著(浪費資源); 要擴充就得再買一台,要搬家很麻煩,也容易被特定硬體廠商綁住。
2. 虛擬化:Hypervisor 把一台實體機切成多台虛擬機(VM)
Hypervisor(虛擬化層,例如 VMware、Hyper-V、KVM、VirtualBox)讓一台實體機同時跑好幾台 VM, 每個應用程式住在自己的 VM 裡。資源可以集中調度、擴充容易、部署快, 這也是雲端「租用虛擬機、用多少付多少」的基礎。 代價是:每一台 VM 都要開一整套作業系統,各自佔用記憶體、磁碟,開機也要等。
3. 容器:共用主機的作業系統核心
容器不模擬整台電腦,而是讓多個應用程式共用主機的作業系統核心(kernel), 每個容器只帶自己需要的函式庫與程式,彼此用核心提供的隔離機制分開。
由上往下看兩種架構(下方的互動練習會畫出來):
| 層次 | 虛擬機 | 容器 |
|---|---|---|
| 應用程式與函式庫 | 每個 App 一份 | 每個 App 一份 |
| 作業系統 | 每個 App 各一套 | 沒有這一層 |
| 中間層 | Hypervisor(虛擬化層) | 容器引擎(Docker) |
| 底層 | 實體主機 | 主機作業系統(大家共用核心)+實體主機 |
投影片的說法是:VM 是基礎設施(infrastructure)等級的切割,把一台實體機當成多台機器; 容器是應用程式等級的封裝。
虛擬機與容器的優缺點
| 比較項目 | 虛擬機(VM) | 容器(Container) |
|---|---|---|
| 每個單位包含 | 應用程式+函式庫+完整作業系統 | 應用程式+函式庫(共用主機核心) |
| 啟動時間 | 要開機,大約數十秒到數分鐘 | 啟動一個程序,大約一秒內 |
| 大小 | 大約數 GB | 大約數 MB 到數百 MB |
| 同一台主機能放幾個 | 較少 | 較多 |
| 隔離程度 | 較強:各自有核心 | 較弱:共用同一個核心 |
| 可以跑不同作業系統 | 可以(Linux 主機上跑 Windows VM) | 只能用和主機核心相容的系統(Linux 容器需要 Linux 核心) |
以上數字都是大約的量級,實際依作業系統、映像檔與硬體而不同。
兩者不是二選一。實務上最常見的做法是容器與 VM 並用:在雲端租幾台 VM, VM 裡面再跑很多個容器。開發(DEV)時在自己電腦用容器,上線(PROD)時把同一包容器放到雲端的 VM 上執行。
Docker 是什麼
Docker 是一個開放原始碼專案,用來把應用程式打包(build)、運送(ship)、執行(run)在輕量的容器裡。
- 在 64 位元的 Linux 核心上執行;不需要 Hypervisor,伺服器資源可以用得更充分。
- 主要的雲端平台(例如 AWS、Google Cloud、Microsoft Azure)都支援執行 Docker 容器。
- 在 Windows 與 macOS 上,Docker Desktop 會在背後準備一個小型的 Linux 環境來跑容器(下一課安裝時會看到)。
為什麼要用 Docker:
| 特性 | 說明 |
|---|---|
| 可攜的部署(Portable) | 程式和環境綁成一個單位,部署到開發機、測試機、雲端都不用改 |
| 快速交付(Fast delivery) | 容器格式標準化,從開發到上線的流程變快 |
| 容易擴充(Scale with ease) | 需要時可以一次啟動很多個容器,不需要時馬上停掉 |
投影片用一句話形容:Docker 是程式碼的裝箱。就像海運貨櫃: 不管裡面裝的是衣服還是電子零件,貨櫃尺寸一樣,船、碼頭、卡車都用同一套方式搬運。
一個限制:容器共用主機的核心,所以CPU 架構要一致。為 x86(amd64)建立的容器, 不能直接在 ARM(arm64)的機器上跑,需要有對應架構的版本。
先認識兩個名詞:映像檔與容器
接下來的每一課都會用到這兩個名詞:
| 名詞 | 比喻 | 說明 |
|---|---|---|
| 映像檔(image) | 食譜、安裝光碟 | 唯讀的範本,裡面有作業系統檔案、程式、套件與設定 |
| 容器(container) | 照食譜做出來的一道菜 | 由映像檔建立、正在執行或執行過的實例;一個映像檔可以建立很多個容器 |
Docker 的工作流程可以濃縮成三步:
BUILD 建立映像檔 ──▶ SHIP 放到倉庫(Docker Hub)分享 ──▶ RUN 在任何主機把映像檔跑成容器
(Dockerfile + docker image build) (docker image push/pull) (docker container run)
- 第 02 課:安裝 Docker,跑第一個容器
- 第 03 課:容器的生命週期
- 第 04、05 課:映像檔從哪裡來、怎麼挑
- 第 07、08 課:自己寫 Dockerfile、建立並發布映像檔
想一想:虛擬機與容器
同一台主機上跑 5 個應用程式,為什麼用 VM 通常比用容器吃更多記憶體?
下面哪一個是 Hypervisor 的工作?
你想在一台 Linux 伺服器上執行一套只能在 Windows 上跑的舊系統,比較適合用哪一種?
想一想:Docker 解決什麼問題
「在我電腦上可以跑,到你那裡就不行」,Docker 用什麼方式解決?
關於映像檔與容器,下面哪一句正確?
重點精華回顧
- 應用程式從單體式走向微服務,執行環境從實體機、虛擬機走向雲端;「N 種軟體 × M 種環境」讓部署變複雜。
- 虛擬機靠 Hypervisor 切割實體機,每台 VM 有完整作業系統:隔離強、可跑不同系統,但吃資源、開機慢。
- 容器共用主機的作業系統核心,只帶自己的函式庫與程式:輕、啟動快、一台主機能放很多個;但 CPU 架構與核心要相容。
- VM 是基礎設施等級的切割,容器是應用程式等級的封裝;實務上常常並用(VM 裡跑容器)。
- Docker 把程式碼和執行環境一起裝箱:Build、Ship、Run。
- 映像檔是唯讀範本,容器是由映像檔建立的實例。