Docker 是一個開放原始碼的開放平臺軟體，用於開發應用、交付（shipping）應用和執行應用。Docker 允許使用者將基礎設施（Infrastructure）中的應用單獨分割出來，形成更小的顆粒（容器），從而提高交付軟體的速度。 Docker 容器與虛擬機器類似，但二者在原理上不同。容器是將作業系統層虛擬化，虛擬機器則是虛擬化硬體，因此容器更具有便攜性、更能高效地利用伺服器。 容器更多的用於表示軟體的一個標準化單元。由於容器的標準化，因此它可以無視基礎設施（Infrastructure）的差異，部署到任何一個地方。另外，Docker 也為容器提供更強的業界的隔離相容。 Docker 利用 Linux 核心中的資源分離機制，例如 cgroups，以及 Linux 核心（namespaces），來建立獨立的容器（containers）。這可以在單一 Linux 實體下運作，避免啟動一個虛擬機器造成的額外負擔。Linux 核心對名稱空間的支援完全隔離了工作環境中應用程式的視野，包括行程樹、網路、使用者 ID 與掛載檔案系統，而核心的 cgroup 提供資源隔離，包括 CPU、記憶體、block IO 與網路。從 09 版本起，Dockers 在使用抽象虛擬是經由 libvirt 的 LXC 與 systemd nspawn 提供介面的基礎上，開始包括 libcontainer 函式庫做為以自己的方式開始直接使用由 Linux 核心提供的虛擬化的設施。 基礎架構 專業名詞 Docker 有兩個意思： 代指整個 Docker 專案。 代指 Docker 引擎。 Docker 引擎 Docker 引擎 Docker Engine 是一個服務端 客戶端結構的應用，主要有這些部分：Docker 守護程序、Docker Engine API、Docker 客戶端。 Docker 守護程序 Docker daemons，也叫 dockerd ，是一個持久化的程序，使用者管理容器。守護程序會監聽 Docker Engine API 的請求。 Docker Engine API 是用於與 Docker 守護程序互動用的的 API。它是一個 RESTful API，因此它不僅可以被 Docker 客戶端呼叫，也可以被 wget 和 curl 等命令呼叫。 Docker 客戶端，也叫 docker，是大部分使用者與 Docker 互動的主要方式。使用者透過客戶端將命令傳送給守護程序。命令會遵循 Docker Engine API Docker 註冊中心 Docker 註冊中心 Docker registry 是用於儲存 Docker 的映象。Docker Hub 是一個公共的註冊中心，任何人都可以使用，預設配置下，Docker 將會在這裡尋找映象。 另外，使用者可以自行構建私有註冊中心。Docker Datacenter DDC 的使用者，可以直接使用 Docker Trusted Registry DTR。 2023 年 5 月，在中國大陸地區被防火長城阻斷遮蔽，同年 9 月恢復訪問 httpscnseccomarchives3150468html。 物件 Docker 的物件是指 Images、Containers、Networks、Volumes、Plugins 等等。 容器（Containers）是映象的可執行的例項。容器可透過 API 或 CLI（命令列）進行操控。 映象（Images）是一個只讀模板，用於指示建立容器。 映象分層 layers 構建的，而定義這些層次的檔案叫 Dockerfile。 服務（Services）允許使用者跨越不同的 Docker 守護程序（Docker daemons）的情況下增加容器，並將這些容器分為管理者（managers）和工作者（workers），讓他們為 swarm 共同工作。 擴充套件架構 Docker Compose Compose 可譯為組合物。Compose 是用於定義和執行 多個容器 Docker 應用程式 的工具。透過 Compose，你可以使用 YAML 檔案來配置應用程式需要的所有服務，然後透過使用一個命令，就可以建立並啟動所有服務。Compose 對應的命令為 dockercompose。 Swarm Mode 當說到 Docker Swarm 時，一般是指單獨專案 Docker Swarm。而在 Docker 112 時，將 swarm mode 整合到 Docker 引擎中，可用 Docker 引擎 API 和 CLI 命令直接使用。官方推薦使用者使用整合的 swarm mode 。 Swarm Mode 內建 kv 儲存功能，提供了眾多的新特性，比如：具有容錯能力的去中心化設計、內建服務發現、負載均衡、路由網格、動態伸縮、滾動更新、安全傳輸等。使得 Docker 原生的 Swarm 叢集具備與 Mesos、Kubernetes 競爭的實力。 cluster 中文：叢集，Docker 將叢集定義為：一群共同作業並提供高可用性的機器 。swarm 中文：群，是指一個叢集的 Docker 引擎以 swarm mode 形式執行。swarm mode 是指 Docker 引擎內嵌的叢集管理和編排功能。當你初始化了一個 swarm cluster 或者將節點加入一個 swarm 時，其 Docker 引擎就會以 swarm mode 的形式執行。 原理 swarm 中的 Docker 機器中分為 managers（管理者） 和 workers（員工），管理者用於處理叢集的關係和委派，員工則用於執行 swarm 服務。 當你建立 swarm 服務時，你可以為其增加各種額外的狀態（如：數量、網路、埠、儲存資源等等）。Docker 會去維持使用者想要的狀態。如：一個工作節點如果掛了，那麼 Docker 會去把這個節點的任務給另外一個節點。此處的任務（task）是指：被 swarm 管理者管理的一個執行中的容器。 swarm 服務比單獨容器好在，修改 swarm 服務的配置之後不用重啟。同時，Docker 以 swarm mode 形式執行時，也可以選擇直接啟動單獨的容器。另外，swarm mode 下，你也可以透過 docker stack deploy 使用 Compose file 部署應用棧。 swarm 服務分為兩種，一種是 replicated services ，可以指定節點任務的總數量；global services，則是每個節點都會執行一個指定任務。 swarm 管理員使用 ingress 負載均衡使服務可被外部接觸。 swarm 管理員會自動地給服務分配 PublishedPort（或者手動配置）。外部元件，如雲負載均衡器能透過叢集中任何節點上的 PublishedPort 去接入服務（不管該服務是否啟動）。另外 swarm mode 有內部 DNS 元件，它會為每個服務分配一個 DNS 條目。swarm 管理員使用 internal load balancing 去分發請求時，就是依靠這個 DNS 元件。 swarm mode 的功能是由 swarmkit 一個獨立專案 提供的，它實現了 Docker 的編排層。swarm 可以直接被 Docker 使用。 檔案格式 Docker 有兩種檔案格式，Dockerfile 和 Compose file。Dockerfile 定義了單個容器的內容和啟動時候的行為。Compose file 定義了一個多容器應用。 Dockerfile Docker 可以依照 Dockerfile 的內容，自動化地構建映象。 Dockerfile 是包含著使用者想要如何構建映象的所有命令的文字。 FROM ubuntu1804 COPY app RUN make app CMD python appapppy 關鍵詞： RUN。RUN 會在當前映象的頂層上新增新的一層 layer，並在該層上執行命令，執行結果將會被提交。提交後的結果將會用於 Dockerfile 的下一步。 ENTRYPOINT，入口點。ENTRYPOINT 允許你配置容器，使之成為可執行程式。即，ENTRYPOINT 允許你為容器增加一個入口點。ENTRYPOINT 和 CMD 類似，均在容器啟動時執行，但是 ENTRYPOINT 為了提供穩定且不可被覆蓋的操作。透過在命令列中指定 entrypoint 命令的方式，可在執行時將 Dockerfile 檔案中的 ENTRYPOINT 覆蓋。 CMD，是 command 的縮寫。CMD 用於為已建立的映象提供預設的操作，當不想要用預設操作時候，可用 docker run IMAGE TAGDIGEST COMMAND 進行替換 。但當 Dockerfile 擁有入口點時，CMD 用於賦予入口點引數。 Compose 檔案 Compose 檔案 是一個 YAML 檔案，定義了服務（service）、網路、卷（volume）。 服務（service）定義 各容器的配置，定義內容將以命令列引數的方式 傳給 docker run 命令。 網路（network），類似地，將定義內容傳給 docker network create 命令 。 卷（volume），類似地，將定義內容傳給 docker volume create 命令。 docker run 命令中有一些選項，和 Dockerfile 檔案中的指令效果一樣（如：CMD EXPOSE VOLUME ENV），如果 Dockerfile 檔案中使用這些指令，那麼這些指令就會被視為預設引數，所以開發者無需特意在 Compose 檔案中再指定一次。 Compose 檔案 可使用 Shell 變數（Variable），如： db image postgresPOSTGRES_VERSION Compose 檔案 可透過自身的 ARGS 變數，將引數傳給 Dockerfile 的 ARGS 指令。 網路 參考文件：Docker 文件 網路概要 bridge 在 Docker 裡，網橋網路 使用的是 軟體形式的網橋。使用相同的網橋的容器連線進入該網路，而非該網路的容器刷故無法接入。Docker 網橋驅動會自動地在 Docker 主機上安裝規則，這些規則讓不同橋接網路之間不能直接通訊。 橋接經常用於：在單獨容器上執行應用時，可透過 網橋 進行通訊。 網橋網路 適用於容器執行在相同地 Docker 守護程序的主機上。不同 Docker 守護程序主機上的容器，它們之間的通訊需要依靠作業系統層次的路由，或者你應該使用 overlay 網路 進行代替。 bridge 是網橋驅動，是 Docker 預設的網路驅動（介面名為 docker0），當你不為容器指定一個網路時候，Docker 將會使用該驅動。 可透過 daemonjson 檔案修改相關配置。 自定義網橋可透過 brctl 命令進行配置。 host 主機模式 host 用於單獨容器，該網路下容器只能和 Docker 主機進行直接連線。host 只適用於 Docker 1706 或以上版本的 swarm 服務。 host 網路和 VirtualBox 的 僅主機網路（Hostonly Networking） 類似。 overlay overlay （中文：覆蓋網路）網路驅動將會建立分散式網路，該網路可以覆蓋若干個 Docker 守護程序主機。該網路是基於 主機特定網路（hostspecific networks），允許 swarm 服務 和 容器 進行安全通訊（當加密功能開啟時）。在該網路下，Docker 能夠清晰地掌握 資料包的路由 以及 傳送接收容器。 overlay 有兩種網路型別網路： ingress 網路，可掌控 swarm 服務 的網路流量 。該網路是 overlay 的預設網路。 docker_gwbridge 網路是 網橋網路。該網路會將 單獨的 Docker 守護程序 連線至 swarm 裡的另外一個守護程序。 在 overlay 網路下，單獨的容器 和 swarm 服務 的行為和配置概念 是不一樣的。 該策略不需要 容器們 具有作業系統級別的路由，因為 Docker 負責路由。 macvlan Macvlan 網路配置提供了一種機制，允許單獨的容器具有獨立的 MAC 地址，使得這些容器在網路上表現得如同物理裝置。 none 該策略下，容器不使用任何網路。none 常常用於連線自定義網路驅動的情況下。 其他 截止 2023 年 5 月 18 日，Docker 官方倉庫域名 httpshubdockercom 在中國大陸被遮蔽，方式為 DNS 汙染。隨後短暫解封，2024 年 6 月 6 日再次被封。 資料管理 Docker 預設下，所有檔案將會儲存在容器裡的可寫的容器層（container layer）。 資料與容器為一體。隨著容器消失，資料將消失；難以與其他程式（容器）共享。可以採用掛載檔案的方式解決。 由於容器的寫入層是與宿主機器緊緊耦合。所以你難以移動資料到其他機器。 容器的寫入層的是透過 儲存驅動（storage driver） 管理檔案系統。儲存驅動 會使用 Linux 核心的 鏈合檔案系統（union filesystem）進行掛載。相比起直接操作於宿主機器檔案系統的 資料卷，這額外的抽象層將會降低效能。 容器有兩種永久化儲存方式：卷（volumes）和 繫結掛載（bind mounts）。另外，Linux 使用者還可使用 tmpfs 進行掛載；Window 使用者還可以使用 命名管道（named pipe）。在容器中，不管是哪種永久化儲存，表現形式都是一樣的。 卷 卷（volumes）是宿主機器的檔案系統的一部分，由 Docker 進行管理（ 在 Linux，儲存於 varlibdockervolumes）。非 Docker 程式不應該去修改這些檔案。Docker 推薦使用 卷 進行持久化資料。 卷 可支援 卷驅動（volume drivers），該驅動允許使用者將資料儲存到 遠端主機 或 雲服務商（cloud provider）或 其他。 沒有名字的卷叫匿名卷（anonymous volume），有名字的卷叫命名卷（named volume）。匿名卷沒有明確的名字，當被初始化時，會被賦予一個隨機名字。 繫結掛載 繫結掛載（bind mounts）透過將宿主機器的路徑掛載到容器裡的這種方式，從而資料持續化，因此繫結掛載可將資料儲存在宿主機器的檔案系統的任何地方。非 Docker 程式可修改這些檔案。 繫結掛載是 Docker 早期就存在的，相比起卷，繫結掛載十分簡單明瞭。 在開發 Docker 應用時，應使用命名卷（named volume）代替繫結掛載，因為使用者不能對繫結掛載進行 Docker CLI 命令操作。 繫結掛載常用於： 同步配置檔案，如： 將 宿主主機的 DNS 配置檔案（etcresolvconf）同步至容器中 在開發程式時，將 原始碼 或 Artifact 同步至容器中。 這種用法與 Vagrant 類似。 tmpfs tmpfs 掛載（tmpfs mounts），僅僅儲存於記憶體中，並不操作 宿主機器的檔案系統（不持久化於磁碟）。它可用於儲存一些 非持久化狀態、敏感資料。 舉例，swarm 服務 透過 tmpfs 將 secrets（密碼、金鑰、證書等）儲存到 swarm 服務。 命名管道 命名管道（named pipes），透過 npipe 掛載的形式，使 Docker 主機 和 容器 之間能互相通訊。常見用例是在容器內執行第三方工具，並使用命名管道連線到 Docker Engine API。 覆蓋問題 當掛載 空的卷 至一個目錄中，目錄中的內容會被複制於卷中（不會覆蓋）。如果掛載 非空的卷 或 繫結掛載 至一個目錄中，那麼該目錄的內容將會被隱藏（obscured ），當解除安裝後內容將會恢復顯示。 日誌 在 UNIX 和類 Unix 系統中，常見的 IO 流 分為三種：STDIN（輸入 ）、 STDOUT（正常輸出）、STDERR（錯誤輸出）。 預設配置下，Docker 的日誌（如：docker logs、docker service log）所記載的是命令列的輸出結果（STDOUT 和 STDERR）。而 STDOUT 和 STDERR 對應的檔案路徑分別是 devstderr 和 devstdout。 另外，也可以在宿主主機上檢視容器的日誌，使用以下命令可以檢視到容器的日誌位置。 docker inspect formatLogPath INSTANCE_ID Kubernetes in docker kind（全稱：Kubernetes IN Docker）是部署本地 Kubernetes 叢集的工具，而叢集的節點是由 Docker 生成的。 操作細節 在安裝完 kind 之後，透過 kind create cluster 命令生成叢集。 生成 Kubernetes 集群后，可以透過 Docker 命令進行檢視節點概覽： docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 99c96c1f21ab kindestnodev1170 usrlocalbinentr 4 minutes ago Up 4 minutes 127001327696443tcp kindcontrolplane 歷史 Docker 命令在過去的發展中誕生了 40 種以上的命令，過多的命令導致混亂以及難以使用 tab 自動補充，因此在 docker 113 版本（2017119）中，命令列被重構，根據邏輯物件進行劃分。官方建議使用者使用新的語法進行操作。 已過時 Docker Swarm 參考 Swarm Mode 章節。 Docker Machine Docker Machine 是一個工具，它允許你在虛擬宿主機上安裝 Docker 引擎，並使用 dockermachine 命令管理這些宿主機。你可以使用 Machine 在你本地的 Mac 或 Windows box、公司網路、資料中心、或像 AWS 或 Digital Ocean 這樣的雲提供商上建立 Docker 宿主機。 Docker Machine 最後更新時間是在 0160 20181108 版本。官方建議在 112 以及之後版本使用 Docker Desktop for Mac 和 Docker Desktop for Windows 進行代替。 Docker Toolbox Docker Toolbox 是用於幫 Windows 系統和 Mac 系統 安裝 Docker 環境。新版本建議使用 Docker Desktop for Mac 和 Docker Desktop for Windows 進行安裝。最後更新版本是 19031 20190801。 安全性爭議 2021 年，安全公司 Palo Alto Networks 研究人員 Aviv Sasson，在 Docker Hub 上發現的惡意容器映像存檔，分別來自 10 個不同帳號，總下載次數超過 2000 萬次，其中內含的挖礦軟體。 參考文獻 外部連結 Source code repository Multitenancy using Docker Docker 101 Tutorial libcontainer git repo 如何在 Linux 下安裝 Docker Windows 容器 在 Windows 10 部署 Docker 參見 作業系統層虛擬化 cgroups LXC Dotcloud Category 作業系統技術 Category 自由虛擬化軟體 CategoryLinux 容器化 Category 用 Go 程式設計的自由軟體