一、基本概念
如果我們想要讓軟體執行起來,首先要保證作業系統的設定,其次還需要依賴各種元件和庫的正確安裝。那麼虛擬機器就是一種帶環境安裝的一種解決方案,它可以實現在一種作業系統裡面執行另外一種作業系統,但是虛擬機器的缺點也是十分明顯的,資源佔用多、冗餘步驟多、啟動速度慢。由於虛擬機器存在的這些令人詬病的缺點。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中的一條指令。
下面我們來學習下一些基本的命令:
- docker image ls,檢視全部映象。欄位含義如下:
REPOSITORY 倉庫地址 TAG 標籤 IMAGE_ID 映象ID CREATED 建立時間 SIZE 映象大小 - docker search [imageName],查詢映象。欄位含義如下:
欄位 含義 NAME 名稱 DESCRIPTION 描述 STARTS 星星的數量 OFFICIAL 是否官方源 - docker history [imageName],檢視映象歷史。
- docker inspect [imageName],顯示一個或多個映象資訊。
- docker pull [imageName],拉取映象。
- docker push [imageName],推送一個映象到映象倉庫。
- docker rmi [imageName],刪除映象。
- docker image prune,移除未使用的映象,沒有標記或被任何容器引用。
- tag,標記本地映象,將其歸入某一倉庫
- 語法:docker tag [OPTIONS] IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]。
- 例子:docker tag centos:7 zaking/centos:v1。
- export,將容器檔案系統作為一個tar歸檔檔案匯出到STDOUT。
- 語法:docker export [OPTIONS] CONTAINER。
- docker export -o hello-world.tar b2712f1067a3。
- import,匯入容器快照檔案系統tar歸檔檔案並建立映象。
- 語法:docker import [OPTIONS] file/URL/- [REPOSITORY[:TAG]。
- 例子:docker import hello-world.tar。
- save,將指定檔案儲存成tar檔案。
- 語法:docker save [OPTIONS] IMAGE [IMAGE...]。
- docker save -o hello-world.tar hello-world:latest。
- load,載入tar檔案並建立映象。
- 例子:docker load -i hello-world.tar。
- 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映象檔案和容器檔案。關閉容器並不會刪除容器檔案,只是停止容器的執行。
下面,我們來學習一下容器有關的命令:
- 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:。
- docker ps:檢視容器。
- 引數:
- -a:顯示所有的容器,包括已停止的。
- -l:顯示最新的那個容器。
欄位 含義 CONTAINER ID 容器ID IMAGE 使用的映象 COMMAND 使用的命令 CREATED 建立時間 STATUS 狀態 PORTS 埠號 NAMES 自動分配的名稱
- 引數:
- docker run -i -t ubuntu /bin/bash:執行互動式的容器。可以通過exit命令或CTRL+D退出互動介面。
- -t=--interactive 在新容器內指定一個偽終端或終端。
- -i=--tty 允許你對容器內的標準輸入 (STDIN) 進行互動。
- docker kill:kill是不管容器同不同意,直接執行
kill -9
,強行終止;stop的話,首先給容器傳送一個TERM
訊號,讓容器做一些退出前必須的保護性、安全性操作,然後讓容器自動停止執行,如果在一段時間內,容器還是沒有停止,再進行kill -9,強行終止。
- 例子:docker kill 5a5c3a760f61。
- docker rm:刪除容器。
- 例子:docker rm 5a5c3a760f61。
- docker rm $(docker ps -a -q)。刪除所有的容器,-a,所有的,-q顯示id號。就是批量刪除所有的意思。
- docker start [containerId]:啟動容器。
- docker stop [containerId]:停止容器。
- docker attach [containerID]:進入一個容器。
- docker container -exec -it [containerID] /bin/bash:進入一個正在進行中的容器。
- docker container cp [containerID]/readme.md .:拷貝檔案。
- docker run --rm ubuntu /bin/bash:自動刪除。
- docker container stats:顯示容器資源使用統計。
- docker container top:顯示一個容器執行的程式。
- docker update -m 500m 6d1a25f95132:更新一個或多個容器配置。
- 列出指定的容器的埠對映:
docker run -d -p 8080:80 nginx docker container port containerID
-
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 [你自己剛才生成的映象名字]
然後,在另一個終端訪問下:
直接就出來了,不需要我們再重新建立了。當然,如果要釋出到遠端倉庫,需要註冊賬號。這個我就不多說了,大家有興趣可以自己試一下。
好啦,關於容器和映象的部分。就先到這裡了。