從0開始學Docker(下)

引言

這一篇文章,理論和實踐各佔一半,有需要的可以先安裝配置好兩臺虛擬機和Docker。
覺得寫的可以不妨點個贊吧,收藏比贊高N倍,枯了​😂~

文章導讀

  • Docker的C/S架構​​
  • Docker容器的網絡連接​
  • Docker容器的數據管理

一、Docker的C/S模式

Docker的C/S架構中,最重要的就是Docker Client和Docker Daemon。

1.1 Docker的C/S模式

Docker守護進程會在Docker啓動後,在宿主機後臺運行,負責處理docker的各種命令功能。用戶並不是直接和守護進程交互,而是和Docker客戶端交互。意思是我們輸入的命令,通過命令行接口(/bin/bash這樣二進制的程序),再傳遞給守護進程,守護進程再將命令執行後返回結果給客戶端,顯示於命令行接口。

圖片來源於網絡

docker客戶端除了以命令的方式和守護進程通信,還可通過Remote API。

圖片來源於網絡

客戶端與守護進程的連接方式

從整體上來看,用戶通過命令行接口或應用程序(程序是對Remote API的封裝)來對Docker Client進行訪問,而這個客戶端是以Socket的方式來對守護進程訪問的。

Docker是以Socket的方式連接,有三種模式:

  • unix://var/run/docker.sock(默認)
  • tcp://host:port
  • fd://socketfd
圖片來源於網絡

1.2 Docker守護進程的配置和操作

使用service命令管理

  • service docker start
  • service docker stop
  • service docker restart

Docker的啓動選項

docker -d [OPTIONS]

  • 運行相關 
    -D,--debug:是否開啓debug
    -e, 運行時使用的驅動模式
    -g ,指定docker寫入文件的地址
    --icc :指定容器之間是否可以互相連接
    -l,--log-level:設置日誌界別 
    -p,pidfile默認爲"/var/run/docker.pid"
  • 服務器連接相關 
    -G,指定用戶組,默認是"docker" 
    -H,按照上一節所講的Socket連接模式來寫
    --tls=false 安全性相關選項
    ... ...
  • RemoteAPI相關
    --api-enable-cors 是否使用RemoteAPI
  • 存儲相關
    -s:storage driver,設置驅動 
    --selinux-enable:是否開啓selinux 
    ... ...
  • Registry相關
    --registry-mirror:配置鏡像連接
  • 網絡設置相關(下一章會講) 
    -ip 
    -ip-forward:決定是否會轉發流量
    --iptables :允許容器與iptables設置的ip之間的訪問
    ... ...

具體配置可以參考官網: 詳細配置說明

除了通過設置啓動時的參數,也可以通過配置docker啓動時的配置文件,/etc/default/docker設置詳細的配置項。

二、Docker容器的網絡連接

Docker的網絡連接部分主要包括:

  • Docker容器的網絡基礎
  • Docker容器的互聯
  • Docker容器與外部網絡的連接
  • Docker容器的跨主機訪問

2.1 Docker容器的網絡基礎

Docker守護進程啓動後,在宿主機中查看網卡信息,會發現多了一個網卡(Docker0)。Docker0其實就是一個Linux虛擬網橋。

提到這裏,先回顧一下什麼是網橋? 
網橋工作於數據鏈路層,通過網絡設備的物理地址(MAC地址)對網絡進行劃分,在不同網絡之間傳遞數據。

Linux虛擬網橋的特點是可以設置IP地址,相當於擁有一個隱藏的虛擬網卡。

docker0來說,他的IP地址爲172.17.0.1,屬於B類IP。子網掩碼爲255.255.0.0。可以計算出總共可劃分65534個地址。

docker0的工作過程

Docker對網絡連接的管理,是在容器啓動時就初始化兩端。一端是容器中的網絡設備,另一端在守護進程的主機中(docker0的Host端)開放veth開頭的接口,用於網橋與容器網卡的網絡通信。

簡單感受下網橋是怎麼工作的:

  1. 首先安裝網橋管理程序
    yum install bridge-utils
  2. 查看網橋設備 
    brctl show

3. 創建一個容器

  • docker run -it --name container1 centos:centos7 /bin/bash
  • ctrl+P;ctrl+Q(讓容器後臺運行)

此時可以看到,網橋有了對應的網絡。

我們也可以自定義docker0的ip網段,使用ifconfig指令:
ifconfig docker0 192.168.200.1 netmask 255.255.255.0

自定義虛擬網橋

  1. 添加虛擬網橋 
    brctl addbr newbridge 
    ifconfig newbridge 192.168.100.1 netmask 255.255.255.0
  2. 更改docker守護進程的啓動配置 
    vim /etc/default/docker 
    添加DOCKER_OPS="-b=newbridge"

