docker進階——數據管理與網絡


 

 一、數據卷管理

 

用戶在使用 Docker 的過程中,勢必需要查看容器內應用產生的數據,或者 需要將容器內數據進行備份,甚至多個容器之間進行數據共享,這必然會涉及 到容器的數據管理

1Data Volume (數據卷)

2Data Volume Dontainers --- 數據卷容器

 

 

Data Volume ---數據卷

 

Data Volume 本質上是 Docker Host 文件系統中的目錄或文件,使用類似 與 Linux 下對目錄或者文件進行 mount 操作。數據卷可以在容器之間共享 和重用,對數據卷的更改會立馬生效,對數據卷的更新不會影響鏡像,卷會一 直存在,直到沒有容器使用

 

Data Volume 有以下特點   

aData Volume 是目錄或文件,而非沒有格式化的磁盤(塊設備)。   

b容器可以讀寫 volume 中的數據。   

cvolume 數據可以被永久的保存,即使使用它的容器已經銷毀。

 

Data Volume的使用:

通過-v 參數格式為 <host path>:<container path>

a)利用 nginx的鏡像運行一個容器,並在容器內創建一個數據卷掛載到容器 的 /web 目錄上 

[root@localhost ~]# docker run -dti -v /web nginx:latest /bin/bash
d4e002045c2bd022a826dbd2805b121dd43c41443d86eeb6515f616bf52c8549

 

b)運行一個容器,本地創建/date目錄掛載到容器的/var/log/目錄上 

docker run -dti -v /data:/var/log nginx /bin/bash

docker run -dti -v /data:/var/log centos:latest /bin/bash
25773c239584614e301644db01b7275377887c9bbefe8c54cf5cd6be2917ab54

 

 

DataVolumeDontainers --- 數據卷容器

如果用戶需要在容器之間共享一些持續更新的數據,最簡單的方法就是使用數據 卷容器,其實數據卷容器就是一個普通的容器,只不過是專門用它提供數據卷供 其他容器掛載使用

 

Data Volume Dontainers使用:

 

a)創建一個名為 dbdata 的數據卷,並在其中創建一個數據卷掛載到 /dbdata

docker run -dti -v /dbdata --name dbser centos:7.0

--name 參數為給容器指定名字為dbser方便記憶 

[root@localhost ~]# docker run -dti -v /dbdata --name dbser centos:latest
82b264b29e56700afebaa7acec8c69309964f27dafd271454048b8b7a113720e

 

 

b)其他容器使用--volume-from 去掛載dbdata容器中的/dbdata數據卷  eg :創建 db1&db2 兩個容器, 並掛載 /dbdata 數據卷到本地

docker run -dti --volumes-from dbserver --name db1 centos:7.0  

docker run -dti --volumes-from dbserver --name db2 centos:7.0

 

此時,容器 db1 db2 同時掛載了同一個數據卷到本地相同 /dbdata 目錄。三個容器任何一個目錄下的寫入,都可以時時同步到另外兩個

 

