kubernetes(k8s)大白學習02:容器和docker基礎、使用、架構學習

2023-05-31 21:00:55

一、什麼是容器

容器簡介

簡單說:容器(container)就是計算機上的一個沙盒程序,它與計算機上的所有其它程序相隔離。

這種隔離是怎麼做到的呢?它利用了核心提供的 namespace 和 cgroup 這 2 種技術。這些技術能力在 Linux 中已經存在了很長時間。而 Docker 或容器技術致力於將這些功能更易於使用和更方便使用。容器技術把 linux 中已存在的這些技術顯性化了,讓使用者容易操作使用,體驗更好。

」沙盒「就像是一個集裝箱,能夠把應用及其相關依賴軟體裝在一起。在 docker 的隔離下,應用和應用之間就有了邊界,相互隔離不被打擾,也方便「搬來搬去」,搬到各種伺服器環境中執行。

Docker 的 logo 是一條鯨魚駝著許多"四方盒子「 - 標準集裝箱,很形象的表達。把軟體打包標準化,像一個一個集裝箱,可以方便快捷運輸到各種伺服器環境中並安裝。

Docker 的口號:

Develop faster. Run anywhere.

Docker 是容器技術的一種實現,還有其它容器比如 Podman,Container 等。

容器的實質是程序。但與直接執行在宿主機上的程序不同,容器程序執行在屬於自己獨立的名稱空間。因此,容器可以擁有自己獨立的 root 檔案系統、網路設定、程序空間、自己的使用者 ID 空間等等。

容器的一些特性總結:

  1. 它是映象(image)的一個執行範例。比如你能夠使用 docker api 或 cli 建立、啟動、停止、移動或刪除容器。
  2. 它可以在本地機器、虛擬機器器或雲伺服器上執行。
  3. 它可以在任何作業系統上執行。
  4. 它可以與其它容器隔離並執行自己的軟體、二進位制檔案和設定資訊。
  5. 它可以自包含一些軟體,這樣就可以使應用程式幾乎在任何地方以相同的方式執行。

比如開發人員在自己筆電上建立並測試好的容器,無須修改就可以在生產系統的虛擬機器器、伺服器等上面執行。

容器解決了什麼問題

我們把應用程式開發完之後,部署到伺服器上時,會有很多軟體需要部署,比如部署 PHP 程式開發的應用專案,就有 MySQL,Redis,Nginx 等各種軟體需要部署。

部署的伺服器環境呈現多樣化,比如物理伺服器,雲伺服器,虛擬機器器等,不同伺服器上安裝的作業系統可能又不同,執行環境不同,依賴各不同。

面對這種多個軟體需要部署,不同的伺服器環境、不同的作業系統,環境差異這麼大,如何能做到一鍵部署且遮蔽彼此的各種差異?如何做到構建一次完之後就能部署到各種不同的伺服器環境中?也就是,一次構建,多地多次部署,且都能順利執行。

這時容器技術就可以解決這些問題。容器能夠把應用程式及其依賴的軟體打包到一個容器中,然後釋出到各種伺服器上。

這樣就能加快執行環境搭建、應用程式的部署,解決了運維效率和成本高的一些問題。

一次構建,隨時隨地搬運,任意環境執行

​ (Build,Ship and Run Anywhere)

Docker 還提供了一種類似「程式設計的方式」來方便構建映象:Dockerfile。

二、什麼是映象

映象(Container Image)是一個模板,一種容器化標準化交付物,容器應用打包的標準格式,用於打包應用程式及其依賴環境。

容器和映象的關係,這個就相當於物件導向程式語言中,類(container image)和範例(container instance)的關係。映象是靜態定義,容器是映象執行時的實體。容器可以被建立、啟動、刪除、暫停等。

容器映象是一個隨時可以執行的軟體包,當執行一個容器時,它使用一個隔離的檔案系統,這個自定義的檔案系統包含應用程式所需的依賴項、設定、指令碼、二進位制檔案等,映象也包含其它平臺的設定。