2.2 Docker容器的互聯

Docker容器的互聯可分爲:

  • 允許所有容器互聯
  • 拒絕容器間互聯
  • 允許特定容器間的連接

前提

FROM centos:centos7
RUN yum install -y ping
RUN yum install -y nginx
RUN yum install -y curl
EXPOSE 80
CMD /bin/bash

構建鏡像 docker build -t image1 .

2.2.1 允許容器間的互聯

容器之間默認是可以互聯的,具體可由docker守護進程的啓動選項:--icc=true|false指定。

  1. 構建容器 
    docker run -it --name container1 image1
  2. 啓動服務 
    nginx
  3. 讓容器後臺運行後,再啓動一個容器 docker run -it --name container2 image1
  4. 進入各自容器,互相ping一下,發現是可行的

配置容器間的動態連接

docker容器重啓後,IP會發生變化,如果服務與服務之間將IP寫死調用,勢必會調用失敗,此時就需要link參數: 
docker run --link=[CONTAINER]:[ALIAS] [IMAGE] [COMMAND] 

給某個想要連接的容器取別名,這樣在容器重啓時,對應的host文件中的映射也會變化

2.2.2 拒絕容器間的互聯

首先要修改守護進程的啓動選項,就要修改docker默認的配置文件。

  • vim /etc/default/docker
  • 在DOCKER_OPS中添加--icc=false

執行service dockers restart後,創建的所有容器都不能互聯,如果需要指定容器互聯就需要下一節的操作。

2.2.3 允許特定容器間的連接

  1. Docekr守護進程的啓動選項:
    --icc=false
    --iptables=true
  2. 重啓一下docker,創建容器時用--link指定
    service docker restart 
    docker run -it --name container3 --link=container1:c1 image1
  3. 測試是否能連通
    curl c1

2.3 Docker容器與外部網絡連接

ip-forward是linux系統中的變量,決定是否會轉發流量。 對應了Linux的這個系統變量:
sysctl net.ipv4.conf.all.forwarding

docekr守護進程配置的ip-forword默認爲true。iptables是與Linux內核集成的包過濾防火牆系統,幾乎所有的Linux發行版本都包括iptables的功能。

阻止特定ip對特定容器的訪問

指令格式:
iptables -I DOCKER -s 源地址 -d 目標地址 -p TCP --dport 目的端口 -j 執行操作 
注:執行操作包括DROP,ACCEPT等等。

可以通過iptables -L -n 來查看系統中的一些包過濾規則。

通過一個例子感受下:
阻止192.168.29.100訪問容器ip爲192.168.29.111的80端口
iptables -l DOCKER -s 192.168.29.100 -d 192.168.29.111 -p TCP --dport 80 -j DROP

如果是允許的化,也同理,講DROP改爲ACCEPT。

2.4 Docker容器的跨主機訪問

目前蒐集的至少有3中方式可以實現:

  • 使用網橋實現跨主機容器連接。
  • 使用Open vSwitch實現跨主機容器連接。
  • 使用weave實現跨主機容器連接。

這裏由於配置簡單,就講解第一種,使用網橋的方式。

主要思路:
如果將連接容器的網橋橋接到docker宿主機提供的網卡上,並將網橋分配的ip地址與docker宿主機的ip地址設置到同一網段,就能夠實現容器與容器之間跨主機的通信。簡單來說就是在一個宿主機中,大家都用一個網橋

圖片來源於網絡

操作步驟

  1. 需要兩臺虛擬機
    IP地址:Host1(192.168.29.3),Host2(192.168.29.4)
  2. 修改兩臺虛擬機中網橋的連接
    vim /etc/network/interfaces 
    配置如下:
auto bridge
#分配網橋的方式
iface bridge inet static
address 192.168.29.3
netmask 255.255.255.0
#默認網關
gateway 192.168.29.1
#將本地的物理網卡連接到新建的網橋上
bridge_ports eth0

在另一臺虛擬機中也進行類似操作。

3. 修改docker默認的網絡配置
IP的劃分將改成192.168.29.65~192.168.29.126和192.168.29.129~192.168.29.190
Host1中:
vim /etc/default/docker 
DOCKER_OPTS=" -b=bridge --fixed-cidr='192.168.29.64/26' "

Host2中:
DOCKER_OPTS=" -b=bridge --fixed-cidr='192.168.29.128/26' "

4. 啓動一個容器,執行ping另一臺宿主機的ip或者另一臺宿主機中的容器,發現能夠連通則配置成功。

三、Docker容器的數據管理