[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS                    NAMES
aff1e64343bf        centos:latest       "/bin/bash"              4 minutes ago       Up 4 minutes                                        db2
893450737ade        centos:latest       "/bin/bash"              4 minutes ago       Up 4 minutes                                        db1
82b264b29e56        centos:latest       "/bin/bash"              6 minutes ago       Up 6 minutes                                        dbser

在db2中創建jam文件,寫入0330
[root@localhost ~]# docker exec -it  aff1e64343bf /bin/bash
[root@aff1e64343bf dbdata]# echo "0330" >jam
[root@aff1e64343bf dbdata]# cat jam 
0330

在db1中查看是否存在jam文件
[root@localhost ~]# docker exec -it 893450737ade /bin/bash
[root@893450737ade /]# cd dbdata/
[root@893450737ade dbdata]# ls
jam
[root@893450737ade dbdata]# cat jam
0330

在dbser中查看jam文件是否存在
[root@localhost ~]# docker exec -it 82b264b29e56 /bin/bash
[root@82b264b29e56 /]# ls
  dbdata  
[root@82b264b29e56 /]# cd dbdata/
[root@82b264b29e56 dbdata]# ls
jam
[root@82b264b29e56 dbdata]# cat jam
0330

 

 

 

 

二、docker網絡介紹

 

大量的互聯網應用服務需要多個服務組件,這往往需要多個容器之間通過網絡 通信進行相互配合

docker 網絡從覆蓋范圍可分為單個 host 上的容器網絡和跨多個 host 的網絡 docker 目前提供了映射容器端口到宿主主機和容器互聯機制來為容器提供網絡服務,在啟動容器的時候,如果不指定參數,在容器外部是沒有辦法通過網絡來訪問容器內部的網絡應用和服務的

docker 安裝時會自動在host上創建三個網絡,我們查看一下docker網絡:

docker network ls

[root@localhost ~]# docker network list
NETWORK ID          NAME                DRIVER              SCOPE
460b8a01b798        bridge              bridge              local
d4ae07a1372e        host                host                local
63bead0d7ffc        none                null                local

 

 

 

二、docker--none網絡

none 網絡就是什么都沒有的網絡。掛在這個網絡下的容器除了lo,沒有其他任何網卡。容器創建時,可以通過 --network=none 指定使用 none 網絡。

 

none 網絡的應用

封閉的網絡意味着隔離,一些對安全性要求高並且不需要聯網的應用可以使用 none 網絡。

比如某個容器的唯一用途是生成隨機密碼,就可以放到 none 網絡中避免密 碼被竊取。

 

 

 

三、docker--host網絡

 

 

連接到 host 網絡的容器,共享 docker host 的網絡棧,容器的網絡配置與 host 完全一樣。可以通過 --network=host 指定使用 host 網絡

 

在容器中可以看到 host 的所有網卡,並且連 hostname 也是 host 的。host 網絡的使用場景又是什么呢?

直接使用 Docker host 的網絡最大的好處就是性能,如果容器對網絡傳輸效率 有較高要求,就可以選擇 host 網絡

當然不便之處就是犧牲一些靈活性,比如要考慮端口沖突問題Docker host 上已經使用的端口就不能再用了。

Docker host 的另一個用途是讓容器可以直接配置 host 網路。比如某些跨 host 的網絡解決方案,其本身也是以容器方式運行的,這些方案需要對網絡進 行配置,比如管理 iptables

 

四、docker--bridge網絡

 

docker 安裝時會創建一個 命名為 docker0 linux bridge如果不指定 --network,創建的容器默認都會掛到 docker0

當前 docker0 上沒有任何其他網絡設備,我們創建一個容器看看有什么變化

[root@localhost docker]# brctl show
bridge name    bridge id        STP enabled    interfaces
docker0       8000.0242ec43479a    no        vethb2a3b02  #以密鑰對的形式掛到docker0

 

一個新的網絡接口 vethb2a3b02 被掛到了 docker0 上,vethb2a3b02 就是 新創建容器的虛擬網卡。

 

 

進入剛才運行的容器查看網絡,容器有一個網卡 eth0@if9

[root@localhost docker]# docker exec -it 5449774b40e5 /bin/sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

 

實際上 eth0@if9 和 vethb2a3b02是一對 veth pair

veth pair 是一種成對出現的特殊網絡設備,可以把它們想象成由一根虛擬網線 連接起來的一對網卡,網卡的一頭(eth0@if9)在容器中,另一頭 (vethb2a3b02)掛在網橋 docker0 上,其效果就是將 eth0@if9 也掛在了 docker0

 

 

可以看到,eth0@if9 已經配置了 IP 172.17.0.3,為什么是這個網段呢?

看一下 bridge 網絡的配置信息:

docker network inspect bridge

Config": [
                {
                    "Subnet": "172.17.0.0/16"

可以看到bridge 網絡配置的 subnet 就是 172.17.0.0/16,並且網關是 172.17.0.1, 在docker0

容器創建時,docker 會自動從 172.17.0.0/16 中分配一個 IP,這里 16 位的 掩碼保證有足夠多的 IP 可以供容器使用,(主機位是16位)

 

 

五、創建 user--defined網絡

 

我們可通過 bridge 驅動創建類似前面默認的 bridge 網絡

1)利用bridge驅動創建名為my-net2網橋(docker會自動分配網段):

docker network create --driver bridge my-net2

可以看到新創建的網絡也自動被分配了子網ip。

 

[root@localhost ~]# docker network create --driver bridge net2 
2edd5371dd2fbcb32c9c2b2a9420cb806e406edc011379c7c7c70f53d6c74585
[root@localhost ~]# docker network list
NETWORK ID          NAME                DRIVER              SCOPE
460b8a01b798        bridge              bridge              local
d4ae07a1372e        host                host                local
2edd5371dd2f        net2                bridge              local
63bead0d7ffc        none                null                local
[root@localhost ~]# docker network inspect net2
。。。
Config": [ { "Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1"

 

刪除網橋:brctl delbr 網橋名

 

4)利用bridge驅動創建名為net3網橋(user-defined網段及網關)

