花間客

2020-08-14 11:06:36

參考文件:https://zhuanlan.zhihu.com/p/53260098
Docker的英文字意是碼頭工人,碼頭工人的工作就是將商品打包到Container(集裝箱)並且搬運Container、裝載Container。從docker字面上的解釋就可以看出docker是幹什麼的,對應到Linux中,docker就是將App打包到Container,通過Container實現App在各種平臺上的部署,執行。Docker通過Linux Container技術將App變成一個標準化的、可移植的、自管理的元件,實現了應用的build once,run anywhere。Docker技術特點是:應用快速發佈、應用部署和擴容簡單、更高的應用密度、應用管理更簡單。
Docker本身並不是容器,它是建立容器的工具,是應用容器引擎。            

docker與虛擬機器的區別
hypervisor:管理程式

Docker的優勢:
啓動非常快,秒級實現
資源利用率高,一臺高設定伺服器可以跑上千個docker容器
更快的交付和部署,一次建立和設定後,可以在任意地方執行
內核級別的虛擬化,不需要額外的hypevisor支援,會有更高的效能和效率
易遷移,平臺依賴性不強

Build, Ship and Run 搭建、發送、執行」,三板斧
Build once,Run anywhere 一次搭建,到處能用

安裝docker
由於docker的ee企業版是需要收取一定費用的,所以安裝的是ce社羣版,以下是官方的安裝文件:
https://docs.docker.com/install/linux/docker-ce/centos/
以下是我的安裝步驟:

1.如果你的系統沒有安裝過docker的話,只需要兩步就可以把docker安裝上,首先使用以下命令下載docker的repo源:
curl https://download.docker.com/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker.repo

2.然後直接通過yum安裝即可
yum install -y docker-ce

如果以上這種安裝方式的速度比較慢的話,大家也可以直接下載rpm包:
https://download.docker.com/linux/centos/7/x86_64/stable/Packages/

下載完之後也需要使用yum安裝,yum可以自動解決依賴關係:
yum install -y docker-ce-xxxx.rpm

3.安裝完成之後,啓動docker:
[root@server ~]# systemctl start docker  
[root@server ~]# ps aux |grep docker   # 檢視進程 
UID       PID    %CPU  %MEM VSZ RSS TTY STAT START TIME COMMAND 
root       5289  2.3  1.6 531968 30256 ?        Ssl  23:16   0:00 /usr/bin/docker
root       5297  1.5  1.2 366740 22500 ?        Ssl  23:16   0:00 docker-containerd --config /var/run/docker/containerd/containerd.toml

root       5438  0.0  0.0 112652   964 pts/0    S+   23:17   0:00 grep --color=auto docker
啓動docker後,會自動生成一些iptables規則:
[root@server ~]# iptables -nvL

[root@server ~]# iptables -t nat -nvL  # 檢視nat表

但是這生成的規則是臨時的,如果想要儲存,可以使用以下命令,不過一般沒有這個必要:
service iptables save

映象加速器
設定和使用阿裡雲提供的Docker映象加速器及國內映象加速器
存取阿裡雲註冊賬號
https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors

生成唯一加速地址,將加速地址配入daemon.json
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<EOF 
{ "registry-mirrors": ["https://vp****g8.mirror.aliyuncs.com","https://registry.docker-cn.com"] }
EOF 
systemctl daemon-reload 
systemctl restart docker.service
如果有容器,重新啓動docker後要重新啓動容器

批次操作容器    #多用於重新啓動docker引擎,容器全部停掉後批次重新啓動docker服務或全部停止容器
docker start/stop/restart $(docker ps -aq)

inspect:檢視,映象或容器
docker inspect 映象/容器ID
docker inspect $(docker ps -a|grep nginx|awk '{print $1}') |grep -i nginx


檢視註冊地址
docker info

常用命令
把映象拉取下來之後,就可以進行使用了,以下是一些常用命令:
1.檢視原生的映象:
[root@server ~]# docker images 
REPOSITORY          TAG                 IMAGE ID              CREATED             SIZE
centos                    latest              ff426288ea90        3 weeks ago         207MB
 
說明:
REPOSITORY 倉庫
TAG 標籤,相當於給這個映象標上一個版本,用於區分這是新版本還是舊版本,
或者用於區分這是什麼環境的版本,總之就是作爲一個識別符號的存在
IMAGE ID是這個映象的唯一標識,用於區分系統中不同的映象
CREATED,什麼時候建立的
SIZE,這個映象的大小

