Docker

Docker是一個開放原始碼的開放平臺軟體，用於開發應用、交付（shipping）應用和運行應用。Docker允許用戶將基礎設施（Infrastructure）中的應用單獨分割出來，形成更小的顆粒（容器），從而提高交付軟件的速度。
Docker容器與虛擬機類似，但二者在原理上不同。容器是將操作系統層虛擬化，虛擬機則是虛擬化硬件，因此容器更具有便攜性、更能高效地利用服務器。 容器更多的用於表示軟件的一個標準化單元。由於容器的標準化，因此它可以無視基礎設施（Infrastructure）的差異，部署到任何一個地方。另外，Docker也為容器提供更強的業界的隔離兼容。
Docker 利用Linux核心中的資源分離機制，例如cgroups，以及Linux核心命名空間（namespaces），來建立獨立的容器（containers）。這可以在單一Linux實體下運作，避免啟動一個虛擬機器造成的額外負擔。Linux核心對命名空間的支援完全隔離了工作環境中應用程式的視野，包括行程樹、網路、用戶ID與掛載檔案系統，而核心的cgroup提供資源隔離，包括CPU、記憶體、block I/O與網路。從0.9版本起，Dockers在使用抽象虛擬是經由libvirt的LXC與systemd - nspawn提供界面的基礎上，開始包括libcontainer函式庫做為以自己的方式開始直接使用由Linux核心提供的虛擬化的設施。

**基礎架構**
專業名詞Docker有兩個意思：- 代指整個Docker項目。- 代指Docker引擎。

**Docker引擎**
Docker引擎（Docker Engine）是一個服務端-客戶端結構的應用，主要有這些部分：Docker守護進程、 Docker Engine APIdate=20200218205320 、Docker客戶端。
*Docker守護進程（Docker daemons），也叫 dockerd ，是一個持久化的進程，用戶管理容器。守護進程會監聽 Docker Engine APIdate=20200218205320  的請求。- Docker Engine APIdate=20200218205320 是用於與Docker守護進程交互用的的API。它是一個RESTful API，因此它不僅可以被Docker客戶端調用，也可以被wget 和 curl等命令調用。
*Docker客戶端，也叫docker，是大部分用戶與Docker交互的主要方式。用戶通過客戶端將命令發送給守護進程。命令會遵循 Docker Engine API date=20200218205320  date=20200218205320 

**Docker註冊中心**
Docker註冊中心（Docker registry）是用於存儲Docker的鏡像。Docker Hub 是一個公共的註冊中心，任何人都可以使用，默認配置下，Docker將會在這裡尋找鏡像。
另外，用戶可以自行構建私有註冊中心。Docker Datacenter（DDC）的用戶，可以直接使用 Docker Trusted Registry（DTR）。
2023年5月，在中國大陸地區被防火長城阻斷屏蔽，同年9月恢復訪問。

**對象**
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對應的命令為docker-compose。

**Docker Desktop**
Docker Desktop 是適用於Windows、Linux、MacOS操作系統的一鍵式安裝程序，提供了圖形用戶界面，便於管理Docker的容器、鏡像以及應用等對象。Docker Desktop包含了：Docker Engine、CLI、構建以及擴展等組件。

**Swarm Mode**
當說到 Docker Swarm 時，一般是指單獨項目 Docker Swarm。而在Docker 1.12時，將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 ubuntu:18.04
COPY . /app
RUN make /app
CMD python /app/app.py
關鍵詞：- RUN。RUN會在當前鏡像的頂層上添加新的一層(layer)，並在該層上執行命令，執行結果將會被提交。提交後的結果將會用於Dockerfile的下一步。- ENTRYPOINT，入口點。ENTRYPOINT允許你配置容器，使之成為可執行程序。即，ENTRYPOINT允許你為容器增加一個入口點。ENTRYPOINT和CMD類似，均在容器啟動時執行，但是ENTRYPOINT為了提供穩定且不可被覆蓋的操作。通過在命令行中指定--entrypoint 命令的方式，可在運行時將Dockerfile文件中的ENTRYPOINT覆蓋。- CMD，是command的縮寫。CMD用於為已創建的鏡像提供默認的操作，當不想要用默認操作時候，可用docker run  IMAGE@DIGEST 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: "postgres:${POSTGRES_VERSION}"
Compose文件 可通過自身的ARGS變量，將參數傳給Dockerfile的 ARGS 指令。