有時候,我們需要容器與宿主機磁盤中的數據共享,對此,Docker提供的解決方案是數據卷技術。以容器掛載數據卷的方式來實現數據的互通。

本小節主要分爲:

  • Docekr容器的數據卷
  • Docker的數據卷容器
  • Docker數據卷的備份和還原

3.1 Docker容器的數據卷

什麼是數據卷? 
數據卷是經過特殊設計的目錄,可以繞過聯合文件系統(UFS),爲一個或多個容器提供訪問。對數據卷應該有如下的感覺:

數據卷設計的目的在於持久化,它完全獨立於容器的生存週期,因此,Docker不會在容器刪除時,刪除其掛載的數據卷,也不會存在類似的垃圾收集機制,對容器的數據捲進行處理。

數據卷的特點

  • 數據卷在容器啓動時初始化,如果容器使用的鏡像在掛載點包含了數據,這些數據會拷貝到新初始化的數據卷中。
  • 數據卷可以在容器之間共享和重用。
  • 可以對數據卷裏的內容直接進行修改。
  • 數據卷的變化不會影響鏡像的更新。
  • 卷會一直存在,即使掛載數據卷的容器已經被刪除。

爲容器添加數據卷

docker run -v ~/container_data:/data -it centos:centos7 /bin/bash

爲數據卷添加訪問權限

docker run -v 宿主機目錄:容器目錄:ro IMAGE COMMAND -d 
注:"ro"的意思是read only。

使用Dockerfile構建數據卷

VOLUME["/data"]

這裏是不需要寫明映射關係的,因爲通過這個鏡像創建的不同容器的數據卷是不一樣的。具體映射關係可以通過docker inspect CONTAINER 查看。

3.2 Docker的數據卷容器

數據卷提供了容器與宿主機的共享數據,如果容器與容器之間要共享,該怎麼辦呢?這就需要掛載包含數據卷的容器來實現。

什麼是數據卷容器? 
命名的容器掛載數據卷,其他容器通過掛載這個容器實現數據共享,掛載數據卷的容器叫數據卷容器。

文字看着又繞又枯燥,一張圖梳理一下:

圖中可以看出:

  1. 數據卷容器掛載了一個本地目錄。
  2. 其他容器通過連接這個數據卷容器實現數據的共享。

掛載數據卷容器的方法 
docekr run --volumes-from [CONTAINER] 
注:CONTAINER是掛載數據卷的容器。

下面通過一個例子來實現container1與container2的數據共享。

前提

image2.dockerfile如下:

FROM centos:centos7
VOLUME["/datavolume"]
CMD /bin/bash

構建鏡像後的步驟

下面步驟中container1是數據卷容器,container2和container3要實現數據共享。

  1. 啓動container1
    docker run -it --name container1 image2
  2. 在container1中創建文件
    touch /datavolume/c1
  3. exit
  4. 啓動container2,並掛載到container1
    docker run -it --name container2 --volumes-from container1 IMAGE /bin/bash
  5. 在container2中創建文件
    touceh /datavolume/c2
  6. exit
  7. 同理啓動container3
    docker run -it --name container3 --volumes-from container1 IMAGE /bin/bash
  8. exit
  9. docker inspect --format="{{.Volumes}}" container2
  10. docker inspect --format="{{.Volumes}}" container3

最後,我們可以驚奇地發現兩個掛載了數據卷容器的容器返回結果一樣

此時將container1容器刪除,會發現,container2和container3還是共享了一個數據卷容器,因此可以得出這樣的結論:數據卷容器僅僅承載配置信息的傳遞

3.3 Docker數據卷的備份和還原

數據備份方法

docker run --volumes-from CONTAINER -v 期望備份存放的路徑(宿主機路徑):映射到備份命令容器中的目錄:權限(一般爲wr,即讀寫權限) IMAGE tar cvf 壓縮至某個路徑下的某個文件名(宿主機路徑) 數據卷在容器中的路徑

文字描述比較繞,通過例子展示一下:

docker run --volumes-from container1 -v ~/backup:/backup --name container2 IMAGE tar cvf /backup/c1.tar /datavolume1

具體過程:

備份過程其實就是對數據容器掛載的數據卷中的數據的轉移,相當於執行備份命令的容器既掛載了數據容器的數據卷,又掛載了備份數據存放的數據卷。

同樣地,數據還原方法就是對備份的解壓縮:
docker run --volumes-from container1 -v ~/backup:/backup IMAGE tar xvf /backup/backup.tar /datavolume1

總結

Docker的學習暫時告一段落,在這個過程中,最終要的還是在虛擬機中多多實踐。真實運行中可能會碰到許多問題,解決問題的過程中經驗才能一步一步的積累~

感覺寫得還可不妨點個贊哈~

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