docker images -q
只展示映象id

2.搜尋映象命令,用於搜尋哪些映象可以提供下載,其中xxx是關鍵詞:
[root@server ~]# docker search xxx
例如我要搜尋centos的映象,則格式如下:
[root@server ~]# docker search centos

3.給某一個映象打標籤或者說定義它的標識,打上標籤後會新生成一個不同標籤的映象:tag類似於cp,命令格式一樣
[root@server ~]# docker pull centos 
[root@server ~]# docker tag centos test_centos  
[root@server ~]# docker images 
REPOSITORY      TAG                 IMAGE ID             CREATED              SIZE
centos                latest              ff426288ea90       3 weeks ago         207MB 
test_centos         latest              ff426288ea90       3 weeks ago         207MB
 
 
雖然說會新生成一個映象,但其實並不是,從上面的輸出結果可以看到,這兩個映象使用的IMAGE ID是一樣的,那它們其實就是同一個,不同的只是標籤。
除了可以定義映象的 REPOSITORY 之外,還可以定義映象的TAG:

[root@server ~]# docker tag centos test_centos2:171104
[root@server ~]# docker images 
 
REPOSITORY            TAG                 IMAGE ID             CREATED                SIZE 
centos                      latest               ff426288ea90        3 weeks ago          207MB  
test_centos2            171104            ff426288ea90        3 weeks ago          207MB
test_centos               latest               ff426288ea90        3 weeks ago          207MB
 
4.我們說了docker是容器,所以下載到映象後,還需要把映象啓動爲容器:
[root@server ~]# docker run -itd centos
  #加/bin/bash則進入容器,相當於exec
79fab4540315f6eb2b5616a2f8c8fabbcba7f3b5dffd46d52f98473c323594e9
 -i表示讓容器的標準輸入開啓,-t表示分配一個僞終端,-d表示後臺啓動,要把-i -t -d 放到映象名字前面。