我們可以借用 Buildah 等開源工具,來建立相容 OCI 和 Docker 的映象檔案。

Dockerfile 是用來構建映象的文字檔案,文字內容包含了構建映象所需的指令和說明。Docker 等工具可以通過讀取 Dockerfile 中的指令自動構建生成容器映象。

三、映象倉庫

映象倉庫(container repository)是儲存、分發映象檔案的地方。這些映象檔案放在映象倉庫裡。映象倉庫可以是開放的映象倉庫,例如 docker hub;也可以是自建的映象倉庫,比如用 docker-registryharborNexus 等。

四、什麼是Docker

Docker 簡介

Docker 是用 Go 開發實現,基於 linux 的 cgroup,namespace 和 UniosFS 等主要技術,對程序進行封裝隔離,在作業系統之上的虛擬化技術。隔離的程序是獨立於宿主和其它程序,它又稱為容器。

Docker 容器,又進一步的封裝,從檔案系統、網路到程序隔離等,簡化了容器的建立、啟動、刪除等操作。Docker 技術比虛擬機器器技術更為輕便。

Docker 可以快速、一致性的交付你的應用程式。

Docker和虛擬機器器比較

(來自 kubernetes 官網)

從上圖軟體交付的變化歷程圖可以看出,容器和傳統虛擬機器器的不同。

  • 傳統虛擬機器器是虛擬出一套硬體,在其上執行完整作業系統,在這之上再來執行各種應用軟體。

  • 容器直接執行在容器執行時上,容器執行時直接執行在宿主機的核心裡,它也不需要進行硬體虛擬化。

虛擬機器器和容器的比較:

特點 容器 虛擬機器器
隔離性 較弱的隔離 強隔離
啟動速度 秒級 分鐘級
映象大小 最小的幾 MB 幾百 MB 到幾個 GB
效能(與裸機比) 損耗小於 2% 損耗 15% 左右
系統支援數量 單機可支援 100 個到 1000 個容器 單機支援 10 到 100 個左右
安全性 1.容器內的使用者從普通使用者許可權提升到root使用者,就直接具備宿主機root許可權 2. 容器中沒有硬體隔離,這使得容器攻擊彼此牽連 1.虛擬機器器租戶root許可權和主機的root許可權是分離的 2.硬體隔離技術:防止虛擬機器器彼此互動

五、Docker架構和執行流程

Docker 整體架構

Docker 整體架構圖:

