> For the complete documentation index, see [llms.txt](https://philipzheng.gitbook.io/docker_practice/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://philipzheng.gitbook.io/docker_practice/introduction/why.md).

# 為什麼要用 Docker

在回答「為什麼用 Docker」之前，筆者想先問一個問題：**你有沒有經歷過這些情境？**

## 沒有 Docker 的世界

在 Docker 出現之前，軟體開發和維運面臨著諸多棘手的問題。我們先來看看以下三個典型的痛點情境。

### 情境一：「在我電腦上明明能跑」

```
週五下午 5:00
├── 開發者：程式碼寫完了，本地測試通過，提交！🎉
├── 週一早上 9:00
│   └── 測試："這個功能在測試環境跑不起來"
└── 開發者："不可能，在我電腦上明明能跑啊……"
```

筆者統計過，這個問題通常由以下原因導致：

* Python/Node/Java 版本不一致
* 相依庫版本不一致
* 作業系統設定不一致
* 某些環境變數沒有設定
* 「哦，忘了說我本地裝了個 XXX」

### 情境二：環境設定的噩夢

```bash
新同事入職
├── Day 1：領電腦，配環境
├── Day 2：繼續配環境，遇到問題
├── Day 3：換種方法配環境
├── Day 4：問老同事怎麼配的，他也忘了
└── Day 5：終於能跑起來了！但不知道為什麼……
```

### 情境三：伺服器遷移的恐懼

```bash
維運："我們需要把服務遷移到新伺服器"
開發："舊伺服器上的設定文件在哪？"
維運："當時是一個已經離職的同事配的……"
所有人：😱
```

## Docker 如何解決這些問題

Docker 的出現為上述問題提供了完美的解決方案。它透過「一次建立，到處執行」的核心理念，從根本上改變了軟體交付的方式。

### 核心理念：一次建立，到處執行

```mermaid
flowchart LR
    dev["開發團隊"] -->|建立| img["Docker 映像檔"]
    img -->|測試團隊驗證| test["測試團隊"]
    test -- "有問題<br/>回饋修改和更新" --> dev
    test -- "沒問題<br/>發布" --> prod["生產環境"]
```

## Docker 的核心優勢

除了解決上述痛點，Docker 還擁有諸多顯著的技術優勢，包括環境一致性、秒級啟動、高效的資源利用等。

### 1. 環境一致性

Docker 映像檔包含了應用執行所需的大部分使用者態相依：程式碼、執行時期、系統工具、庫和預設設定。它不包含宿主機核心，也不能消除 CPU 架構、核心能力、外部服務、網路、卷和執行時期設定差異。這意味著：

* ✅ 開發環境和生產環境可以顯著減少差異
* ✅ 大幅降低「在我機器上能跑」的問題
* ✅ 新人入職，一條命令就能啟動開發環境

```bash
## 新同事入職第一天

$ git clone https://github.com/company/project.git
$ docker compose up

## 完整的開發環境就準備好了

...
```

### 2. 秒級啟動

傳統虛擬機啟動需要幾分鐘（引導作業系統），而 Docker 容器啟動通常只需要 **幾秒甚至幾百毫秒**。

筆者實測資料：

| 啟動內容      | 虛擬機     | Docker 容器 |
| --------- | ------- | --------- |
| 空系統       | \~60 秒  | \~0.5 秒   |
| MySQL     | \~90 秒  | \~3 秒     |
| 完整 Web 應用 | \~120 秒 | \~5 秒     |

這個差異對以下情境尤為重要：

* **CI/CD 流水線**：每次建立節省幾分鐘，一天累積下來就是幾小時
* **彈性擴容**：流量高峰時能快速啟動更多實例
* **開發體驗**：快速重啟服務進行除錯

### 3. 資源效率

Docker 容器共享宿主機核心，無需為每個應用執行完整的作業系統。以一台 64GB 記憶體的實體伺服器為例：

* **傳統虛擬機方案**：每個虛擬機都需要執行完整的作業系統（每個額外佔用如 2GB 記憶體），產生大量資源開銷，實際可用於應用的記憶體可能只有約 18GB。
* **Docker 方案**：容器直接共享宿主機系統，只需付出很少的基礎開銷（OS 及引擎約 4GB），即可將約 60GB 的記憶體全部用於實際應用。

```mermaid
flowchart TD
    subgraph VM ["傳統虛擬機方案 ❌"]
        direction TB
        Server1["實體伺服器 (64GB 記憶體)"]
        subgraph VMs ["可用應用記憶體: 約 18GB"]
            direction LR
            VM1["VM 1: 應用 1<br/>(含 2GB OS)"]
            VM2["VM 2: 應用 2<br/>(含 2GB OS)"]
            VM3["VM 3: 應用 3<br/>(含 2GB OS)"]
        end
        Server1 --- VMs
    end

    subgraph Docker ["Docker 方案 ✅"]
        direction TB
        Server2["實體伺服器 (64GB 記憶體)<br/>含約 4GB OS及引擎設定"]
        subgraph Containers ["可用應用記憶體: 約 60GB"]
            direction LR
            C1["容器 1: 應用 1<br/>(按需分配)"]
            C2["容器 2: 應用 2<br/>(按需分配)"]
            C3["容器 3: 應用 3<br/>(按需分配)"]
        end
        Server2 --- Containers
    end
```

### 4. 持續交付和部署

Docker 完美契合 DevOps 的工作流程：

```mermaid
flowchart LR
    A["程式碼提交<br/>(Git push)"] --> B["自動建立映像檔<br/>(docker build)"]
    B --> C["自動測試<br/>(容器內執行測試)"]
    C --> D["自動部署<br/>(容器滾動更新)"]
```

使用 [Dockerfile](/docker_practice/dockerfile/run.md) 定義映像檔建立過程，使得：

* 建立過程 **可重複、可追溯**
* 任何人都能從程式碼重建完全相同的映像檔
* 配合 [GitHub Actions](/docker_practice/case_devops/github_actions.md) 等 CI 系統實作自動化

### 5. 輕鬆遷移

Docker 可以在幾乎任何平台上執行：

* ✅ 本地開發機 (macOS、Windows、Linux)
* ✅ 公有雲（AWS、Azure、GCP、阿里雲、騰訊雲）
* ✅ 私有雲和自建資料中心
* ✅ 邊緣裝置和 IoT

**同一個映像檔，在任何地方執行結果都一致。** 這讓應用遷移變得前所未有的簡單。

### 6. 微服務架構的基石

現代微服務架構幾乎都依賴容器技術。Docker 讓你可以：

* **隔離服務**：每個服務執行在獨立容器中，互不干擾
* **獨立擴展**：哪個服務負載高，就單獨擴展哪個
* **獨立部署**：更新一個服務不影響其他服務
* **技術多樣**：不同服務可以用不同語言和框架

```mermaid
flowchart TD
    subgraph Microservices ["微服務架構範例"]
        direction TB
        subgraph AppLayer ["應用層"]
            direction LR
            Frontend["前端容器<br/>(Node.js)"]
            API["API 容器<br/>(Python)"]
            Worker["Worker 容器<br/>(Go)"]
        end
        Redis["Redis 容器"]
        DB["PostgreSQL 容器"]

        Frontend --> API
        API --> Redis
        API --> DB
        Worker --> Redis
        Worker --> DB
    end
```

## Docker 不適合的情境

筆者認為，技術選型要客觀。Docker 並非銀彈，以下情境可能不太適合：

* **需要完全隔離的情境**：容器共享宿主機核心，隔離性不如虛擬機。如果需要執行不受信任的程式碼，虛擬機可能更安全。
* **需要特殊核心的情境**：容器使用宿主機核心。如果應用需要特定版本的核心或核心模組，可能需要虛擬機。
* **Windows 原生應用**：雖然 Docker 支援 Windows 容器，但生態不如 Linux 容器成熟。傳統 Windows 應用的容器化仍有挑戰。
* **桌面應用**：Docker 主要面向服務端應用。桌面 GUI 應用的容器化雖然可行，但通常得不償失。

## 與傳統虛擬機的對比總結

關於容器與虛擬機的詳細特性對比，請參閱 [Docker vs 虛擬機](/docker_practice/introduction/what.md) 中的對比表。總結來說：

* **效能差異**：虛擬機通常有 5-20% 的效能損耗，而容器接近原生效能。
* **最佳情境**：Docker 容器適合微服務、CI/CD、開發環境；虛擬機適合多租戶、高安全需求情境。