5.檢視執行中的容器:
[root@server ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
79fab4540315         centos               "/bin/bash"             46 seconds ago      Up                   44 seconds         friendly_chatterjee
 
加上-a選項後可以檢視所有容器,包括未執行的。

6.刪除指定映象:
[root@server ~]# docker rmi test_centos
Untagged: test_centos:latest

[root@server ~]# docker images 
REPOSITORY          TAG                 IMAGE ID              CREATED              SIZE 
centos                    latest               ff426288ea90        3 weeks ago         207MB
test_centos2          171104            ff426288ea90        3 weeks ago         207MB
 
後面的參數可以是 REPOSITORY 也可以是 TAG,如果是TAG時,實際上是刪除該TAG。當後面的參數爲映象ID時,則會徹底刪除整個映象,所有標籤也會一同刪除。
或者 REPOSITORY 和 TAG 一起使用:
[root@server ~]# docker rmi test_centos2:171104
Untagged: test_centos2:171104

[root@server ~]# docker images 
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
centos                   latest              ff426288ea90        3 weeks ago         207MB

通過容器建立映象
我們從倉庫上拉取到一個映象後,啓動爲容器就可以使用了,但是可能這個容器裏面的環境不是我需要的,所以我們需要自己進行定製,例如在裏面設定自己需要的環境什麼的,設定好之後把這個容器生成一個映象就可以拿到其他機器上使用了。

1.想要定製容器的環境,首先要進入容器裡,命令如下:
[root@server ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
7
79fab4540315         centos               "/bin/bash"              27 minutes ago    Up 27 minutes                             friendly_chatterjee
[root@server ~]# docker exec -it 79fab4540315 bash

[root@79fab4540315 /]# ls  # 進入成功
anaconda-post.log  dev  home  lib64  mnt  proc  run   srv 
tmp  var
b bin etc  lib  media  opt  root  sbin  sys  usr
 
相當於建立一個互動式的容器
docker run -ti ubuntu /bin/bash

-ti選項分配一個僞終端給容器並可以使用STDIN進行互動,可以看到這時的容器跟可以在容器內執行一些命令  

     

這時的容器看起來完全是一個獨立的linux虛擬機器。使用exit命令退出容器。

這個拉取下來的centos映象,是一個閹割的操作系統,很多東西都沒有的,需要自己通過yum去安裝。
說明:
其中 79fab4540315 爲執行時該容器的id,這個id使用docker ps命令可以檢視到
最後面的bash爲進入容器後我們要執行的命令,這樣就可以開啓一個終端

2.進入到該容器後,我們可以做一些變更,比如安裝一些東西,搭建自己需要的環境,然後針對這個容器建立新的映象:
## 隨便裝點東西 
[root@79fab4540315 /]# yum install -y net-tools
[root@79fab4540315 /]# yum install vim

3.安裝完成後Ctrl + d或exit 退出該容器,然後執行以下命令生成一個映象:

[root@server ~]# docker commit -m "install net-tools and vim" -a "author" 79fab4540315 test_centos
sha256:0749459e3be3d66c787217bc7842c0856f7452e286f38e7e7979218787c1842a
[root@server ~]# docker images

REPOSITORY          TAG                  IMAGE ID            CREATED                SIZE 
test_centos             latest              0749459e3be3     11 seconds ago      359MB
centos                    latest              ff426288ea90        3 weeks ago          207MB

說明:
docker commit建立映象命令
-m指定該映象的描述資訊
-a指定映象作者的資訊
79fab4540315爲該容器的id
test_centos則是生成的新映象的名稱

如果熟悉git或svn的命令列操作的話,會發現這和它們的命令格式很像。
以上我們就通過容器建立了一個新的、由自己自定義環境的映象,之後使用該映象時,就不需要再去搭建環境了。而且我們可以把這個映象放到一個倉庫上,這樣其他機器也可以下載。這就和集裝箱一樣,把東西都封裝到一個箱子裡,不僅方便移動,還可以開箱即用。

Docker的容器
1、容器的基本操作
建立、停止、進入、刪除、匯入、導出(遷移)、檢視

a、建立容器
命令:run、create、start
run=create+start
例子:docker create --name mycontainer centos
此時建立的容器無法通過 docker ps檢視,因爲沒有執行
docker start [container_id]

b、停止容器
docker stop [container_id]

c、進入容器
docker exec -it  [container_id]  /bin/bash

d、刪除容器
docke rm [container_id]

e、匯入、導出容器(遷移)不管容器處於什麼狀態
docker export [container_id]
docker export -o 123.tar [container_id] 
# -o 指定導出後的tar包名稱
docker export busybox > busybox.tar

docker import 把匯入的tar包變成一個映象
docker import  123.tar 123_image
docker ps -a

#命令中有壓縮包的,包要在前,檔案在後。

Docker應用範例
docker與數據庫:Mysql

1、在Docker容器中部署執行Mysql
  docker search mysql
  docker pull mysql
  docker run --name mysql_demon -p 3306:3306 -e MYSQL_ROOT_PASSWD=Welcome_1 -d mysql
  docker exec -it mysql  /bin/bash 
  mysql -uroot -pWelcome_1
  show databases;

2、數據庫不適合執行在Docker容器中
(1)數據儲存在宿主機上,數據不安全
(2)執行數據庫需要一些硬體環境支援,IO操作的要求很高,競爭對硬體的使用
(3)對網路的要求高
(4)Docker中打包的應用是無狀態的應用

DockerFile使用(綜合例子)
Dockerfile是由一系列命令和參數構成的指令碼,這些命令應用於基礎映象並最終建立一個新的映象。它們簡化了從頭到尾的流程並極大的簡化了部署工作。Dockerfile從FROM命令開始,緊接着跟隨者各種方法,命令和參數。其產出爲一個新的可以用於建立容器的映象。
1、Docker映象、容器和DockerFile三者間的關係    

    

2、DockerFile的基本概念
Docker映象是一個特殊的檔案系統
DockerFile基於文字的組態檔,包含一條條指令。每一條指令構建分層檔案系統中的一層
Dockerfile是一個包含用於組合映像的命令的文字文件。可以使用在命令列中呼叫任何命令。 Docker通過讀取Dockerfile中的指令自動生成映象。
docker bulid 構建image映象
docker build命令用於從Dockerfile構建映像。可以在docker build命令中使用-f標誌指向檔案系統中任何位置的Dockerfile。

3、DockerFile檔案格式
4、綜合例子
從一個基本的centos基礎映象開始
基於這個基礎映象上來建立一個nginx環境的映象

拉取了一個centos7的基礎映象
docker pull centos7

a、建立Dockerfile,編輯內容如下:
#基於centos映象
FROM centos7
#作者資訊
MAINTAINER test [email protected]

#安裝一些依賴的包 
RUN yum install -y pcre-devel wget net-tools gcc zlib zlib-devel make openssl-devel

# Install Nginx  安裝nginx 
#ADD將本地檔案新增到容器中,tar型別檔案會自動解壓(網路壓縮資源不會被解壓),可以存取網路資源,類似wget。
ADD http://nginx.org/download/nginx-1.8.0.tar.gz .  # 新增nginx的壓縮包到當前目錄下 
RUN tar zxvf nginx-1.8.0.tar.gz  # 解包 
RUN mkdir -p /usr/local/nginx  # 建立nginx目錄
RUN cd nginx-1.8.0 && ./configure --prefix=/usr/local/nginx && make && make install  # 編譯安裝
RUN rm -fv /usr/local/nginx/conf/nginx.conf  # 刪除自帶的nginx組態檔 
ADD http://www.apelearn.com/study_v2/nginx_conf /usr/local/nginx/conf/nginx.conf  # 新增nginx組態檔
# Expose ports  開放80埠出來
EXPOSE 80

# Set the default command to execute when creating a new container  這裏是因爲防止服務啓動後容器會停止的情況,所以需要多執行一句tail命令
ENTRYPOINT /usr/local/nginx/sbin/nginx && tail -f /etc/passwd

b、通過Dockerfile來建立映象
docker bulid -t centos_nginx .
命令說明:
build -t tag,指定通過Dockerfile來建立映象
centos_nginx 則是新映象的名稱
. 表示在當前路徑尋找Dockerfile

c、建立完成後,檢視新建的映象:
[root@server ~]# docker images
REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
centos_nginx                    latest              167ba72ca0b2    3 minutes ago     374MB
centos                              latest              ff426288ea90      4 weeks ago        207MB

d、然後我們再把該容器的80埠對映到原生的81埠,這樣在外部也可以存取該容器的nginx服務了:
docker run -itd -p 81:80 centos_nginx /bin/bash
由於此命令爲對映埠所以並未進入到容器     
[root@server ~]# docker run -itd -p 81:80 centos_nginx
ef4d1bb6b288baab4e7e0c81645894c752e85ba3a4be70900b0dd627eddf43ef


[root@server ~]# docker exec -it ef4d1b bash #進入容器

[root@ef4d1bb6b288 /]# ps aux |grep nginx

root              1  0.1  0.0  11640  1336 pts/0    Ss+  15:39   0:00 /bin/sh -c /usr/local/nginx/sbin/nginx && tail -f /etc/passwd bash

root              8  0.0  0.0  24840   784 ?            Ss    15:39   0:00 nginx: master process /usr/local/nginx/sbin/nginx

nobody        9  0.0  0.1  27284  3356 ?           S      15:39   0:00 nginx: worker process

nobody       10  0.0  0.1  27284  3360 ?          S      15:39   0:00 nginx: worker process

root              27  0.0  0.0   9048   664 pts/1    S+    15:39   0:00 grep --color=auto nginx


[root@ef4d1bb6b288 /]# netstat -lntp |grep nginx

tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      8/nginx: master pro 

[root@ef4d1bb6b288 /]# exit #退出容器

e、最後使用curl來測試一下是否能通過存取宿主機的81埠來存取到容器的nginx服務:
[root@server ~]# curl localhost:81

Docker網路通訊的基本原理

Docker中的網路介面預設都是虛擬的介面。
虛擬介面的最大優勢就是轉發效率極高。這是因爲Linux通過在內核中進行數據複製來實現虛擬介面之間的數據轉發,即發送介面的發送快取中的數據包將被直接複製到接收介面的接收快取中,而無需通過外部物理網路裝置進行交換。對於本地系統和容器內系統來看,虛擬介面跟一個正常的乙太網卡相比並無區別,只是它速度要快得多。
Docker容器網路就很好地利用了Linux虛擬網絡技術,在本地主機和容器內分別建立一個虛擬介面,並讓它們彼此連通(這樣的一對介面叫做veth pair)。

Docker建立一個容器的時候,會具體執行如下操作:
建立一對虛擬介面,分別放到本地主機和新容器的名稱空間中;
本地主機一端的虛擬介面連線到預設的docker0網橋或指定網橋上,並具有一個以veth開頭的唯一名字,如veth1234;
容器一端的虛擬介面將放到新建立的容器中,並修改名字作爲veth0。這個介面只在容器的名稱空間可見;
從網橋可用地址段中獲取一個空閒地址分配給容器的eth0(例如172.17.0.2/16),並設定預設路由閘道器爲docker0網絡卡的內部介面docker0的IP地址(例如172.17.0.1/16)。

[root@server~]#ifconfig #安裝docker服務後本地會產生docker0網橋資訊,一般是172.17.0.1/16

root@server~]# docker pull centos
root@server~]# docker run  centos 
[root@server~]# ifconfig   #此時宿主機上增加了一個虛擬介面(網絡卡)vethd1b406d

