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

一、什麼是容器

容器簡介

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

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

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

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

image-20230517200139565

Docker 的口號:

Develop faster. Run anywhere.

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

容器的實質是進程。但與直接運行在宿主機上的進程不同,容器進程運行在屬於自己獨立的命名空間。因此,容器可以擁有自己獨立的 root 文件系統、網絡配置、進程空間、自己的用戶 ID 空間等等。

容器的一些特性總結:

  1. 它是鏡像(image)的一個運行實例。比如你能夠使用 docker api 或 cli 創建、啓動、停止、移動或刪除容器。
  2. 它可以在本地機器、虛擬機或雲服務器上運行。
  3. 它可以在任何操作系統上運行。
  4. 它可以與其它容器隔離並運行自己的軟件、二進制文件和配置信息。
  5. 它可以自包含一些軟件,這樣就可以使應用程序幾乎在任何地方以相同的方式運行。

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

容器解決了什麼問題

我們把應用程序開發完之後,部署到服務器上時,會有很多軟件需要部署,比如部署 PHP 程序開發的應用項目,就有 MySQL,Redis,Nginx 等各種軟件需要部署。

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

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

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

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

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

image-20230531134410289

​ (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和虛擬機比較

image-20230516200027411

(來自 kubernetes 官網)

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

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

  • 容器直接運行在容器運行時上,容器運行時直接運行在宿主機的內核裏,它也不需要進行硬件虛擬化。

虛擬機和容器的比較:

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

五、Docker架構和執行流程

Docker 整體架構

Docker 整體架構圖:

image-20230516202647251

​ (來自: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 執行流程畫出來了。只不過看起來不太明顯,在簡化下:

image-20230517182349311

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

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

比如 docker 構建:在 docker 客戶端發出命令,docker 主機的守護進程接收命令,然後它通過鏡像來運行出一個容器。

docker 底層技術

請看下面的架構圖:

image-20230529144517118

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

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

  • Namespace:每個容器都有自己獨立的命名空間,運行在其中的應用像是在獨立操作系統上運行。命名空間保證了容器彼此不受影響。
  • CGroups:對共享資源進行隔離、限制等。比如對CPU、內存的限制。
  • Union FS:聯合文件系統是一種分層、輕量級且高性能的文件系統。

Docker 使用存儲驅動程序(storage driver)來存儲 image 的圖像層,將數據存儲在容器的可寫層中。

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

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

image-20230529150803868

​ (來源docker storage driver:images and layers

image-20230531141421811

​ (圖片來源網絡侵刪)

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

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

八、參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章