你已經會「用」容器了——docker compose up 一下,一顆 SQL Server 就活過來。這門課要補的是中間那段黑箱:它到底做了什麼、為什麼做得到、你要怎麼把自己的程式也變成那樣一個東西。
第一章不碰任何指令,先回答最根本的問題:容器是為了解決什麼痛苦而誕生的?理解了這個「為什麼」,後面每一個看起來很怪的設計(為什麼容器刪掉資料就沒了、為什麼要做 port mapping、為什麼 image 要分層)才會變成理所當然,而不是死記硬背的規則。
幾乎每個工程師都遇過:同一份程式碼,在自己筆電上跑得好好的,交給同事或丟上測試機就爆炸。要理解容器,得先看清楚這件事為什麼會發生。
你以為你交付的是一個 app.jar,但那個 jar 檔要跑起來,其實踩在一整疊「它假設一定存在」的東西上面:
UnsupportedClassVersionError。application.yml 指向 localhost 的資料庫,測試機沒有那個資料庫。C:\temp\upload,Linux 機器上根本沒有 C 槽。所以真正的問題是:我們一直只交付食譜,卻假設每個人的廚房都一樣。容器的答案很暴力也很有效——那就把廚房一起寄過去。
「把廚房一起交付」不是新想法,容器只是最後的答案。看過前面三代的失敗,才知道容器的每個設計在補什麼洞。
先給定義,再拆解:
一台 Linux 電腦的軟體其實分成兩層:
libssl、glibc)、設定檔、/usr/bin 底下的指令工具。「Ubuntu 和 CentOS 的差別」幾乎都在這一層,不在核心。關鍵洞見來了:你的程式真正需要的,其實只是「一堆使用者空間的檔案」+「一個能執行它的核心」。既然同一台機器上的核心大家都能用,那只要打包使用者空間就夠了——這正是容器做的事。
cat /etc/os-release 會看到 Ubuntu,於是以為「容器裡裝了一個 Ubuntu」。不對。那裡面只有 Ubuntu 的使用者空間檔案(指令工具、函式庫),沒有 Ubuntu 的核心。它借用的是你宿主機的核心。這也解釋了一個常見疑問:為什麼 Linux 容器不能直接在 Windows 核心上跑?——因為它要的是 Linux 核心。(Docker Desktop 的作法是偷偷幫你開一台輕量 Linux 虛擬機來提供核心。)你現在的用法大概是這樣:寫個 docker-compose.yml,打一句指令,SQL Server 就活了。
services:
sqlserver:
image: mcr.microsoft.com/mssql/server:2022-latest
environment:
ACCEPT_EULA: 'Y'
MSSQL_SA_PASSWORD: '請放在 .env,不要寫死在這裡'
ports:
- '1433:1433'
volumes:
- mssql-data:/var/opt/mssql
volumes:
mssql-data:你按下 docker compose up 的那幾秒鐘,底下依序發生了六件事。這六件事正好就是這門課的地圖——每一件都有專章拆解:
mcr.microsoft.com/mssql/server:2022-latest 這串座標翻譯成「哪個倉庫、哪個映像、哪個版本」。→ ch04sqlserver:1433)。→ ch07localhost:1433 的流量,被轉進容器內部。→ ch07技術細節可以慢慢學,但有個思維一定要先換過來,否則後面每一章都會覺得彆扭。
docker exec 進去裝了個套件、改了個設定,下次容器重建就全部消失。這不是 bug,是刻意的設計——它保證了「每次長出來的都一樣」。Dockerfile;要改一個設定 → 寫進 docker-compose.yml 或環境變數。這種「把最終狀態寫成檔案,讓工具去實現它」的風格叫做宣告式(declarative),也是後面 Kubernetes(ch14)的靈魂。docker compose down -v 砍掉重來,30 秒後回到乾淨狀態。「壞了不修,重建就好」——這是容器化最大的生產力來源,而它建立在「環境完全由檔案定義」這個前提上。| 方式 | 怎麼做 | 致命問題 | 體積/速度 |
|---|---|---|---|
| 安裝文件 | 寫 30 步驟給對方照做 | 人會漏步驟、文件會過期 | — / 數小時 |
| 自動化腳本 | Shell / Ansible 自動執行 | 依賴機器初始狀態,不可重現 | KB / 數分鐘 |
| 虛擬機映像 | 整台機器(含 OS)打包 | 太重:每台養一套完整 OS | 10~40 GB / 分鐘級 |
| 容器映像 | 只打包使用者空間,共用核心 | 隔離不如 VM 徹底(見 ch02) | 數十~數百 MB / 秒級 |
| 常見誤解 | 實際上是 |
|---|---|
| 容器是一種輕量虛擬機 | 不是。VM 靠 hypervisor 模擬硬體;容器只是一個被隔離、被限制的普通 process(ch02 詳解) |
| 容器裡裝了一個完整的 Ubuntu | 只有 Ubuntu 的使用者空間檔案,沒有核心——核心是跟宿主機借的 |
| 容器啟動=在開一台機器 | 沒有開機流程,只是啟動一個 process,所以是秒級甚至毫秒級 |
| 容器比較安全 | 隔離度其實比 VM 弱(共用核心=共用攻擊面)。安全是靠正確設定換來的,不是預設送的 |
| 資料放容器裡就好 | 容器刪掉,裡面寫的資料就消失。要留的必須放 volume(ch06) |
| Docker = 容器 | 容器是技術概念,Docker 只是最流行的實作工具之一(還有 Podman、containerd 等) |
點擊卡片翻面查看答案,共 9 張。