[root@server /]# yum -y install net-tools #下載ifcongfig命令
[root@server /]# ifconfig  #容器增加一個eht0虛擬網絡卡

總體如下:容器的veth0<——>vethd1b406d<——>docker0<——>外部網路網橋
 

補充:

1.想要定製容器的環境,首先要進入容器裡,命令如下:
[root@server ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
7
79fab4540315         centos                  "/bin/bash"         27 minutes ago       Up 27 minutes                           friendly_chatterjee
[root@server ~]# docker exec -it 79fab4540315 bash
[root@79fab4540315 /]# ls  # 進入成功
anaconda-post.log  dev  home  lib64  mnt  proc  run   srv  tmp  var
b
bin                etc  lib   media  opt  root  sbin  sys  usr

相當於建立一個互動式的容器
docker run -ti ubuntu /bin/bash

-ti選項分配一個僞終端給容器並可以使用STDIN進行互動,可以看到這時的容器跟可以在容器內執行一些命令        

這時的容器看起來完全是一個獨立的linux虛擬機器。使用exit命令退出容器。

docker run -v 掛載數據卷
格式:
-v 容器目錄 或 -v 本地目錄:容器目錄
1、容器目錄只能是絕對路徑,且會自動建立掛載的目錄
2、本地目錄不存在,則自動建立該目錄
3、只指定一個目錄,則爲容器目錄,在本地自動建立/var/lib/docker/容器id/_data目錄

樣例:
docker run  -v /usr/ToolsAPIDir:/ToolsAPIDir1 -d -p 5005:5004 -it toolsapi:v8 python3 tools_api.py
命令解析:
-v 本地目錄:容器目錄。掛載主機的本地目錄 /usr/ToolsAPIDir 目錄到容器的/ToolsAPIDir1 目錄,本地目錄的路徑必須是絕對路徑
-d 後臺執行容器
-p 5005:5004指定主機的5005埠對映到容器的5004埠
-it toolsapi:v8 以互動模式執行 toolsapi:v8啓動的容器
python3 tools_api.py 啓動api.py檔案,這樣可以不需要再Dockfile中指定 CMD命令,或者覆蓋Dockfile中的CMD命令。

優點:
當啓動的py檔案中有bug時,可以在主機中更新py檔案,然後重新執行 run 命令即可。這樣就將環境和程式碼分離,映象就是執行環境,執行環境只要不改變,就不用重新生成映象。
否則如果將py檔案打包到映象中的話,任何對程式碼的修改都必須重新生成映象。

數據卷共用
     既然可以將原生的目錄掛在到Docker容器中,那麼掛載的數據卷是否可以再被其他的Docker容器使用呢?答案是:可以。我們首先建立兩個容器DataTest1 、DataTest2:
$docker run -it --name DataTest1 -v /home/docker_tmp_test:/home/test/docker docker.io/ubuntu:12.04     
$docker run -it --name DataTest2 -v /home/docker_tmp_test:/home/test/docker docker.io/ubuntu:12.04
     可以發現name爲」DataTest1 」和」DataTest2」的容器都是啓動的.同時他們掛在了宿主主機的同一個目錄,在各自的容器中看到的是一致的。然後在"DataTest2」建立一個檔案「test.txt 「,在去檢視」DataTest1 」的掛在目錄和宿主原生的被掛載目錄,發現新建的「test.txt」檔案都存在。