**網絡**
參考文檔： Docker文檔-網絡概要date=20200415060005 

**bridge**
在Docker裡，網橋網絡 使用的是 軟件形式的網橋。使用相同的網橋的容器連接進入該網絡，而非該網絡的容器刷故無法接入。Docker網橋驅動會自動地在Docker主機上安裝規則，這些規則讓不同橋接網絡之間不能直接通信。 橋接經常用於：在單獨容器上運行應用時，可通過 網橋 進行通信。 網橋網絡 適用於容器運行在相同地Docker守護進程的主機上。不同Docker守護進程主機上的容器，它們之間的通信需要依靠操作系統層次的路由，或者你應該使用 overlay網絡 進行代替。
bridge 是網橋驅動，是Docker默認的網絡驅動（接口名為 docker0），當你不為容器指定一個網絡時候，Docker將會使用該驅動。  可通過  daemon.json 文件修改相關配置。
自定義網橋可通過 brctl 命令進行配置。

**host**
主機模式
host 用於單獨容器，該網絡下容器只能和Docker主機進行直接連接。host 只適用於 Docker 17.06或以上版本的swarm服務。
host網絡和VirtualBox的 僅主機網絡（Host-only Networking） 類似。

**overlay**
overlay （中文：覆蓋網絡）網絡驅動將會創建分佈式網絡，該網絡可以覆蓋若干個 Docker守護進程主機。該網絡是基於 主機特定網絡（host-specific networks），允許 swarm服務 和 容器 進行安全通信（當加密功能開啟時）。在該網絡下，Docker能夠清晰地掌握 數據包的路由 以及 發送接收容器。
overlay 有兩種網絡類型網絡：- ingress 網絡，可掌控 swarm服務 的網絡流量 。該網絡是 overlay  的默認網絡。- docker_gwbridge 網絡是 網橋網絡。該網絡會將 單獨的Docker守護進程 連接至 swarm裡的另外一個守護進程。
在 overlay 網絡下，單獨的容器 和 swarm服務 的行為和配置概念 是不一樣的。
該策略不需要 容器們 具有操作系統級別的路由，因為Docker負責路由。

**macvlan**
Macvlan網絡配置提供了一種機制，允許單獨的容器具有獨立的MAC地址，使得這些容器在網絡上表現得如同物理設備。

**none**
該策略下，容器不使用任何網絡。none 常常用於連接自定義網絡驅動的情況下。

**其他**
截止2023年5月18日，Docker官方倉庫域名 https://hub.docker.com/ date=20230610172413  在中國大陸被屏蔽，方式為DNS汙染。隨後短暫解封，2024年6月6日再次被封。

**數據管理**
Docker默認下，所有文件將會存儲在容器裡的可寫的容器層（container layer）。- 數據與容器為一體。隨著容器消失，數據將消失；難以與其他程序（容器）共享。可以採用掛載文件的方式解決。- 由於容器的寫入層是與宿主機器緊緊耦合。所以你難以移動數據到其他機器。- 容器的寫入層的是通過  存儲驅動date=20200218205357 （storage driver） 管理文件系統。 存儲驅動date=20200218205357  會使用Linux內核的 鏈合文件系統（union filesystem）進行掛載。相比起直接操作於宿主機器文件系統的 數據卷，這額外的抽象層將會降低性能。
容器有兩種永久化存儲方式：卷（volumes）和 綁定掛載（bind mounts）。另外，Linux用戶還可使用 tmpfs 進行掛載；Window用戶還可以使用 命名管道（named pipe）。在容器中，不管是哪種永久化存儲，表現形式都是一樣的。

**卷**
卷（volumes）是宿主機器的文件系統的一部分，由Docker進行管理（ 在Linux，存儲於/var/lib/docker/volumes/）。非Docker程序不應該去修改這些文件。Docker推薦使用 卷 進行持久化數據。 卷 可支持 卷驅動（volume drivers），該驅動允許用戶將數據存儲到 遠程主機 或 雲服務商（cloud provider）或 其他。
沒有名字的卷叫匿名卷（anonymous volume），有名字的卷叫命名卷（named volume）。匿名卷沒有明確的名字，當被初始化時，會被賦予一個隨機名字。