[root@localhost ~]# docker network create --driver bridge --subnet 172.18.2.0/24 --gateway 172.18.2.1 net3

 

報錯:Error response from daemon: Pool overlaps with other one on this address space

這是因為新創建的網絡自定義的子網ip與已有的網絡子網ip沖突。

只需要重新定義子網ip段就行

 

[root@localhost ~]# docker network create --driver bridge --subnet 192.18.2.0/24 --gateway 192.18.2.1 net3
3f028deb3aa0b37ee69e3a04a0edb14c00b1933a415c2d0961a9eec7b4b2ecb1

 

重新查看網絡配置信息:

[root@localhost ~]# docker network inspect net3
"Config": [
                {
                    "Subnet": "192.18.2.0/24",
                    "Gateway": "192.18.2.1"

可以看到自定義的網絡配置成功。

 

 

5)啟動容器使用新建的net3網絡

 

docker run -itd --network=net3(網絡名) 鏡像名 /bin/sh(環境名)

 

[root@localhost ~]# docker run  -itd --network=net3 busybox:latest /bin/sh
632e2d8245ade9e0a8ee9cf13d7105f19a2d28728e3d38b65423eb34ef38ac4c
[root@localhost ~]# docker exec -it 632e2d8245ad /bin/sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
18: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:c0:12:02:03 brd ff:ff:ff:ff:ff:ff
    inet 192.18.2.3/24 brd 192.18.2.255 scope global eth0
       valid_lft forever preferred_lft forever   

可以看到使用新建網絡net3啟動的容器會自動分配一個net3子網段內的ip。

 

 

6)啟動容器使用net3網絡並指定ip(只有使用 --subnet 創建的網絡才 能指定靜態 IP,如果是docker自動分配的網段不可以指定ip

[root@localhost ~]# docker run  -itd --network=net3 --ip 192.18.2.4 busybox:latest /bin/sh

當然,這個指定的ip也要在net3的子網范圍內。

 

[root@localhost dbdate]# docker run -itd --network=bridge --ip 172.17.0.3 busybox:latest /bin/sh

docker: Error response from daemon: user specified IP address is supported on user defined networks only.

 如上的報錯就是因為運行容器時選中的網絡不是使用--subnet定義的網絡,所以不能指定ip。

 

 

7)讓已啟動不同vlanningx容器,可以連接到net2(其實在nigx中新建了my-net2的網卡)

docker run -itd --network=net3 busybox:latest  /bin/sh

docker network connect net2   容器名(id)

[root@localhost ~]# docker run  -itd --network=net3 busybox:latest /bin/bash
e42da501655faa6e2067a6d9ee6c49016ec49bb0dc750b78a82f2540751840c5
[root@localhost docker]# docker network connect net2 0d3e78d4298c
[root@localhost docker]# docker exec -it 0d3e78d4298c /bin/sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
20: eth0@if21: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:c0:12:02:04 brd ff:ff:ff:ff:ff:ff
    inet 192.18.2.4/24 brd 192.18.2.255 scope global eth0
       valid_lft forever preferred_lft forever
24: eth1@if25: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.2/16 brd 172.18.255.255 scope global eth1
       valid_lft forever preferred_lft forever

