引言
在現代軟體開發中,「一次建置,處處運行」的理想正逐漸成為現實。Docker 作為容器技術的代表,正是這股浪潮的核心之一。
Docker 是
Build and Ship any Application Anywhere (建置任何應用程式並運行在任何地方)
Docker 是一個開源的容器化平台,可以用來打包、運行和分享應用程式。Docker 通過容器化技術實現了應用程式的獨立性和可移植性,這代表只要安裝 Docker,就能在不同的作業系統或平台上,毫無差異地執行相同的應用程式,讓開發者和運維人員可以更加便捷地進行應用程式的開發、部署和運維。
容器技術與虛擬機
虛擬機器
所謂的 VM,就是將「一台實體的主機」,拆分成「許多個作業系統」的技術,共享硬體資源。
VM(Virtual Machine,虛擬機) 是一種使用軟體模擬出來的電腦系統,它能在一台實體機器(宿主機,Host)上模擬出多台獨立運作的「虛擬電腦」。這些虛擬電腦彼此之間相互隔離,像是真實的電腦一樣可以安裝作業系統、應用程式、進行開發、測試或部署。
一台虛擬機的背後通常包含以下幾個核心元件:
- 實體硬體(Host Hardware)
真正的電腦主機,包括 CPU、記憶體、硬碟、網卡等 - Hypervisor(虛擬機監控器)
一種管理 VM 的軟體,負責將實體硬體「切分」給多個虛擬機使用
有兩種類型:類型 說明 Type 1(裸機型) 安裝在實體機上,例如 VMware ESXi、Microsoft Hyper-V、Xen。效率高,常見於企業伺服器環境 Type 2(託管型) 安裝在作業系統之上,例如 VMware Workstation、VirtualBox。適合開發或學習用途 - Guest OS(客體作業系統)
安裝在每台 VM 裡的作業系統,可以是 Windows、Linux、macOS(受限)等 - 虛擬硬體(Virtual Hardware)
包括虛擬的 CPU、RAM、硬碟、顯示卡、網卡等。從客體 OS 來看,就像真實硬體一樣
Docker 與虛擬機器不同
Docker 運行應用程式的環境被稱作 容器 (Container)。它不像虛擬機器 (virtual machine ) 需要 虛擬機器監視器 (hypervisor) 模擬出軟體、韌體或硬體,反而直接運行在宿主機(host machine)的核心。以執行應用程式的運行來說,虛擬機器需要模擬出整套作業系統才能運行應用程式,而容器則是直接運行在宿主機上。不僅如此,宿主機也可以是虛擬機器。因此,它比虛擬機器又更為輕量級、執行啟動又更快。
過去,當我們想要在不同的環境下運行同一份程式碼,我們需要使用虛擬機技術。然而,虛擬機有一些固有的問題,比如需要的資源多、啟動慢、難以移動和複製等。容器技術則為解決這些問題提供了新的方向。
容器是一種軟體技術,可以將應用程式及其全部運行環境(包括文件系統、系統庫等)打包在一起,形成一個獨立、一致的運行單元。容器之間互相隔離,但共享同一個作業系統,每個容器都像一個輕量級的虛擬機。這種技術可以讓開發者在不同的系統和環境中,輕鬆地運行和管理他們的應用程式。
- 啟動速度:
Docker 屬於作業系統層級的虛擬化,啟動極快,通常在秒級甚至毫秒等級即可完成。相比之下,傳統虛擬機需啟動完整作業系統,常見情況下需要數十秒至數分鐘。 - 資源效率:
Docker 相對虛擬機更節省資源,容器共用宿主機的核心,不需要像虛擬機那樣為每台虛擬作業系統配置獨立的資源。這種架構大幅減少了 CPU、記憶體等的開銷,也提升了效能。不過,仍有部分系統資源競爭或隔離上的考量,並非毫無性能損耗。 - 輕量與可擴展性:
Docker 容器架構支援共用核心與分層式映像(image layer)技術,使其相較虛擬機更輕量、更容易快速部署。在相同的硬體環境下,通常可以部署更多的容器來服務不同應用。但要注意,容器數量一多,也會對系統資源管理提出挑戰,例如記憶體、PID、網路等限制。 - 安全性:
相較虛擬機,Docker 的安全性較弱。容器的使用者(尤其是 root)若未經妥善限制,可能直接存取宿主機的資源。虛擬機則有完整的硬體與作業系統隔離,搭配如 Intel VT-d、VT-x 等技術,即使其中一台虛擬機被攻破,也較難波及宿主機或其他虛擬機。容器則必須透過額外機制(如 AppArmor、Seccomp、user namespace)強化安全隔離。 - 可管理性:
早期 Docker 的管理工具確實不夠成熟,但如今已有完整的容器管理生態系統,如 Kubernetes、Docker Compose、Portainer 等,可實現集中式部署、監控與資源管理。雖然和 VMware vCenter 等虛擬機管理工具相比,在某些使用體驗上仍有差異,但不可再簡單認為 Docker 管理能力不足。 - 高可用與容錯性:
Docker 本身雖不具備這些機制,但可透過 Kubernetes 等容器編排工具,實現自動故障恢復、滾動升級與副本擴展等功能,達成應用層級的高可用性。虛擬機透過成熟的架構如 VMotion、HA、高可用集群等,在業界經過多年驗證,具備高度的業務連續性保證。 - 部署與交付:
Docker 透過Dockerfile
記錄應用構建流程,能完整還原映像並實現一致性的交付與自動化部署,極適合 DevOps 流程整合。而傳統虛擬機雖可透過映像實現環境封裝,但缺乏標準化的構建過程與分發機制,難以支援大規模快速部署。
虛擬機 (VM) | 容器 (Docker) | |
---|---|---|
啟動速度 | 較慢 | 非常快 |
系統資源占用 | 高 | 低 |
是否需完整 OS | 是 | 否 |
可攜性 | 較差 | 高 |
應用隔離性 | 高 | 中~高 |
Docker 的優勢與應用場景
- 環境一致
Docker 可以將應用程式及其所有依賴項打包在一個容器中,確保了從開發到測試到生產的整個生命週期中,環境的一致性。這解決了「在我的機器上運行得好好的」這種常見問題,讓開發和發佈有統一的標準環境,也有利於持續整合(CI, Continuous Integration)與持續交付(CD, Continuous Delivery)流程的建立,讓應用程式從寫好程式碼到部署上線都能自動化完成。 例如,開發者在 macOS 上開發的 Node.js 應用,使用 Docker 打包後可以直接部署到 Ubuntu 的生產環境中,不會因為 Node.js 版本不同而出錯。 - 輕量級和性能優越
容器提供輕量級的沙盒環境,與傳統的虛擬機相比,Docker 容器不需要運行一整套操作系統,而是直接使用主機的操作系統,這使得容器變得非常輕量且啟動速度快 - 應用程式隔離
容器提供輕量級的沙盒環境,每個容器都在自己的空間中運行,並有其自己的網路和文件系統,互不干擾。這提供了額外的安全層,也使得各種應用程式可以在同一台機器上共存 - 可移植
由於容器包含了所有需要的依賴項,因此它可以在任何安裝了 Docker 的系統上運行,無論這個系統是物理機還是虛擬機,是在數據中心還是在雲端 - 易於管理和擴展
Docker 提供了豐富的工具和平台,用於管理容器、服務和集群,使應用程式的部署、擴展和運維變得簡單
Docker 可以做什麼?
- 容器管理
使用 Docker CLI 建立、啟動、停止、搬移和刪除容器 - 映像管理
可以從容器建立映像,並推送至映像倉庫以供分享與部署。這是實現快速應用程式部署和擴展的基礎 - 映像版本控制
透過 tag 機制追蹤映像變化,可回溯特定版本。開發者可以追蹤映像的改變,並在需要的時候回退至先前的版本 - 系統資源隔離
使用 Linux 的 cgroups 和 namespaces 技術,將每個容器的 CPU、記憶體、網路等與其他容器隔離 - 資源掛載與整合
容器可掛載的資源如磁盤、網路和檔案系統,使容器可以像真實的獨立系統一樣運行
這些功能構成了 Docker 作為開發、測試與部署平台的基礎。
Docker 是如何運作的?
Docker 的架構主要由以下三個部分組成:
docker daemon
(dockerd)
Docker 的核心服務程式,稱為 dockerd 或 docker 引擎,是常駐在背景的守護行程(daemon process),負責處理容器的建立管理、控制映像、配置網路與儲存空間等工作,幾乎所有背後的魔法,都是它在操控- REST API
dockerd 暴露出一組 RESTful API,讓用戶或工具可以程式化地控制、操控 Docker,例如管理 Images、containers、networks 和 volumes 等資源 - Docker CLI (Command-Line Interface)
相較於 REST API,使用者更常透過命令列來操作 Docker。這個 CLI 是與 Docker Daemon 互動的主要方式。CLI 會呼叫 REST API 與 dockerd 溝通
容器的物件
Container(容器):映像檔的執行物件
Container 是 Docker 的核心技術,運行於 Docker Engine 之上,且在各種作業系統上皆有對應版本。
容器是映像檔 (Image) 的實際執行物件,用 docker + run
/ start
/ restart
/ stop
/ rm
指令可以管理容器。當容器建立時,容器執行於隔離的沙箱環境中,可視為擁有獨立的檔案系統。另外,我們還可以為 Container 設定 network
和 volume
等資源,讓其具備通訊與持久化資料的能力:
volume
是容器與別人共享的資料區,我們把資料放在裡面,可以:- 與
Host
共同存取 - 提供其它 Container 掛載 (mount) 使用,共享同樣的資料區
- 獨立於 container,當 Container 移除時,
volume
裡的資料可以保留下來
- 與
network
讓我們可以與別的容器和主機通訊,像是:從外部存取容器內的服務,可能是從Host
,也可能是來自別的 Container
Image(映像檔):容器建立的範本
Image 是容器建立的範本,它打包著相關程式碼、函式庫、環境配置檔。簡而言之,就是一群檔案集合。Image 常常是基於別的 Image 建立的,像是我們可以基於 nginx:1.18.0
加入客制的 Nginx 設定組態或加入你自己的檔案再重新建置 (build) 一個新的 Image。
當要建立並執行 Container 時一定要指定「唯一」的一個映像檔,如 docker run <Image>
Volume:獨立於容器的檔案空間
在實際應用中,我們常需要容器擁有「持久化資料」或「跨容器共用資料」的能力,以下是常見使用場景:
- 資料在容器刪除後仍需保留(例如:資料庫)
- 容器與宿主機 (
Host
) 共享資料夾或檔案 - 多個容器共用設定檔或資料集
簡單來說當我們需要「資料共用」或「資料保留」,此時就會用到 Volume
docker run -v (–volume)
來掛載 volume,格式是:-v <source>:<target>
:其中 source 可以是宿主機路徑(bind mount)或 volume 名稱,兩者都不會因為容器移除而被自動刪除。;目標 (target) 是指定要掛入容器內的位置。
Docker 提供三種掛載類型(mount types):
bind mount
:掛入現有的 Host 檔案系統 (filesystem),用在容器與 Host 共享資料夾或檔案volume
:掛入 volume 物件tmpfs mount
:從 memory 掛載
Network:與容器通訊
網路是 Docker 物件中重要的一環,它可以讓其它人存取容器中的應用程式,也可以讓各個 Docker daemons (dockerd) 串接起來,使容器在它們之間擴張 (scale) 複製,而容器不會察覺它目前運行在哪台主機。
docker 支援許多模式,但我們只考慮本機常遇到的 bridge
和 Host
使用情境。
- Bridge mode:分離容器和本機的網路
這是容器預設的網路模式。當我們docker run
時,容器會使用一個預設的 network,名稱為 bridge 的網路物件 (不同的作業系統可能名稱會有差異,mac 叫 bridge, linux 叫 docker0)。容器接上那個預設的 network 並配給一個 IP。 - Host mode:直接使用本機的網路
這是最簡單的模式,容器會共用主機的網路堆疊與 IP,可視為在主機上執行的「本地行程(local process)」,不再有獨立的網路介面。它監聽什麼port
,那麼Host
的port
就會被使用,所以連-p
都不用設定。此外,有個小細節要注意,一個port
只有一個 process 能監聽,同理,一個port
也只能給一個容器物件監聽。