**綁定掛載**
綁定掛載（bind mounts）通過將宿主機器的路徑掛載到容器裡的這種方式，從而數據持續化，因此綁定掛載可將數據存儲在宿主機器的文件系統的任何地方。非Docker程序可修改這些文件。 綁定掛載是Docker早期就存在的，相比起卷，綁定掛載十分簡單明瞭。 在開發Docker應用時，應使用命名卷（named volume）代替綁定掛載，因為用戶不能對綁定掛載進行 Docker CLI 命令操作。
綁定掛載常用於：- 同步配置文件，如： 將 宿主主機的DNS配置文件（/etc/resolv.conf）同步至容器中- 在開發程序時，將 源代碼 或 Artifact 同步至容器中。 這種用法與 Vagrant 類似。

**tmpfs**
tmpfs 掛載（tmpfs mounts），僅僅存儲於內存中，並不操作 宿主機器的文件系統（不持久化於磁盤）。它可用於存儲一些 非持久化狀態、敏感數據。 舉例，swarm服務 通過tmpfs 將  secretsdate=20200321112911 （密碼、密鑰、證書等）存儲到swarm服務。 

**命名管道**
命名管道（named pipes），通過 npipe 掛載的形式，使 Docker主機 和 容器 之間能互相通訊。常見用例是在容器內運行第三方工具，並使用命名管道連接到Docker Engine API。

**覆蓋問題**
當掛載 空的卷 至一個目錄中，目錄中的內容會被複制於卷中（不會覆蓋）。如果掛載 非空的卷 或 綁定掛載 至一個目錄中，那麼該目錄的內容將會被隱藏（obscured ），當卸載後內容將會恢復顯示。

**日誌**
在UNIX和類Unix系統中，常見的 I/O流（I/O streams） 分為三種：STDIN（輸入 ）、 STDOUT（正常輸出）、STDERR（錯誤輸出）。
默認配置下，Docker的日誌（如：docker logs、docker service log）所記載的是命令行的輸出結果（STDOUT和STDERR）。而STDOUT 和 STDERR 對應的文件路徑分別是 /dev/stderr和/dev/stdout。 另外，也可以在宿主主機上查看容器的日誌，使用以下命令可以查看到容器的日誌位置。
$ docker inspect --format= $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        kindest/node:v1.17.0   "/usr/local/bin/entr…"   4 minutes ago       Up 4 minutes        127.0.0.1:32769->6443/tcp   kind-control-plane

**歷史**
Docker命令在過去的發展中誕生了40種以上的命令，過多的命令導致混亂以及難以使用tab自動補充，因此在docker 1.13版本（2017.1.19）中，命令行被重構，根據邏輯對象進行劃分。官方建議用戶使用新的語法進行操作。

**已過時**

**Docker Swarm**
參考Swarm Mode章節。

**Docker Machine**
Docker Machine 是一個工具，它允許你在虛擬宿主機上安裝 Docker引擎，並使用 docker-machine 命令管理這些宿主機。你可以使用 Machine 在你本地的 Mac 或 Windows box、公司網絡、數據中心、或像 AWS 或 Digital Ocean 這樣的雲提供商上創建 Docker 宿主機。
Docker Machine 最後更新時間是在0.16.0 (2018-11-08)版本。官方建議在1.12以及之後版本使用Docker Desktop for Mac和Docker Desktop for Windows進行代替。

**Docker Toolbox**
Docker Toolbox是用於幫 Windows系統和Mac系統 安裝Docker環境。新版本建議使用Docker Desktop for Mac和Docker Desktop for Windows進行安裝。最後更新版本是 19.03.1(2019-08-01)。

**安全性爭議**
2021年，安全公司Palo Alto Networks研究人員Aviv Sasson，在Docker Hub上發現的惡意容器映像存檔，分別來自10個不同帳號，總下載次數超過2000萬次，其中內含的挖礦軟體。

**參考文獻**

**外部連結**
  Source code repositorydate=20190201052505 -  Multi-tenancy using Dockerdate=20141110083528 -  Docker 101 Tutorialdate=20141012120005 -  libcontainer git repodate=20140816072508 -  如何在Linux下安裝Dockerdate=20170102080531 -  Windows 容器date=20180305063147  - 在 Windows 10 部署 Docker

**參見**
 作業系統層虛擬化- cgroups- LXC- Dotcloud