《前端運維》三、Docker--1映象與容器

Zaking發表於2022-03-25

一、基本概念

  如果我們想要讓軟體執行起來,首先要保證作業系統的設定,其次還需要依賴各種元件和庫的正確安裝。那麼虛擬機器就是一種帶環境安裝的一種解決方案,它可以實現在一種作業系統裡面執行另外一種作業系統,但是虛擬機器的缺點也是十分明顯的,資源佔用多、冗餘步驟多、啟動速度慢。由於虛擬機器存在的這些令人詬病的缺點。Linux發展出了另一種虛擬化技術,Linux Containers,即Linux容器,縮寫為LXC。

  Linux容器並沒有虛擬一個完整的作業系統,而是對程式進行隔離。或者說,在正常程式的外面套了一層保護層。對於容器裡面的程式來說,它接觸到的各種資源都是虛擬的,從而實現與底層系統的隔離。Linux的容器也十分明顯,體積小、啟動快、資源佔用也是極少的。

  Docker屬於Linux容器的一種封裝,提供簡單易用的容器使用介面。它是目前最流行的Linux容器解決方案。Docker將應用程式與該程式的依賴,打包在一個檔案裡面。執行這個檔案,就會生成一個虛擬容器。程式在這個虛擬容器裡面執行,就好像在真實的物理機上執行一樣。

  同時Docker的應用場景也十分廣泛,比如:單專案打包、整套專案打包、新開源技術、環境一致性、持續整合、微服務、彈性伸縮等。

  下面我們來看一張圖,來學習下Docker體系的結構:

  我們看上圖哦,Docker通過Docker Client的客戶端傳送指令,驅動Docker Engine引擎來啟動容器,然後通過Containerd來管理對應容器的內容,然後,shim只用來管理每個獨立的容器,通過runC這個輕量級的工具來啟動容器。在啟動容器的時候,可能會去Image Repository映象倉庫中去取對應的依賴。

  Docker提供了一些內部的元件,我們也需要了解一下:

  • namespaces,名稱空間,Linux核心提供的一種對程式資源隔離的機制,例如程式、網路、掛載等資源。
  • cgroups,控制組,linux核心提供的一種限制程式資源的機制,例如cpu、記憶體等資源。
  • unonFS,聯合檔案系統,支援將不同位置的目錄掛載到同一虛擬檔案系統中,形成一種分層的模型。

二、Docker安裝

  首先docker的版本型別上,分為企業版和社群版,我們們用社群版就可以了,企業版是付費的。它的安裝文件地址在:https://docs.docker.com/engine/install/centos/

  我們通過下面的命令來安裝下docker:

  先安裝docker的一些依賴:

yum install -y yum-utils   device-mapper-persistent-data   lvm2

  再安裝docker的安裝源:

yum-config-manager     --add-repo     https://download.docker.com/linux/centos/docker-ce.repo

  最後安裝docker:

yum install docker-ce docker-ce-cli containerd.io -y

  這樣,我們的docker就安裝好了。然後我們看下常用的一些命令:

# 啟動docker
systemctl start docker
# 檢視docker資訊
docker version
docker info
# 解除安裝docker
yum remove docker
# 刪除docker相關的資料夾
rm -rf /var/lib/docker

  我們也可以把相關的軟體依賴改成阿里雲的映象地址,這樣下載的時候會快一些,我就不多說了,因為我沒改:

# 建立一個檔案
sudo mkdir -p /etc/docker
# 寫入一些配置
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://fwvjnv59.mirror.aliyuncs.com"]
}
EOF
# 過載所有修改過的配置檔案 
# daemon-reload: 重新載入某個服務的配置檔案
sudo systemctl daemon-reload
sudo systemctl restart docker

