【Docker】Docker基礎知識(面試一籮筐)

小碼農(微信公眾號:標準Java)發表於2020-10-11

文章目錄

一、前言

二、為什麼需要Docker

2.1 工具和中介軟體 + 開發與運維使用Docker

工具和中介軟體

工具:因為Maven,所以統一依賴管理、統一專案結構
因為Git,所以版本管理、團隊協作
因為Docker,所以微服務部署,容器化部署

中介軟體:因為mysql叢集,所有讀寫分離、主從同步
因為訊息佇列,所有 非同步、解耦、限流
因為redis叢集 主從同步
因為高併發 後端微服務系統

Docker 是世界領先的軟體容器平臺,企業利用 Docker 可以更好的在 Linux 和 Windows 伺服器上釋出應用新功能。
開發人員利用 Docker 可以消除協作編碼時“在我的機器上可正常工作”的問題,即環境不同造成重新新增依賴的問題,這是Docker的第一個功能;
運維人員利用 Docker 可以在隔離容器中並行執行和管理應用,獲得更好的計算密度,即隔離應用之間資源的問題,這是Docker的第二個功能。

開發人員是否需要學習Docker?
Docker,開發人員不需要涉及(比較雞肋):小公司不需要涉及多個環境,不需要Docker,大公司需要涉及多個環境,但是有自己的運維團隊;
Docker,開發人員需要涉及:很多專案,開發完之後,就把開發人員抽調走了,然後留一個開發人員做運維,所以,開發人員會被做運維,需要使用Docker
小結:Java開發人員需要懂一些Docker的操作和原理,面試中能將出一個12345)

2.2 不使用Docker遇到的問題(同一個專案的更換一個環境執行就好重新部署好各種依賴、不同專案在同一Linux伺服器上相互硬體資源和軟體資源的影響)

環境(切換/配置)麻煩
一般我們寫程式的,能接觸到好幾個環境:
開發環境:自己寫程式碼的環境叫做開發環境。
測試環境:給測試去跑的環境叫做測試環境。
生產環境:測試完可以對外使用的叫做生產環境。
其實我們在學習程式設計中,很多時間都浪費在“環境”上:
如果我現在重灌了系統,我想要跑我的war/jar包,我得去安裝一下JDK、Tomcat、MySQL等配置各種的環境變數才能跑起來。
開開心心地跟著博主給出的步驟去寫Demo,但總是有Bug。(這裡我將版本/依賴也歸納在環境的範疇裡邊)。
好不容易在測試環境下跑起來了,在生產環境就各種出錯!
跟著教學視訊做分散式/叢集的專案,跑一堆的虛擬機器,每個虛擬機器都要安裝對應的環境。