可以看到此容器同時擁有了net2和net3的子網ip。

 

 

8)使用--name指定啟動容器名字,可以使用docker自帶DNS通信,但只能 工作在user-defined 網絡,默認的 bridge 網絡是無法使用 DNS 的。

 

root@localhost docker]# docker run -itd --network=net3 --name=b1 busybox
203fc1c4fb19dc1212da8f97dc8654b5b928f9ab1406bed4c39a31f76b686d4c
[root@localhost docker]# docker run -itd --network=net3 --name=b2 busybox
5dfabb01d5d718429e382acb4115a1d8c4c7e2e89c302b899bcf5923be1df527
[root@localhost docker]# docker exec -it b1 /bin/sh
/ # ping b2
PING b2 (192.18.2.7): 56 data bytes
64 bytes from 192.18.2.7: seq=0 ttl=64 time=0.417 ms
64 bytes from 192.18.2.7: seq=1 ttl=64 time=0.110 ms
64 bytes from 192.18.2.7: seq=2 ttl=64 time=0.099 ms

在創建容器時使用相同網絡,並且給容器命名的話

意思是給兩個容器之間做了域名解析和配置相同網段,所以能ping通

 

 

9)容器之間的網絡互聯

  a). 首先創建一個 db 容器 

 

[root@localhost ~]# docker run -itd --name db busybox

 

b). 創一個 web 容器,並使其連接到 db   

 

[root@localhost ~]# docker run -itd --name web --link db:dblink busybox /bin/sh

-link db:dblink 實際是連接對端的名字和這個鏈接的名字,也就是和 db 容器 建立一個叫做 dblink 的鏈接  

 

c).查看鏈接的情況 

docker ps -a

[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
141e370eea76        busybox             "/bin/sh"                8 seconds ago       Up 7 seconds                                    web
9f89a1945f6b        busybox             "sh"                     54 seconds ago      Up 53 seconds                                   db

 

d)進入web容器,使用 ping 命令來測試網絡鏈接的情況

[root@localhost ~]# docker exec -it 141e370eea76 /bin/sh/ # ping db
PING db (172.17.0.4): 56 data bytes
64 bytes from 172.17.0.4: seq=0 ttl=64 time=0.445 ms

發現可以ping通,連接有效

 

    e)嘗試進入db容易,使用ping命令測試

[root@localhost docker]# docker exec -it 9f89a1945f6b /bin/sh
/ # ping web
ping: bad address 'web'

發現無法ping通,因此可以推斷出容器之間的網絡連通是單向的,即哪個容器建立了連接,哪個容易才能連接到另一個容器,反之不行。

 

 

10)容器端口映射 在啟動容器的時候,如果不指定參數,在容器外部是沒有辦法通過網絡來訪問容 器內部的網絡應用和服務的

當容器需要通信時,我們可以使用 -P (大) &&-p (小)來指定端口映射

 

-P Docker 會隨機映射一個 49000 49900 的端口到容器內部開放的網絡端口

p 則可以指定要映射的端口,並且在一個指定的端口上只可以綁定一個容器。

 

 

支持的格式有

iP HostPort   ContainerPort

IP : : ContainerPort

IP HostPort

如果不指定就隨機 

 

查看映射

docker port 容器名

 

拓展:用腳本刪除所有容器

 

[root@localhost docker]# for id in `docker ps -a | grep a | awk -F " +" '{print $1}'` ;do docker rm -f $id ;done

 

 

 

 

a)映射所有接口地址,此時綁定本地所有接口上的 5000 到容器的 5000 接口, 訪問任何一個本地接口的 5000 ,都會直接訪問到容器內部

docker run -dti -p 5000:5000 nginx /bin/bash

 

b)多次使用可以實現多個接口的映射

 

[root@localhost docker]# docker run -itd -p 5000:22 -p 5001:23 nginx /bin/bash

 

 

查看容器信息,發現新容器的的22,23端口都映射到了宿主機的5000和5001端口。