​ (來自:docker docs architecture

Docker 架構是一個使用者端-伺服器端架構,使用者端是 Client,伺服器端是 Docker Host。後面的 Registry 是一個映象倉庫。

Docker 使用者端與 Docker daemon 守護行程進行通訊,守護行程負責構建、執行和分發 Docker 容器。Docker 使用者端和 Docker 守護行程直接進行資訊互動。Docker 還有另外一個使用者端 Docker Compose,它處理一組容器組成的應用程式。

Client :docker 使用者端。docker rundocker builddocker pull,都是 docker 裡的命令。

  • docker build:執行 docker 構建命令,會根據 docker 檔案構建一個映象存放在本機上。
  • docker run:執行 docker 啟動命令,它會將映象執行為容器。
  • docker pull:該命令從映象倉庫拉取映象檔案至本地 docker 主機,或將本地映象推播至遠端映象倉庫。

Docker Host:docker 主機。Docker daemon,守護行程;Images,映象;Containers,容器。

Registry:映象倉庫,儲存映象的倉庫。

docker 執行流程

其實上面的架構圖已經把 docker 執行流程畫出來了。只不過看起來不太明顯,在簡化下:

​ (docker 命令執行流程,實線條不同顏色代表不同步驟)

從圖上可以看出,docker 使用者端發出命令,後都會與 docker host(docker 主機)互動,然後在由 docker 主機進行後面的操作。

比如 docker 構建:在 docker 使用者端發出命令,docker 主機的守護行程接收命令,然後它通過映象來執行出一個容器。

docker 底層技術

請看下面的架構圖:

​ (docker 底層技術構成簡圖)

linux kernel,docker 技術的實現依賴了 linux 底層一些技術特性:

  • Namespace:每個容器都有自己獨立的名稱空間,執行在其中的應用像是在獨立作業系統上執行。名稱空間保證了容器彼此不受影響。
  • CGroups:對共用資源進行隔離、限制等。比如對CPU、記憶體的限制。
  • Union FS:聯合檔案系統是一種分層、輕量級且高效能的檔案系統。

Docker 使用儲存驅動程式(storage driver)來儲存 image 的影象層,將資料儲存在容器的可寫層中。

Docker 映象是由一系列層(layers)構建而成,每層代表 Dockerfile 的一條指令。除了最後一層之外每一層都是唯讀的。

Docker 用 UnionFS (聯合檔案系統)把這些層聯合在一起。

​ (來源docker storage driver:images and layers

​ (圖片來源網路侵刪)

docker engine

docker engine 引擎裡的 runc 是開放容器執行時,它是 OCI(Open Container Initiative)Spec 的一個實現。

docker engine 在 linux 下提供了很多儲存驅動,Docker Storage Driver:

Docker Storage Driver
overlay2
fuse-overlayfs
btrfs and zfs
vfs
devicemapper

關於上面 docker storage driver 的更多資訊請檢視:https://docs.docker.com/storage/storagedriver/select-storage-driver/

六、Docker安裝

Docker 可以在不同的作業系統中安裝,官方安裝地址:

我在虛擬機器器中裝的 ubuntu 作業系統:

Description: Ubuntu 20.04.2 LTS, Codename: focal

該系統對應 docker 官方安裝地址:https://docs.docker.com/engine/install/ubuntu/

具體安裝 docker 就不詳細說明了,請按照官方檔案一步一步進行安裝。

我安裝的docker版本:

$ docker -v
Docker version 24.0.1, build 6802122

驗證是否安裝成功:

$ sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
719385e32844: Pull complete 
Digest: sha256:fc6cf906cbfa013e80938cdf0bb199fbdbb86d6e3e013783e5a766f50f5dbce0
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

七、Docker簡單使用

docker cli檔案地址:https://docs.docker.com/engine/reference/commandline/cli/

啟動容器

啟動容器

建立或啟動一個新容器的命令:docker run , 語法為:

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

獲取更多 docker run 幫助檔案:docker run --help

比如,下面的命令輸出一個「hello world」後,終止容器。

因為我本地沒有 ubuntu:20.04 這個映象,所以要先下載,docker run 會自動下載這個映象,命令和執行過程如下:

$ sudo docker run ubuntu:20.04 /bin/echo 'hello world'
Unable to find image 'ubuntu:20.04' locally
20.04: Pulling from library/ubuntu
ca1778b69356: Pull complete 
Digest: sha256:db8bf6f4fb351aa7a26e27ba2686cf35a6a409f65603e59d4c203e58387dc6b3
Status: Downloaded newer image for ubuntu:20.04
hello world

下載完映象後,自動執行這個映象,最後輸出了 hello world 。

啟動一個 bash 終端,允許使用者進入容器終端進行互動:

$ sudo docker run -t -i ubuntu:20.04 /bin/bash
root@049706bffe28:/#

輸入 ls 命令:

root@049706bffe28:/# ls
bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

來解釋一下 docker run -t -i 這個命令中的引數:

-t 選項讓 docker 分配一個偽終端並繫結到容器的標準輸入上

-i 互動式操作,也就是命令列模式進入容器

這2個引數也可以寫一起:docker run -it ubuntu:20.04 /bin/bash

退出容器終端可以輸入命令 exit

上面的兩個引數還可以合一起:

docker run -dit ubuntu:20.04
  • 大部分情況下,我們希望 docker 是在後臺的執行的。加 -d 指定容器執行模式, 預設不會進入容器,想要進入容器需要繼續執行指令 docker exec,下面會介紹。

如果 docker 命令太長,還可以用 \ 來換行,如下:

docker run -it --rm \
    ubuntu:20.04 \
    /bin/bash
  • -it:-i 互動操作,-t 終端,上面解釋了
  • --rm:這個參數列示容器退出後隨之將其刪除
  • ubuntu:20.04:以 ubuntu:20.04 映象為基礎來啟動容器
  • /bin/bash:放在映象後面的是命令,有一個互動式的 shell,這裡使用的 bash

啟動已停止執行容器

啟動已經停止執行容器:docker startdocker container start

重新啟動容器:docker container restart 命令將一個執行態的容器終止,然後重新啟動它

終止執行中容器:docker container stop 來終止一個執行中的容器

檢視所有的容器:

VirtualBox:~$ sudo docker ps -a
CONTAINER ID   IMAGE       COMMAND      CREATED         STATUS          PORTS     NAMES
56ca83925f03 ubuntu:20.04  "/bin/bash"  15 minutes ago  Up 15 minutes             strange_allen   
c1482012b069 ubuntu:20.04  "/bin/bash"  26 minutes ago  Exited (0) 20 minutes ago gallant_ellis     

啟動停止的容器 container id c1482012b069:

VirtualBox:~$ sudo docker start c1482012b069
c1482012b069
VirtualBox:~$ sudo docker ps -a
CONTAINER ID  IMAGE        COMMAND      CREATED         STATUS        PORTS     NAMES
56ca83925f03  ubuntu:20.04 "/bin/bash"  21 minutes ago   Up 20 minutes         strange_allen       
c1482012b069  ubuntu:20.04  "/bin/bash" 31 minutes ago   Up 8 seconds          gallant_ellis       

獲取映象

大量的映象檔案都儲存在遠端的映象倉庫中,比如 docker hub 。獲取映象的命令 docker pull ,語法為:

docker pull [OPTIONS] NAME[:TAG|@DIGEST]

  • OPTIONS:選項,比如,-a
  • NAME[:TAG|@DIGEST]:映象地址

獲取 docker pull 更詳細引數:docker pull --help

比如,拉取 ubuntu:20.04 這個映象檔案:

$ sudo docker pull ubuntu:20.04
20.04: Pulling from library/ubuntu
Digest: sha256:db8bf6f4fb351aa7a26e27ba2686cf35a6a409f65603e59d4c203e58387dc6b3
Status: Image is up to date for ubuntu:20.04
docker.io/library/ubuntu:20.04

由於前面啟動映象命令 docker run 執行了這個映象檔案,顯示 Image is up to date for ubuntu:20.04 。

拉取映象後,就可以啟動這個映象,命令 docker run

$ sudo docker run -it --rm ubuntu:20.04 bash
root@5c2a77428b80:/# 

-it-i 表示互動操作,-t 表示是一個終端

--rm:這個參數列示容器退出後會將其刪除。在預設情況下,為了排障需要,退出的容器並不會馬上刪除,觸發手動執行 docker rm。我這裡只是演示命令的執行,不需要排障,--rm 可以避免浪費空間

ubuntu:20.04:表示映象,以這個映象來作為啟動容器

bash:放在映象後面的是命令。這裡希望進入互動式 shell,所以用 bash

列出映象

列出所有映象

列出映象的命令:docker image ls ,顯示映象下載到本地後,展開後各層所佔用空間的總和。語法:

docker image ls [OPTIONS] [REPOSITORY[:TAG]]

關於 docker image ls 更多用法,可以檢視幫助命令:docker image ls --help

$ sudo docker image ls
REPOSITORY    TAG       IMAGE ID       CREATED       SIZE
hello-world   latest    9c7a54a9a43c   2 weeks ago   13.3kB
ubuntu        20.04     88bd68917189   5 weeks ago   72.8MB

列出了倉庫名、標籤、映象ID、建立時間、所佔用的空間大小。

映象ID是映象的唯一識別符號,一個映象可以對應多個標籤

列出部分映象

列出部分映象的命令:docker image ls 映象名

比如下面例子;

$ sudo docker image ls ubuntu
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
ubuntu       20.04     88bd68917189   5 weeks ago   72.8MB

還可以加過濾的引數 --filter

$ sudo docker image ls --format "{{.ID}}: {{.Repository}}"
9c7a54a9a43c: hello-world
88bd68917189: ubuntu

刪除本地映象

刪除本地映象的命令:docker image rm,語法:

docker image rm [OPTIONS] IMAGE [IMAGE...]

上面大家映象 IMAGE ,可以是映象長ID、映象短ID、映象名 或映象摘要。

比如用映象短ID來刪除映象:

$ sudo docker image ls
REPOSITORY    TAG       IMAGE ID       CREATED       SIZE
hello-world   latest    9c7a54a9a43c   2 weeks ago   13.3kB
ubuntu        20.04     88bd68917189   5 weeks ago   72.8MB

$ sudo docker image rm 189

檢視映象詳情

檢視映象詳細資訊的命令:docker image inspect

檢視映象 hello-world:latest 的詳細資訊:

docker image inspect hello-world:latest

搜尋倉庫映象

搜尋遠端倉庫映象命令:docker search

例如 檢視遠端倉庫中 ubuntu 的映象有哪些:

docker search ubuntu

進入容器

使用 -d 引數,容器啟動後可以進入後臺。

在容器啟動後,我們有時需要進入容器映象操作,命令有 docker attachdocker exec ,推薦使用 docker exec , 因為 docker attach 進入容器操作完 exit 退出後,會導致容器停止,而 exec 不會。

docker attach 進入容器:

$ sudo docker run -dit ubuntu:20.04
c1482012b06914449cafd461931eb890dec01fa8e6858233d3fcc98de9ceb4bc

$ sudo docker container ls
CONTAINER ID   IMAGE          COMMAND       CREATED          STATUS          PORTS     NAMES
c1482012b069   ubuntu:20.04   "/bin/bash"   53 seconds ago   Up 42 seconds             gallant_ellis

$ sudo docker attach c148
root@c1482012b069:/# 

上面引數 -d 表示容器啟動後會進入後臺執行。

注意:上面容器用 exit 退出後會導致容器停止執行

root@c1482012b069:/# exit
exit
VirtualBox:~$ sudo docker container ls
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

用命令檢視容器,剛才執行的容器退出了。exec 就不會。

docker exec 進入容器:

// 執行容器
VirtualBox:~$ sudo docker run -dit ubuntu:20.04
56ca83925f039f9ba087aff8a521678e2dcc87836bffede90ed2f2614aec8065

// 列出容器列表
VirtualBox:~$ sudo docker container ls
CONTAINER ID   IMAGE          COMMAND       CREATED          STATUS          PORTS     NAMES
56ca83925f03   ubuntu:20.04   "/bin/bash"   16 seconds ago   Up 13 seconds             strange_allen

// 進入容器
VirtualBox:~$ sudo docker exec -it 56ca bash
root@56ca83925f03:/# ls
bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

// 退出容器
root@56ca83925f03:/# exit
exit

退出容器後,在列出容器列表:

VirtualBox:~$ sudo docker container ls
CONTAINER ID   IMAGE          COMMAND       CREATED         STATUS         PORTS     NAMES
56ca83925f03   ubuntu:20.04   "/bin/bash"   2 minutes ago   Up 2 minutes             strange_allen

CONTAINER ID 和前面顯示的 CONTAINER ID 相同,STATUS 狀態也是 Up 2 minutes,執行狀態,容器沒有退出。

刪除容器

刪除終止狀態的容器命令:docker container rm

docker container rm strange_allen
  • 如果要刪除一個執行中的容器,加引數 -f

歡迎大家提建議,討論,點贊

八、參考