三、Docker映象

   Docker把應用程式及其依賴,打包再image映象檔案裡面,只有通過這個檔案,才能生成Docker容器。image映象檔案可以看作是容器的模板。Docker根據image映象檔案生成容器的例項。同一個image映象檔案,可以生成多個同時執行的image例項。映象檔案不是一個單一的檔案,而是有多層次的結構。容器其實就是在image映象的最上面一層加了一層讀寫層。在執行容器裡做的任何檔案改動,都會寫到這個讀寫層裡。如果容器刪除了,最上面的讀寫層也就刪除了,改動也就丟失了。

  我們可以通過docker history [id/name] 檢視映象中各層級的內容及大小,每層對應著dockerfile中的一條指令。

  下面我們來學習下一些基本的命令:

  1. docker image ls,檢視全部映象。欄位含義如下:
    REPOSITORY 倉庫地址
    TAG 標籤
    IMAGE_ID 映象ID
    CREATED 建立時間
    SIZE 映象大小
  2. docker search [imageName],查詢映象。欄位含義如下:
    欄位含義
    NAME 名稱
    DESCRIPTION 描述
    STARTS 星星的數量
    OFFICIAL 是否官方源
  3. docker history [imageName],檢視映象歷史。
  4. docker inspect [imageName],顯示一個或多個映象資訊。
  5. docker pull [imageName],拉取映象。
  6. docker push [imageName],推送一個映象到映象倉庫。
  7. docker rmi [imageName],刪除映象。
  8. docker image prune,移除未使用的映象,沒有標記或被任何容器引用。
  9. tag,標記本地映象,將其歸入某一倉庫
    • 語法:docker tag [OPTIONS] IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]。
    • 例子:docker tag centos:7 zaking/centos:v1。
  10. export,將容器檔案系統作為一個tar歸檔檔案匯出到STDOUT。
    • 語法:docker export [OPTIONS] CONTAINER。
    • docker export -o hello-world.tar b2712f1067a3。
  11. import,匯入容器快照檔案系統tar歸檔檔案並建立映象。
    • 語法:docker import [OPTIONS] file/URL/- [REPOSITORY[:TAG]。
    • 例子:docker import hello-world.tar。
  12. save,將指定檔案儲存成tar檔案。
    • 語法:docker save [OPTIONS] IMAGE [IMAGE...]。
    • docker save -o hello-world.tar hello-world:latest。
  13. load,載入tar檔案並建立映象。
    • 例子:docker load -i hello-world.tar。
  14. build,根據Dockerfile構建映象。
  • 語法:docker build [OPTIONS] PATH / URL / -。
  • 例子:docker build -t zf/ubuntu:v1。

  然後,我們學習了一些相關的命令,下面我們來拿這些命令做一些實踐:

  首先,我們查詢一下centos映象:

docker search centos

  然後,我們把centos的映象拉取到本地,如果你這裡下載很慢的話,請回頭安裝阿里源,嘻嘻:

docker pull centos

  然後,我們可以使用fs命令,檢視下現在有哪些映象:

docker image ls

  下一步我們從遠端映象倉庫拉取一個docker官方的例子映象到本地的映象倉庫:

docker pull docker.io/hello-world

  然後,可以通過rmi命令,刪除本地映象:

docker rmi hello-world

 

四、Docker容器

   首先,我們來學習下一些有關於容器的基本概念。docker run 命令會從image映象檔案中生成一個正在執行的容器例項。該命令具有自動抓取image映象檔案的功能,如果發現本地沒有指定的image檔案,就會從倉庫自動抓取。輸出提示後,例項就會停止執行,容器自動終止,當然,並不是所有的容器都會自動終止。同過image映象檔案生成的生成的容器例項,本身也是一個檔案,成為容器檔案。生成了容器後,就會同時存在兩個檔案,image映象檔案和容器檔案。關閉容器並不會刪除容器檔案,只是停止容器的執行。

  下面,我們來學習一下容器有關的命令:

  1. docker run:啟動容器。
    • 例子:docker run ubuntu /bin/echo 'hello world'。這句話的意思就是,通過ubuntu映象生成一個容器,在容器中執行/bin/echo 'helloworld'的命令。我們看下圖,當我們想要執行的命令在容器中列印後,該容器就自動終止了。這就是我們上面說到的含義。另外,如果本地沒有對應的映象,docker會自動去docker hub拉取。
    • 引數:
      • -i,--interactive:互動式。
      • -t,-tty:分配一個偽終端。
      • -d,--detach:執行容器到後臺。
      • -a,--attach list:附加到執行的容器。
      • -e,--env list:設定環境變數。
      • -p,--publish list:釋出容器埠到主機。
      • -P,--publish-all:。
  2. docker ps:檢視容器。
    • 引數:
      • -a:顯示所有的容器,包括已停止的。
      • -l:顯示最新的那個容器。
        欄位含義
        CONTAINER ID 容器ID
        IMAGE 使用的映象
        COMMAND 使用的命令
        CREATED 建立時間
        STATUS 狀態
        PORTS 埠號
        NAMES 自動分配的名稱
  3. docker run -i -t ubuntu /bin/bash:執行互動式的容器。可以通過exit命令或CTRL+D退出互動介面。
    • -t=--interactive 在新容器內指定一個偽終端或終端。
    • -i=--tty 允許你對容器內的標準輸入 (STDIN) 進行互動。
  4. docker kill:kill是不管容器同不同意,直接執行kill -9,強行終止;stop的話,首先給容器傳送一個TERM訊號,讓容器做一些退出前必須的保護性、安全性操作,然後讓容器自動停止執行,如果在一段時間內,容器還是沒有停止,再進行kill -9,強行終止。
    • 例子:docker kill 5a5c3a760f61。
  5. docker rm:刪除容器
    • 例子:docker rm 5a5c3a760f61。
    • docker rm $(docker ps -a -q)。刪除所有的容器,-a,所有的,-q顯示id號。就是批量刪除所有的意思。
  6. docker start [containerId]:啟動容器
  7. docker stop [containerId]:停止容器。
  8. docker attach [containerID]:進入一個容器。
  9. docker container -exec -it [containerID] /bin/bash:進入一個正在進行中的容器。
  10. docker container cp [containerID]/readme.md .:拷貝檔案。
  11. docker run --rm ubuntu /bin/bash:自動刪除。
  12. docker container stats:顯示容器資源使用統計。
  13. docker container top:顯示一個容器執行的程式。
  14. docker update -m 500m 6d1a25f95132:更新一個或多個容器配置。
  15. 列出指定的容器的埠對映:
    docker run -d -p 8080:80 nginx 
    docker container port containerID 
  16. docker logs [containerId]:檢視docker容器的輸出。

  下面,我們把上面學習的命令來實踐一下:

  剛才我們在學習run命令的時候已經啟動了一個容器並列印出了命令,那個是最基礎的方法,那下面,我們來檢視下我們的容器都有哪些:

docker ps -a

   哈,只有一個,就是我們剛才執行的那個。下面我們來試一下啟動一個互動式的容器:

docker run -i -t ubuntu /bin/bash 

  我們就進入了互動式容器的偽終端裡,可以進行命令互動。然後我們執行下面的命令:

docker run centos ping www.baidu.com

  執行了這個命令後,就會一直ping www.baidu.com,別的事就幹不了了,只能看著:

  此時,我們就需要--detach引數,進入後臺執行:

docker run --detach centos ping www.baidu.com

  然後,這個容器就會在後臺執行:

   那,我想要檢視這個容器裡面的日誌怎麼辦呢,通過下面的命令就可以檢視對應容器裡的日誌了:

docker logs --follow [id/name]

  當然,我們也可以通過attach,重新進入這個容器。

docker attach [id]

  然後,可以通過stop命令,停止某個正在執行中的容器:

docker stop [containerId]

   docker stop是否能停止,是由容器內部指定的,需要執行完一些必要的容器才會停止。如果你希望可以立即殺死該容器,直接強行終止,就使用kill命令。停止了以後,我們可以通過docker start來重新啟動。

  然後,我們可以通過rm命令,刪除已有的容器:

docker ps -a

  先通過ps命令看下目前容器的id,然後通過rm刪除:

docker rm [id]

  這樣一個一個刪除太慢了,我們可以通過下面的命令批量刪除:

docker rm $(docker ps -a -q)

  很簡單吧。

 

1、其它命令實踐:

  下面我們來練習下其他命令,我們先啟動個hello-world的容器:

docker run hello-world

  然後我們把這個容器匯出:

docker export -o hello-world.tar [cantainerId]

  然後我們看下這個檔案:  

   刪除這個容器:

docker rm [containerId]

  然後映象檔案也刪除掉:

docker rmi hello-world

   然後,我們可以通過import命令,把剛才匯出的tar包,再匯入回來:

docker import hello-world.tar

   就是這個了。

   save命令可以把指定映象打包成tar檔案:

docker save -o redis.tar redis:latest

  然後刪除你剛才打包成tar的映象,怎麼刪除我就不說了啊。刪除了之後,我們可以通過load命令,把剛才的tar包下載回來。

docker load -i redis.tar

  使用者既可以使用 docker load 來匯入映象儲存檔案到本地映象庫,也可以使用 docker import 來匯入一個容器快照到本地映象庫。這兩者的區別在於容器(import)快照檔案將丟棄所有的歷史記錄和後設資料資訊(即僅儲存容器當時的快照狀態),而映象(load)儲存檔案將儲存完整記錄,體積也要大。此外,從容器(import)快照檔案匯入時可以重新指定標籤等後設資料資訊。

 2、下面我們來實踐一些容器相關的:

  我們先後臺跑起來前面的那個ping命令:

docker run --detach centos ping www.baidu.com

  然後,我們來用stats看下它的狀態:

docker stats [containerId]

   然後可以通過top命令,檢視一個執行中容器的程式:

docker top [containerId]

   我們還可以使用update命令更新一個或多個容器的配置,看stats那個圖,LIMIT是1.7G左右,我們來通過update命令,限制一下它的記憶體:

docker update -m 500m [containerId]

   可惜報錯了,他跟你說還要同時設定memoryswap,設定一下唄:

   然後LIMIT就變成了500M,簡單吧。

3、下面我們來實踐下如何對映指定容器的埠:

  先使用下面的命令,啟動一個docker容器中的nginx:

docker run -d -P nginx

  這樣會自動指定與宿主機的埠對映。

   圖中紅框的部分就是自動指定的與宿主機的對映,我們也可以手動設定:

docker run -d -p 8080:80

   這個意思就是說宿主機的ip是8080埠對映到docker容器的nginx的80埠。

4、學習下如何commit命令製作個性化映象:

  我們先停止並刪除之前所有的容器:

docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)

  然後像之前的例子一樣,啟動一個nginx容器。

  通過下面的命令進入到容器的偽終端中:

docker exec -it [containerId]/bin/bash

  然後,我們進入到容器的nginx儲存html檔案的目錄,/usr/share/nginx/html:

cd /usr/share/nginx/html

  建立一個html檔案:

echo hello > hello.html

  然後我們再開啟一個命令列,訪問一下剛才的nginx服務,要注意檢視埠號哦:

   這樣就成功了。下面看下如何基於這個容器,建一個新的映象:

docker commit -m'zakings nginx' -a'zaking' 0a90e57ca86b zaking/zakingnginx

  這段程式碼是什麼意思呢,docker commit -m'描述資訊' -a'作者資訊' [containerId] [包名]。

   我們可以檢視下:

   多了我們剛才生成的映象。下面我們清空下容器,使用我們自己建立的映象建立容器:

   不多說了,實踐好多遍了。

  然後呢,實際上就是跟之前的方式一樣,建立nginx容器,並自動設定埠號就好了:

docker run -d -P [你自己剛才生成的映象名字]

   然後,在另一個終端訪問下:

   直接就出來了,不需要我們再重新建立了。當然,如果要釋出到遠端倉庫,需要註冊賬號。這個我就不多說了,大家有興趣可以自己試一下。

  好啦,關於容器和映象的部分。就先到這裡了。

相關文章