應用之間需要隔離(小結:兩個應用部署到同一個伺服器上,硬體資源不隔離會衝突,一個應用將CPU用到100%會影響另一個應用,軟體資源不隔離會衝突,一個應用的依賴可能會影響另一個應用的執行
比如我寫了兩個應用(網站),這兩個應用部署在同一臺伺服器上,那可能會出現什麼問題?
第一,硬體資源不隔離會衝突:如果一個應用出現了問題,導致CPU佔100%。那另一個應用也會受到關聯,跟著一起涼涼了。
第二,軟體資源不隔離會衝突:這兩個應用是完全不同技術棧的應用,比如一個PHP,一個.NET。這兩個應用各種的依賴軟體都安裝在同一個伺服器上,可能就會造成各種衝突/無法相容,這可能除錯就非常麻煩了。

2.3 Docker是如何解決上述的問題的

解決環境(切換/配置)
什麼是映象?
回答:
第一,映象就是把想要的環境構建成一個映象,推送到網上去:其中,你早已認識映象了,在電腦重灌系統的時候,重灌windows系統需要到網上下載iso映象,在vmware上安裝centos 7.0,需要下載centos的iso映象,有了這個映象,我們就可以執行這個映象,來進行安裝系統的操作(此處省略N個下一步),於是我們的系統就裝好了。一般來說,我們去官方渠道下載的映象,都是純淨的。比如去官方下載Windows映象,裝完後之後桌面只有一個回收站。
第二,映象分層的
2.1 對於安全windows系統,從系統之家下載的映象,映象裝完可能還有360這些軟體,但系統的的確確是變了。簡單來說,就是這些映象新增了其他的東西(比如360軟體、騰訊、千千靜聽等等軟體)。因為在windows映象中家裡其他東西;
2.2 對於安裝centos映象,分為最小化安裝(安裝完之後只能命令列)和圖形化介面安裝(安裝完之後有圖形介面),兩種都是映象,後者是對前者的加強。

上面第一點,對於windows系統和linux系統,我們只是使用別人釋出在網上的映象,下載下來使用,有了Docker,我們可以自己製作映象了,映象就是把想要的環境構建成一個映象,推送到網上去
對,Docker也是這種思路,可以將我們的想要的環境構建(打包)成一個映象,然後我們可以推送(釋出)到網上去。想要用這個環境的時候,在網上拉取一份就好了。
有了Docker,我們在搭環境的時候,跟以前的方式就不一樣了。
之前:在開發環境構建出了一個war包,想跑到Linux下執行。我們得先在Linux下載好Java、Tomcat、MySQL,配置好對應的環境變數,將war包丟到Tomcat的webapps資料夾下,才能跑起來。
現在:在Linux下直接從DockerHub下,拉取一份映象(各種環境都配好了,DockerHub提供了很多映象),將映象執行起來,把war包丟進去就好了。將Docker的映象執行起來就是一兩秒的事情而已,十分方便。

解決應用之間隔離
說到這裡,就得提出一個大家可能不認識的概念:LXC(Linux Containers)—>Linux容器。

Linux容器
第一,Linux核心,提供了cgroups功能,來達成資源的區隔;
第二,Linux核心,提供了名稱空間(namespace)區隔化的功能,使應用程式看到的作業系統環境被區隔成獨立區間,包括程式樹,網路,使用者id,以及掛載的檔案系統。

小結:LXC是一個為Linux核心包含特徵的使用者介面。通過強大的API和簡單的工具,它可以讓Linux使用者輕鬆的建立和託管系統或者應用程式容器。
問題:LXC與Docker有什麼關係?
標準答案:在linux系統下,Docker就是通過lxc來實現資源隔離的。
解釋:lxc是早期版本docker的一個基礎元件,docker 主要用到了它對 Cgroup 和 Namespace 兩個核心特性的控制。新的Docker版本已經移除了對LXC的support。

Docker在Windows和Mac
問題:在windows/mac系統下,docker如何實現資源隔離?
之前,Windows和Mac使用Docker實際上就是跑了一層Linux虛擬機器。
比如在Windows下安裝的是Docker Toolbox,它需要Oracle Virtual Box來跑Docker
現在,Windows和Mac都已經原生支援Docker了。

2.4 從(物理機時代到)虛擬機器時代到容器化時代 (Docker實現容器化)

從(物理機時代到)虛擬機器時代到容器化時代 (Docker實現容器化)
物理機時代:略過,就是一個系統部署到一個物理機上,有四個缺點,Docker部落格中有講到。
虛擬機器時代:虛擬機器也能實現對應用的隔離,安裝特定的映象也能跑出我們想要的環境。
虛擬化與容器化比對:虛擬機器已經發展了很久了,為什麼我們還需要Docker呢?
在這裡插入圖片描述
容器:容器是一個應用層抽象,用於將程式碼和依賴資源打包在一起,多個容器可以在同一個機器上執行,共享作業系統核心,但各自作為獨立的程式在使用者空間中執行,與虛擬機器相比,單個容器佔用的空間比單個虛擬機器佔用的空間少(一個虛擬機器需要一個作業系統,但是所有容器共用一個作業系統),瞬間就可以啟動。
虛擬機器:虛擬機器是物理硬體層的抽象,管理程式允許多個虛擬機器在同一個物理伺服器上執行,從而將一個物理伺服器變為多個物理伺服器,每個虛擬機器都包含一個作業系統,一個或多個應用程式,必要的而二進位制檔案和庫資源(容器包含必要的二進位制檔案和庫資源,但不包含作業系統),佔用空間大,不能瞬間啟動。
小結1(包含):容器包含應用和應用執行必要二進位制檔案和庫資源;虛擬機器包含作業系統、應用和應用執行必要二進位制檔案和庫資源,區別三個:是否包含作業系統,重量還是輕量,啟動快還是啟動慢。
小結2(以什麼為單位):Docker容器比虛擬機器更加輕量,容器以程式為單位,虛擬機器以作業系統為單位,單個容器瞬間就可以啟動,但是單個虛擬機器就不行了。

2.5 面試金手指

Docker兩個功能
功能1:將一整套環境打包封裝成映象,無需重複配置環境,解決環境帶來的種種問題。
功能2:Docker容器間是程式隔離的,誰也不會影響誰。
從虛擬化到容器化:
小結1(包含):容器包含應用和應用執行必要二進位制檔案和庫資源;虛擬機器包含作業系統、應用和應用執行必要二進位制檔案和庫資源,區別三個:是否包含作業系統,重量還是輕量,啟動快還是啟動慢。
小結2(以什麼為單位):Docker容器比虛擬機器更加輕量,容器以程式為單位,虛擬機器以作業系統為單位,單個容器瞬間就可以啟動,但是單個虛擬機器就不行了。

三、Docker兩種方式

3.1 Docker處理環境問題

問題:一個新專案要釋出上線。結果測試環境跑得好好的,生產環境死活跑不起來。
標準答案:使用docker,將 專案程式碼 + 需要的依賴 全部放到生產環境中去,就解決不同環境的問題了。
附:docker的兩大優點
第一,docker對於常見的工具,提供了基礎映象的方式,docker官方的映象倉庫裡有很多映象,可以直接拉下來用,然後新的映象可以以它們為基礎,在上面commit新的東西。
第二,層與層之間的複用,減少佔用大小:docker使用了映象分層的技術,新的commit會產生新的層,可以複用一部分老的層。這樣一來製作新映象的速度還是挺快的。

在這裡插入圖片描述

3.2 把整個環境放到另外一個機器部署,提交程式碼的時候帶上dockerfile

問題:如果我要把整個環境放到另外一個機器部署,還是要拷貝整個大的映象過去吧?
標準答案:整個環境複製到另外一個機器上,通過使用dockerfile,提交程式碼的時候帶上dockerfile,dockerfile就是docker的原始碼,記錄著docker的組織方式,
dockerfile第一行指定基礎映象:這個映象基於ubuntu基礎映象,
dockerfile第二行指定映象維護者:這個映象的維護者的資訊,
dockerfile第三行RUN指定映象啟動前依次執行的命令:RUN就是要執行的shell命令,比如這裡,是在ubuntu的基礎映象上安裝一些額外的東西,
dockerfile第4行CMD指定映象啟動後執行的初始命令:是映象啟動之後執行的初始命令。
總之,映象就是一個包,把需要的東西包裝起來。
在這裡插入圖片描述
實踐:其實在網路好的情況下,下載一個映象一般來說比重新打一個映象更快,所以最終部署都是基於映象去部署,不會重新打映象了。

3.3 docker三個概念 映象、容器和遠端映象倉庫

【docker三個概念 映象、容器和遠端映象倉庫】
映象和容器:映象有點像程式碼,容器有點像程式。程式碼是存放在硬碟上的東西,而把程式碼執行起來,就會形成一個程式,程式才是跑起來的程式。只不過在docker中,我們可以進入容器,做一些操作,然後再把容器中的改動提交形成一個新的映象。映象就是映象,我們重灌系統/搞虛擬機器的時候都要用映象,沒映象哪來系統,我們安裝完映象,就可以跑起來一個系統(Windows也好、Centos也好),於是我們就可以愉快地使用我們通過映象安裝好的系統了。
在Docker中,通過映象執行起來的東西叫做容器
遠端映象倉庫:遠端映象倉庫是存放映象的地方,製作好的映象,就把它放到遠端映象倉庫,方便其他人直接用映象部署。

3.4 面試金手指

1、docker處理環境問題:容器技術docker的思考方式是,將環境一起打包映象,避免部署時的環境問題。
2、docker:dockerfile記錄映象的製作步驟
3、docker中的三個概念:映象、容器、倉庫的概念可以類比程式碼、程式、github

四、使用層面:docker常見命令

4.1 安裝Docker與HelloWorld

4.1.1 檢視當前centos版本 7.0

// 檢視當前linux版本
cat /etc/redhat-release

// 結果
CentOS Linux release 7.3.1611 (Core)

4.1.2 安裝Docker

首先我們需要安裝GCC相關的環境:

// 安裝GCC相關的環境

yum -y install gcc

yum -y install gcc-c++

如果曾經安裝過Docker(舊版本)的話,得先解除安裝,如果沒有安裝過,跳過這一步:

// 解除安裝舊Docker版本

yum -y remove docker docker-common docker-selinux docker-engine

安裝Docker需要的依賴軟體包:

// 安裝Docker需要的依賴軟體包:

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

設定stable映象倉庫(注意:我們這裡使用國內的映象地址【因為Docker 官網給出的地址在國外,太慢了!】)

// 設定stable映象倉庫:

yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

更新yum軟體包索引:

// 更新yum軟體包索引:

yum makecache fast

安裝DOCKER CE(注意:Docker分為CE版和EE版,一般我們用CE版就夠用了)

// 安裝DOCKER CE:

yum -y install docker-ce

啟動Docker

// 啟動Docker

systemctl start docker

4.1.3 接上面,啟動好docker,HelloWorld

到上面為止,我們已經啟動了Docker,下面我們檢驗一下我們執行的Docker是否正常。

首先,我們可以看看下載回來的Docker版本:

// 檢視Docker的版本

docker version   // 版本查到了,說明Docker是執行起來的啦。

我們來一發HelloWorld:

// docker的HelloWorld

docker run hello-world   // 將一個映象Image直接變為一個執行態容器Container

執行結果:docker run hello-world這條命令指示Docker去執行hello-world這個映象,但是我們本地沒有這份映象啊。所以Docker就去DockerHub拉取了一份hello-world映象,然後生成容器,最後執行容器(docker run命令 = docker create + docker start)。這個hello-world容器的功能就是一句話:Hello from Docker!。所以我們在螢幕上就可以看到這句話了。

4.2 Docker啟動tomcat

之前,沒有docker,要在一臺全新的系統上將Tomcat跑起來。我們需要做以下的事:
安裝Java,配置環境變數
安裝Tomcat
有了docker,直接在倉庫里拉一份tomcat的映象下來,將docker run映象跑起來就,就完事了!
步驟一:拉取Tomcat映象:docker pull tomcat
步驟二:docker images檢視是否有拉取到的tomcat:docker image ls
步驟三:docker run執行這個Tomcat映象,生成執行態容器 docker run -it -p 9999:8080 tomcat

4.3 下載映象,優先使用阿里映象

由於安裝的Docker預設是去Docker Hub找我們想要的映象的,官網映象太慢,直接用阿里雲給我們提供的映象
第一,我們到下面連結搜尋一下映象,比如Tomcat (這就需要我們註冊/登入一個阿里雲賬號)
https://promotion.aliyun.com/ntms/act/kubernetes.html
第二,我們可以在映象加速器上找到我們的url:
我們依照阿里雲給出的教程,就可以配置加速器了。
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-‘EOF’
{
“registry-mirrors”: [“https://cubmirje.mirror.aliyuncs.com”]
}
EOF
第三,讓配置生效,並重啟Docker
systemctl daemon-reload
systemctl restart docker

4.4 Docker命令:都是對Image和Container的操作

Docker的命令無非就是對映象、對容器進行增刪改查,沒有什麼太多新鮮的,列入如下:

3.5 Docker命令(啟動)
3.5.1 docker create 將一個靜態Image變為一個容器Container
3.5.1.1 docker create 命令的作用
3.5.1.2 docker create 命令的原理
3.5.2 docker start 將一個容器Container變為一個執行態容器Container
3.5.2.1 docker start 命令的作用
3.5.2.2 docker start 命令的底層
3.5.3 docker run 將一個映象Image直接變為一個執行態容器Container

3.6 Docker命令(列出)
3.6.1 docker ps
3.6.1.1 docker ps 列出所有執行中的容器,但是隱藏了非執行態容器的存在
3.6.1.2 docker ps -a 列出所有容器(執行態容器 + 非執行態容器)
3.6.2 docker images
3.6.2.1 docker images 列出了所有頂層(top-level)映象
3.6.2.2 docker images -a 列出了所有可讀層read layer

3.7 Docker命令 停止、暫停、刪除、commit
3.7.1 停止與暫停
3.7.1.1 docker stop 停止執行中的容器
3.7.1.2 docker kill 停止執行中的容器
3.7.1.3 docker pause 暫停執行中的容器
3.7.2 刪除
3.7.2.1 docker rm 移除非執行態容器的讀寫層
3.7.2.2 docker rmi 移除映象的可讀層
3.7.3 docker commit 將讀寫層變為只讀層,將容器變為映象

3.8 Docker命令 其他
3.8.1 docker build 重複執行命令,生成新的層
3.8.2 docker exec 在執行中的容器執行一個新程式
3.8.3 docker inspect or 提取出容器或者映象最頂層的後設資料
3.8.4 docker save 建立一個映象的壓縮檔案,這個檔案能夠在另外一個主機的Docker上使用
3.8.5 docker export 建立一個tar檔案,並且移除了後設資料和不必要的層,將多個層整合成了一個層,只儲存了當前統一視角看到的內容
3.8.6 docker history 遞迴地輸出指定映象的歷史映象

五、dockerfile中包含基礎映象依賴

容器包含應用和應用執行必要二進位制檔案和庫資源;虛擬機器包含作業系統、應用和應用執行必要二進位制檔案和庫資源

問題1:映象依賴:我們知道Tomcat執行起來需要Java的支援,那麼我們在Docker拉取下來的Tomcat映象是不是也有Java環境呢?
問題2:容器資料儲存:容器退出了(好比Linux程式退出了),容器的資料就沒了,我們想要保留容器內的資料,怎麼辦?
問題3:建立映象的方式:從上面我們可以看出,通過commit可以在原有的容器基礎上,建立出屬於我們自己的映象,還有其他方式建立新的映象嗎?

5.1 問題1:映象依賴:我們知道Tomcat執行起來需要Java的支援,那麼我們在Docker拉取下來的Tomcat映象是不是也有Java環境呢?標準答案:dockerfile都為我們考慮好了

dockerfile
Dockerfile是用來構建Docker映象的檔案,是由一系列命令和引數構成的指令碼。簡單來說:Dockerfile是映象的原始碼。

以tomcat為例,看一下tomcat的Dockerfile長的什麼樣:
我們在Dockerfile的第一行就可以發現FROM openjdk:8-jre,所以可以確定的是:在DockerHub拉取下來的Tomcat映象一定有Java環境!

對於dockerfile,基本要求是大致看懂dockerfile檔案(),然後知道dockerfile是映象的原始碼即可、通過Dockerfile檔案我們可以知道拉取下來的映象究竟是怎麼構建的。

5.2 問題2:為什麼tomcat映象比centos映象大?標準答案:映象是分層的,tomcat在centos上層,依賴的基礎映象當然比centos多

Docker Hub有很多常用的映象,比如說Centos。我們去pull一個下來看看Docker中的Centos長啥樣:
我們可以發現的是:Tomcat的SIZE竟然比Centos還要大!但按我們常規的想法,Centos的映象可能是3或4GB(現在200M),Tomcat的映象可能就200M(現在400M)。這是為什麼呢??

如果我們在pull的時候觀察得比較仔細的話,可以發現pull會拉下很多層映象:
完全pull下來的之後,我們如果使用docker images只能檢視到最終的映象,但是隻能看到最終我們拉下來的映象
如果我們使用docker images -a命令的話,可以把中間層映象都查出來:

理想效果:(在映象列表裡邊除了tomcat和centos應該還夾雜著名為的映象)

我們可以使用history命令來看看,可以發現Tomcat包含很多個映象層,使用history命令可以發現Tomcat包含很多個映象層
還可以發現一點:Dockerfile有多少條命令,那就有多少個映象層(不信你數數)

說了那麼多,就想讓大家知道:我們拉取下來的映象實際上是由很多中間層映象組成的。

對於pull下來的映象由很多層映象組成【這些映象都是精簡過的(甚至連vi命令都不支援)】,我們可以使用cd, ls等基礎命令,但無法使用vi命令(需要我自己去下載)。

因為映象分層,所以可以可以知道,因為Tomcat映象要的基礎環境比Centos映象要多,所以Tomcat映象的SIZE比Centos要大

5.3 Docker映象的三個特點

關於Docker映象,有三個特點:
1、Docker映象是由Dockerfile生成
2、Docker映象層級結構,映象層級結構造成兩種映象複用
3、每層Docker映象包含兩部分:映象檔案 + 映象json後設資料資訊

5.3.1 Docker映象是由Dockerfile生成

Docker映象示意圖

5.3.2 Docker映象層級結構,映象層級結構造成兩種映象複用

映象呈現層級結構
聯合檔案系統(UnionFS)是實現Docker映象的技術基礎。在Docker中一般使用是AUFS(Another Union File System或Advanced Multilayered Unification File System)【具體還是得看宿主機用的什麼系統】。
Docker的映象的基礎是聯合檔案系統,它支援將檔案系統中的修改資訊作為一次提交,並層層疊加,外界看到的是最外層的映象。(比如外界只看到Tomcat映象,而中間疊加了很多層映象)

映象繼承(共享)
Docker映象可以通過分層來進行繼承。

第一,高階映象共享基礎映象:hello-world的Dockerfile映象FROM scratch映象,scratch在Docker中是一個基礎映象
FROM scratch
COPY hello /
CMD ["/hello"]
Centos的Dockerfile映象也是FROM scratch映象:
FROM scratch
ADD centos-7-docker.tar.xz /
LABEL org.label-schema.schema-version=“1.0”
org.label-schema.name=“CentOS Base Image”
org.label-schema.vendor=“CentOS”
org.label-schema.license=“GPLv2”
org.label-schema.build-date=“20181205”
CMD ["/bin/bash"]
那麼Centos映象和hello-world共享同一個基礎映象層scratch,提高了儲存效率。

第二,基於COW,centos映象中放入tomcat映象,磁碟佔用會小點:比如我們有一個Centos映象大小是202M,然後,我們基於Centos映象手動往裡邊新增一個Tomcat(假設這個Tomcat的大小是300M),生成一個映象,總大小就是502M了。
如果僅僅是單純的累加這兩個映象的大小:202M+502M=704M,但是由於映象複用的存在,實際佔用的磁碟空間大小是:202M+300M=502M
AUFS uses the Copy-on-Write (CoW) strategy to maximize storage efficiency and minimize overhead。

5.3.3 每層Docker映象包含兩部分:映象檔案 + 映象json後設資料資訊

json檔案
Docker每一層映象的json檔案,都扮演著一個非常重要的角色,其主要三個作用:
(1)記錄 Docker 映象中與容器動態資訊相關的內容
(2)記錄父子 Docker 映象之間真實的差異關係
(3)彌補 Docker 映象內容的完整性與動態內容的缺失
所以,Docker映象的json檔案可以認為是映象的後設資料資訊

六、面試金手指

略。

七、小結

Docker基礎知識(面試一籮筐),完成了。

天天打碼,天天進步!!!

相關文章