[root@localhost docker]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                         PORTS                                                NAMES
ea3b9412d96d        nginx               "/bin/bash"              5 seconds ago       Up 5 seconds                   80/tcp, 0.0.0.0:5000->22/tcp, 0.0.0.0:5001->23/tcp   hardcore_darwin

 

 

c)映射到指定地址的指定接口 此時會綁定本地 192.168.4.169 接口上的 5000 到容器的80 接口

 docker run -dti -p 192.168.253.9:5000:80 nginx /bin/bash

[root@localhost docker]#  docker run -dti -p 192.168.253.9:5000:80 nginx /bin/bash
[root@localhost docker]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 132746ef0996 nginx "/bin/bash" About a minute ago Up About a minute 192.168.253.9:5000->80/tcp practical_lichterman

 

 

 

d) 映射到指定地址的任意接口 此時會綁定本地 192.168.4.169 接口上的任意一個接口到容器的 5000 接口

docker run -dti -p 192.168.4.169::5000 nginx /bin/bash

 

e) 使用接口標記來指定接口的類型

docker run -dti -p 192.168.4.169::5000/UDP nginx /bin/bash

 指定接口位udp類型

 

11)實驗:通過端口映射實現訪問本地的 IP:PORT 可以訪問到容器內的 web

 

a)將容器80端口映射到主機8080端口,注意末尾不要加環境變量

docker run -itd -p 80:80 --name nginx nginx:latest    

 

b) 查看剛運行docker

docker ps -a

[root@localhost docker]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS                NAMES
0382dfbbd606        nginx:latest        "nginx -g 'daemon of…"   5 seconds ago       Up 4 seconds               0.0.0.0:80->80/tcp   nginx

 

c) 進入容器

docker exec -it nginx /bin/sh,並在 容器內部編輯網頁文件 index.html

 

# cd /usr/share/nginx/
# ls
html
# cd html   
# ls
50x.html  index.html
# echo '123' > index.html

 

e)到宿主機上打開瀏覽器輸入 IP:PORT 訪問驗證

http://192.168.253.9:80

 

 

一些報錯:

1)[root@localhost /]# docker run -itd --name busy busybox:latest /bin/bash
e105747eb16e52da2637379d75e221f46812955c929696234abbf1321fd56da3
docker: Error stat /bin/bash: no such file or directory": unknown

這是因為環境變量不可用,換成/bin/sh或者不加環境變量

 

2)[root@localhost /]# docker run -itd --name busy busybox:latest /bin/sh
docker: Error response from daemon: Conflict. The container name "/busy" is already in use by container "e105747eb16e52da2637379d75e221f46812955c929696234abbf1321fd56da3". You have to remove (or rename) that container to be able to reuse that name.

這是因為容器名已經存在,需要刪除已經存在的容器名

 

3)[root@localhost /]# docker network create --driver bridge my-net2
Error networks have overlapping IPv4

這是因為網橋沖突,刪除沖突的網橋。
brctl delbr 網橋
systemctl restart docker

 

4)error:executable file not found in $PATH": unknown
這是因為命令的順序錯誤

 

5)root@localhost /]# docker run -it --network=my-net3 --ip 192.168.253.13 busybox:latest /bin/sh
docker: Error response from daemon: Invalid address 192.168.253.13: It does not belong to any of this network's subnets.
這是因為自定義的ip不在可使用ip的范圍內。

6)Error No chain/target/match by that name.
這是因為沒有重啟docker,或者關閉firewalld和iptables(不建議)

 

7)docker: Error response from daemon: driver failed programming external connectivity on endpoint vibrant_kepler (0838e9c00e2ffcec24bbd333000cc4de9bd0fa2420c1c330ddb77dfd9d1d534f): Bind for 192.168.253.9:5000 failed: port is already allocated.

這是因為宿主機的端口已經被別的服務占用。

 

8)宿主機映射到容器之后,使用宿主機ip:port來訪問容器的httpd或者nginx服務

報錯連接被拒絕

這是因為端口映射的時候加入了環境變量,去掉環境變量即可。

 

網絡排查命令:

iptables -t nat -L

ip r

tcpdump -i docker0 -n icmp

 

tcpdump -i eth0 -n icmp

 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM