7、docker之容器通信

docker之容器通信

這節(jié)屬于了解學習,算是爛尾,最后我也沒找到合適的方式去固定容器ip,然后作為正式環(huán)境去跑,希望有解決辦法的私信,帶帶我這渣渣。

1、docker的網(wǎng)絡配置介紹

1.1 引子

當 Docker 啟動時,會自動在主機上創(chuàng)建一個 docker0 虛擬網(wǎng)橋,實際上是 Linux 的一個bridge,可以理解為一個軟件交換機。它會在掛載到它的網(wǎng)口之間進行轉發(fā)。

同時,Docker 隨機分配一個本地未占用的私有網(wǎng)段( 在 RFC1918 中定義) 中的一個地址給docker0 接口。比如典型的 172.17.42.1 ,掩碼為 255.255.0.0 。此后啟動的容器內的網(wǎng)口也會自動分配一個同一網(wǎng)段(172.17.0.0/16 ) 的地址。

當創(chuàng)建一個 Docker 容器的時候,同時會創(chuàng)建了一對 veth pair 接口(當數(shù)據(jù)包發(fā)送到一個接口時,另外一個接口也可以收到相同的數(shù)據(jù)包)。這對接口一端在容器內,即 eth0 ;另一端在本地并被掛載到 docker0 網(wǎng)橋,名稱以 veth 開頭( 例如 vethAQI2QT ) 。通過這種方式,主機可以跟容器通信,容器之間也可以相互通信。Docker 就創(chuàng)建了在主機和所有容器之間一個虛擬共享網(wǎng)絡。

以上摘自《docker入門到實踐》。

docker一般完成網(wǎng)絡配置過程如下:

  • 1、在主機上創(chuàng)建一對虛擬網(wǎng)卡veth pair設備。veth設備總是成對出現(xiàn)的,它們組成了一個數(shù)據(jù)的通道,數(shù)據(jù)從一個設備進入,就會從另一個設備出來。因此,veth設備常用來連接兩個網(wǎng)絡設備。

  • 2、Docker將veth pair設備的一端放在新創(chuàng)建的容器中,并命名為eth0。另一端放在主機中,以veth65f9這樣類似的名字命名,并將這個網(wǎng)絡設備加入到docker0網(wǎng)橋中,可以通過brctl show命令查看。

  • 3、從docker0子網(wǎng)中分配一個IP給容器使用,并設置docker0的IP地址為容器的默認網(wǎng)關。

1.2 docker網(wǎng)絡配置簡介

兩張圖開宗明義:

docker之網(wǎng)絡配置
一張圖理解docker網(wǎng)絡通信細節(jié)

docker通過使用linux橋接提供容器之間的通信,docker0橋接接口的目的就是方便docker管理。當docker daemon啟動時,需要做如下操作:

  • 1、如果docker0不存在則創(chuàng)建。
  • 2、搜索一個與當前路由不沖突的ip段。
  • 3、在確定的路由中選擇一個ip。
  • 4、綁定ip到docker0。

1.2.1 docker的四種網(wǎng)絡模式

docker run創(chuàng)建docker容器時,可以用--net選項指定容器的網(wǎng)絡模式,docker有以下4種網(wǎng)絡模式:

  • 1、host模式,使用--net=host指定。
  • 2、container模式,使用--net=container:name or id指定。
  • 3、none模式,使用--net=none指定。
  • 4、bridge模式,使用--net=bridge指定,默認設置。

1、host模式

如果啟動容器的時候使用 host 模式,那么這個容器將不會獲得一個獨立的 Network Namespace,而是和宿主機共用一個 Network Namespace。容器將不會虛擬出自己的網(wǎng)卡,配置自己的 IP 等,而是使用宿主機的 IP 和端口。

比如:我們在 10.10.101.105/24 的機器上用 host 模式啟動一個含有 web 應用的 Docker 容器,監(jiān)聽 tcp 80 端口。當我們在容器中執(zhí)行任何類似 ifconfig 命令查看網(wǎng)絡環(huán)境時,看到的都是宿主機上的信息。而外界訪問容器中的應用,則直接使用 10.10.101.105:80 即可,不用任何 NAT 轉換,就如直接跑在宿主機中一樣。但是,容器的其他方面,如文件系統(tǒng)、進程列表等還是和宿主機隔離的。

2、container模式

這個模式下指定新創(chuàng)建的容器和已經存在的容器共享一個 Network Namespace,而不是和宿主機共享。新創(chuàng)建的容器不會創(chuàng)建自己的網(wǎng)卡,配置自己的 IP,而是和一個指定的容器共享 IP、端口范圍等。同樣,兩個容器除了網(wǎng)絡方面,其他的如文件系統(tǒng)、進程列表等還是隔離的。兩個容器的進程可以通過 lo 網(wǎng)卡設備通信。

3、none模式

這個模式和前兩個不同。在這種模式下,Docker 容器擁有自己的 Network Namespace,但是,并不為 Docker容器進行任何網(wǎng)絡配置。也就是說,這個 Docker 容器沒有網(wǎng)卡、IP、路由等信息。需要我們自己為 Docker 容器添加網(wǎng)卡、配置 IP 等。

4、bridge模式

docker橋接模式示意圖

bridge 模式是 Docker 默認的網(wǎng)絡設置,此模式會為每一個容器分配 Network Namespace、設置 IP 等,并將一個主機上的 Docker 容器連接到一個虛擬網(wǎng)橋上。當 Docker server 啟動時,會在主機上創(chuàng)建一個名為 docker0 的虛擬網(wǎng)橋,此主機上啟動的 Docker 容器會連接到這個虛擬網(wǎng)橋上。虛擬網(wǎng)橋的工作方式和物理交換機類似,這樣主機上的所有容器就通過交換機連在了一個二層網(wǎng)絡中。接下來就要為容器分配 IP 了,Docker 會從 RFC1918 所定義的私有 IP 網(wǎng)段中,選擇一個和宿主機不同的IP地址和子網(wǎng)分配給 docker0,連接到 docker0 的容器就從這個子網(wǎng)中選擇一個未占用的 IP 使用。如一般 Docker 會使用 172.17.0.0/16 這個網(wǎng)段,并將 172.17.42.1/16 分配給 docker0 網(wǎng)橋(在主機上使用 ifconfig 命令是可以看到 docker0 的,可以認為它是網(wǎng)橋的管理接口,在宿主機上作為一塊虛擬網(wǎng)卡使用)。

osi模型之網(wǎng)橋所在

Linux虛擬網(wǎng)橋的特點:可以設置IP地址和相當于擁有一個隱藏的虛擬網(wǎng)卡。

docker0的地址劃分:

  • IP:172.17.42.1 子網(wǎng)掩碼: 255.255.0.0
  • MAC: 02:42:ac:11:00:00 到 02:42:ac:11:ff:ff
  • 總共提供65534個地址

docker守護進程在一個容器啟動時,實際上它要創(chuàng)建網(wǎng)絡連接的兩端。一端是在容器中的網(wǎng)絡設備,而另一端是在運行docker守護進程的主機上打開一個名為veth*的一個接口,用來實現(xiàn)docker這個網(wǎng)橋與容器的網(wǎng)絡通信。

docker網(wǎng)橋的容器通信示意

需要查看網(wǎng)橋,需要linux的網(wǎng)橋管理程序。

a、列出當前主機網(wǎng)橋

# brctl工具依賴bridge-utils軟件包
[root@localhost wwwroot]# brctl show                        
bridge name         bridge id               STP enabled         interfaces
br-e58510118e72     8000.0242a50841cb       no                  veth20851a5
                                                                veth3a6c445
                                                                veth4517766
                                                                veth754cbe0
                                                                vethc04b11d
docker0             8000.02426826e832       no

我這里兩個網(wǎng)橋,因為前期測試docker時跑的。現(xiàn)在docker應用的應該是br-e58510118e72這個。

b、查看當前docker0 ip

[root@localhost wwwroot]# ifconfig docker0
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:68ff:fe26:e832  prefixlen 64  scopeid 0x20<link>
        ether 02:42:68:26:e8:32  txqueuelen 0  (Ethernet)
        RX packets 77211  bytes 7411283 (7.0 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 97645  bytes 146953204 (140.1 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

我這里用這個。

[root@localhost wwwroot]# ifconfig br-e58510118e72
br-e58510118e72: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.18.0.1  netmask 255.255.0.0  broadcast 0.0.0.0
        inet6 fe80::42:a5ff:fe08:41cb  prefixlen 64  scopeid 0x20<link>
        ether 02:42:a5:08:41:cb  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

在容器運行時,每個容器都會分配一個特定的虛擬機口并橋接到 docker0。每個容器都會配置同 docker0 ip 相同網(wǎng)段的專用 ip 地址,docker0 的 IP 地址被用于所有容器的默認網(wǎng)關。

c、運行一個容器

我已經運行過容器了,直接查看。

[root@localhost wwwroot]# docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                                NAMES
78032ccab6ce        lnmp_php7.1         "docker-php-entryp..."   3 days ago          Up 2 days           0.0.0.0:9000->9000/tcp                                               php7.1
87c41d6edb03        nginx:1.13          "nginx -g 'daemon ..."   3 days ago          Up 3 days           0.0.0.0:80->80/tcp, 0.0.0.0:1200->1200/tcp, 0.0.0.0:2334->2334/tcp   nginx1.13
1108c87e77d5        mysql:5.7           "docker-entrypoint..."   6 days ago          Up 3 days           0.0.0.0:3306->3306/tcp                                               mysql5.7
7a78d89243ec        redis:3.2           "docker-entrypoint..."   6 days ago          Up 3 days           0.0.0.0:6379->6379/tcp                                               redis3.2
6e92745e8d1d        memcached:1.5       "docker-entrypoint..."   6 days ago          Up 3 days           0.0.0.0:11211->11211/tcp                                             memcached1.5

進去到php7.1的容器。

[root@localhost wwwroot]# docker exec -it php7.1 bash
# 未安裝網(wǎng)絡工具
root@78032ccab6ce:/www# ifconfig
bash: ifconfig: command not found
# 安裝工具包
root@78032ccab6ce:/www# apt-get install -y net-tools
root@78032ccab6ce:/www# ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:ac:12:00:06  
          inet addr:172.18.0.6  Bcast:0.0.0.0  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:21402 errors:0 dropped:0 overruns:0 frame:0
          TX packets:19027 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:14162531 (13.5 MiB)  TX bytes:2590738 (2.4 MiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:2 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:138 (138.0 B)  TX bytes:138 (138.0 B)

root@78032ccab6ce:/www# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.18.0.1      0.0.0.0         UG    0      0        0 eth0
172.18.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth0

docker已經自動創(chuàng)建了eth0的網(wǎng)卡,注意觀察ip地址為172.18.0.6和mac地址為02:42:ac:12:00:06。

對應我們的網(wǎng)橋列表中br-e58510118e72這個網(wǎng)橋的bridge id為8000.0242a50841cb(好像看不出具體對應那個接口,這里待補充)。

列出查看當前的網(wǎng)絡詳細信息,做參考。

[root@localhost wwwroot]# ifconfig
br-e58510118e72: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.18.0.1  netmask 255.255.0.0  broadcast 0.0.0.0
        inet6 fe80::42:a5ff:fe08:41cb  prefixlen 64  scopeid 0x20<link>
        ether 02:42:a5:08:41:cb  txqueuelen 0  (Ethernet)
        RX packets 2179  bytes 244717 (238.9 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2450  bytes 367035 (358.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:68ff:fe26:e832  prefixlen 64  scopeid 0x20<link>
        ether 02:42:68:26:e8:32  txqueuelen 0  (Ethernet)
        RX packets 77211  bytes 7411283 (7.0 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 97645  bytes 146953204 (140.1 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eno16777984: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.8.234  netmask 255.255.255.0  broadcast 192.168.8.255
        inet6 fe80::20c:29ff:fedb:d7ec  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:db:d7:ec  txqueuelen 1000  (Ethernet)
        RX packets 138519263  bytes 11725473088 (10.9 GiB)
        RX errors 0  dropped 62  overruns 0  frame 0
        TX packets 132204961  bytes 7687001119 (7.1 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 9802  bytes 63063666 (60.1 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 9802  bytes 63063666 (60.1 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth4517766: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::9811:fdff:feac:90e2  prefixlen 64  scopeid 0x20<link>
        ether 9a:11:fd:ac:90:e2  txqueuelen 0  (Ethernet)
        RX packets 678  bytes 213173 (208.1 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 837  bytes 193940 (189.3 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth20851a5: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::28e8:dbff:fefa:53dd  prefixlen 64  scopeid 0x20<link>
        ether 2a:e8:db:fa:53:dd  txqueuelen 0  (Ethernet)
        RX packets 19027  bytes 2590738 (2.4 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 21402  bytes 14162531 (13.5 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth3a6c445: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::9ca3:4eff:feb8:2eed  prefixlen 64  scopeid 0x20<link>
        ether 9e:a3:4e:b8:2e:ed  txqueuelen 0  (Ethernet)
        RX packets 3101  bytes 3877321 (3.6 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3438  bytes 1711375 (1.6 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth754cbe0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::dc02:3aff:feec:628b  prefixlen 64  scopeid 0x20<link>
        ether de:02:3a:ec:62:8b  txqueuelen 0  (Ethernet)
        RX packets 2179  bytes 244717 (238.9 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2450  bytes 367035 (358.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

vethc04b11d: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::4424:62ff:fe28:c1b1  prefixlen 64  scopeid 0x20<link>
        ether 46:24:62:28:c1:b1  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 50  bytes 3132 (3.0 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

上面可以看出 br-e58510118e72 扮演著幾個容器的虛擬接口veth* interface 橋接的角色。

1.2.2 容器使用特定范圍的ip

Docker 會嘗試尋找沒有被主機使用的 ip 段,盡管它適用于大多數(shù)情況下,但是它不是萬能的,有時候我們還是需要對ip進一步規(guī)劃。

Docker允許你管理docker0橋接或者通過-b選項自定義橋接網(wǎng)卡,需要安裝bridge-utils軟件包。

基本步驟如下:

  • 1、確保docker的進程是停止的。
  • 2、創(chuàng)建自定義網(wǎng)橋。
  • 3、給網(wǎng)橋分配特定的ip。
  • 4、以-b的方式指定網(wǎng)橋。

下面這段代碼未嘗試,供借鑒。

[root@localhost wwwroot]# service docker stop
[root@localhost wwwroot]# ip link set dev docker0 down
[root@localhost wwwroot]# brctl delbr docker0
[root@localhost wwwroot]# brctl addbr bridge0
[root@localhost wwwroot]# ip addr add 192.168.5.1/24 dev bridge0
[root@localhost wwwroot]# ip link set dev bridge0 up
[root@localhost wwwroot]# ip addr show bridge0
[root@localhost wwwroot]# 'DOCKER_OPTS="-b=bridge0"' >> /etc/default/docker
[root@localhost wwwroot]# service docker start

1.2.3 不同主機之間容器的通信

以上的容器通信都是基于單機的容器使用,那么不同主機的容器之間的通信可以借助于 pipework 這個工具。

1、安裝pipework

[root@localhost wwwroot]# git clone https://github.com/jpetazzo/pipework.git

報錯的話就更新下軟件包。

yum update nss curl libcurl  # nss為名稱解析和認證服務 curl為網(wǎng)絡請求庫

添加到用戶指令。

[root@localhost wwwroot]# cp -rp pipework/pipework /usr/local/bin/
[root@localhost wwwroot]# pipework
Syntax:
pipework <hostinterface> [-i containerinterface] [-l localinterfacename] [-a addressfamily] <guest> <ipaddr>/<subnet>[@default_gateway] [macaddr][@vlan]
pipework <hostinterface> [-i containerinterface] [-l localinterfacename] <guest> dhcp [macaddr][@vlan]
pipework route <guest> <route_command>
pipework rule <guest> <rule_command>
pipework tc <guest> <tc_command>
pipework --wait [-i containerinterface]

2、pipework指定容器ip

如果刪除了默認的 docker0 橋接,把 docker 默認橋接指定到了 br0,則最好在創(chuàng)建容器的時候加上--net=none,防止自動分配的 IP 在局域網(wǎng)中有沖突。

[root@localhost wwwroot]# pipework br0 -i eth0 a46657528059 192.168.115.10/24@192.168.115.2
# 默認不指定網(wǎng)卡設備名,則默認添加為 eth1
# 另外 pipework 不能添加靜態(tài)路由,如果有需求則可以在 run 的時候加上 --privileged=true 權限在容器中手動添加,
# 但這種安全性有缺陷,可以通過 ip netns 操作

使用ip netns添加靜態(tài)路由,避免創(chuàng)建容器使用--privileged=true選項造成一些不必要的安全問題:

[root@localhost wwwroot]# docker inspect --format="{{ .State.Pid }}" a46657528059 # 獲取指定容器 pid
[root@localhost wwwroot]# ln -s /proc/6350/ns/net /var/run/netns/6350
[root@localhost wwwroot]# ip netns exec 6350 ip route add 192.168.0.0/16 dev eth0 via 192.168.115.2
[root@localhost wwwroot]# ip netns exec 6350 ip route    # 添加成功
[root@localhost wwwroot]# 192.168.0.0/16 via 192.168.115.2 dev eth0

這節(jié)未測試,之后自己測試爬坑再修改。

pipework官檔

docker網(wǎng)絡詳解及pipework源碼解讀與實踐

此篇博文原出處:docker基礎介紹

2、docker的通信設置工具(Pipework和Open vSwitch)

2.1 再次細說docker的四種網(wǎng)絡模式

一張圖開宗明義。

docker容器通信模式對比

南北向通信指容器與宿主機外界的訪問機制,東西向流量指同一宿主機上,與其他容器相互訪問的機制。

2.1.1 host模式

由于容器和宿主機共享同一個網(wǎng)絡命名空間,換言之,容器的IP地址即為宿主機的IP地址。所以容器可以和宿主機一樣,使用宿主機的任意網(wǎng)卡,實現(xiàn)和外界的通信。

容器通信host模式示意

采用host模式的容器,可以直接使用宿主機的IP地址與外界進行通信,若宿主機具有公有IP,那么容器也擁有這個公有IP。同時容器內服務的端口也可以使用宿主機的端口,

無需額外進行NAT轉換,而且由于容器通信時,不再需要通過linux bridge等方式轉發(fā)或者數(shù)據(jù)包的拆封,性能上有很大優(yōu)勢。

當然,這種模式有優(yōu)勢,也就有劣勢,主要包括以下幾個方面:

  • 最明顯的就是容器不再擁有隔離、獨立的網(wǎng)絡棧。容器會與宿主機競爭網(wǎng)絡棧的使用,并且容器的崩潰就可能導致宿主機崩潰,在生產環(huán)境中,這種問題可能是不被允許的。
  • 容器內部將不再擁有所有的端口資源,因為一些端口已經被宿主機服務、bridge模式的容器端口綁定等其他服務占用掉了。

2.1.2 bridge模式

bridge模式是docker默認的,也是開發(fā)者最常使用的網(wǎng)絡模式。在這種模式下,docker為容器創(chuàng)建獨立的網(wǎng)絡棧,保證容器內的進程使用獨立的網(wǎng)絡環(huán)境,實現(xiàn)容器之間、容器與宿主機之間的網(wǎng)絡棧隔離。同時,通過宿主機上的docker0網(wǎng)橋,容器可以與宿主機乃至外界進行網(wǎng)絡通信。

容器通信bridge模式示意

從上面的網(wǎng)絡模型可以看出,容器從原理上是可以與宿主機乃至外界的其他機器通信的。同一宿主機上,容器之間都是連接掉docker0這個網(wǎng)橋上的,它可以作為虛擬交換機使容器可以相互通信。

然而,由于宿主機的IP地址與容器veth pair的 IP地址均不在同一個網(wǎng)段,故僅僅依靠veth pair和namespace的技術,還不足以使宿主機以外的網(wǎng)絡主動發(fā)現(xiàn)容器的存在。為了使外界可以訪問容器中的進程,docker采用了端口綁定的方式,也就是通過iptables的NAT,將宿主機上的端口端口流量轉發(fā)到容器內的端口上。

舉一個簡單的例子,使用下面的命令創(chuàng)建容器,并將宿主機的3306端口綁定到容器的3306端口:

docker run -tid --name db -p 3306:3306 MySQL

在宿主機上,可以通過iptables -t nat -L -n,查到一條DNAT規(guī)則:

DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:3306 to:172.17.0.5:3306

上面的172.17.0.5即為bridge模式下,創(chuàng)建的容器IP。

很明顯,bridge模式的容器與外界通信時,必定會占用宿主機上的端口,從而與宿主機競爭端口資源,對宿主機端口的管理會是一個比較大的問題。同時,由于容器與外界通信是基于三層上iptables NAT,性能和效率上的損耗是可以預見的。

2.1.3 none模式

在這種模式下,容器有獨立的網(wǎng)絡棧,但不包含任何網(wǎng)絡配置,只具有l(wèi)o這個loopback網(wǎng)卡用于進程通信。也就是說,none模式為容器做了最少的網(wǎng)絡設置。

但是俗話說得好“少即是多”,在沒有網(wǎng)絡配置的情況下,通過第三方工具或者手工的方式,開發(fā)這任意定制容器的網(wǎng)絡,提供了最高的靈活性。

2.1.4 container模式

其他網(wǎng)絡模式是docker中一種較為特別的網(wǎng)絡的模式。在這個模式下的容器,會使用其他容器的網(wǎng)絡命名空間,其網(wǎng)絡隔離性會處于bridge橋接模式與host模式之間。

當容器共享其他容器的網(wǎng)絡命名空間,則在這兩個容器之間不存在網(wǎng)絡隔離,而它們又與宿主機以及除此之外其他的容器存在網(wǎng)絡隔離。

容器通信container模式

2.1.5 用戶自定義網(wǎng)絡模式(參考)

在用戶定義網(wǎng)絡模式下,開發(fā)者可以使用任何docker支持的第三方網(wǎng)絡driver來定制容器的網(wǎng)絡。并且,docker 1.9以上的版本默認自帶了bridge和overlay兩種類型的自定義網(wǎng)絡driver。可以用于集成calico、weave、openvswitch等第三方廠商的網(wǎng)絡實現(xiàn)。

除了docker自帶的bridge driver,其他的幾種driver都可以實現(xiàn)容器的跨主機通信。而基于bdrige driver的網(wǎng)絡,docker會自動為其創(chuàng)建iptables規(guī)則,保證與其他網(wǎng)絡之間、與docker0之間的網(wǎng)絡隔離。

例如,使用下面的命令創(chuàng)建一個基于bridge driver的自定義網(wǎng)絡:

docker network create bri1

則docker會自動生成如下的iptables規(guī)則,保證不同網(wǎng)絡上的容器無法互相通信。

 -A DOCKER-ISOLATION -i br-8dba6df70456 -o docker0 -j DROP
 -A DOCKER-ISOLATION -i docker0 -o br-8dba6df70456 -j DROP

除此之外,bridge driver的所有行為都和默認的bridge模式完全一致。而overlay及其他driver,則可以實現(xiàn)容器的跨主機通信。

2.2 docker容器之間的通信(待實踐)

2.2.1 同主機容器通信

早期大家的跨主機通信方案主要有以下幾種:

  • 1、容器使用host模式:容器直接使用宿主機的網(wǎng)絡,這樣天生就可以支持跨主機通信。雖然可以解決跨主機通信問題,但這種方式應用場景很有限,容易出現(xiàn)端口沖突,也無法做到隔離網(wǎng)絡環(huán)境,一個容器崩潰很可能引起整個宿主機的崩潰。
  • 2、端口綁定:通過綁定容器端口到宿主機端口,跨主機通信時,使用主機IP+端口的方式訪問容器中的服務。顯而易見,這種方式僅能支持網(wǎng)絡棧的四層及以上的應用,并且容器與宿主機緊耦合,很難靈活的處理,可擴展性不佳。
  • 3、docker外定制容器網(wǎng)絡:在容器通過docker創(chuàng)建完成后,然后再通過修改容器的網(wǎng)絡命名空間來定義容器網(wǎng)絡。典型的就是很久以前的pipework,容器以none模式創(chuàng)建,pipework通過進入容器的網(wǎng)絡命名空間為容器重新配置網(wǎng)絡,這樣容器網(wǎng)絡可以是靜態(tài)IP、vxlan網(wǎng)絡等各種方式,非常靈活,容器啟動的一段時間內會沒有IP,明顯無法在大規(guī)模場景下使用,只能在實驗室中測試使用。
  • 4、第三方SDN定義容器網(wǎng)絡:使用Open vSwitch或Flannel等第三方SDN工具,為容器構建可以跨主機通信的網(wǎng)絡環(huán)境。這些方案一般要求各個主機上的docker0網(wǎng)橋的cidr不同,以避免出現(xiàn)IP沖突的問題,限制了容器在宿主機上的可獲取IP范圍。并且在容器需要對集群外提供服務時,需要比較復雜的配置,對部署實施人員的網(wǎng)絡技能要求比較高。

上面這些方案有各種各樣的缺陷,同時也因為跨主機通信的迫切需求,docker 1.9版本時,官方提出了基于vxlan的overlay網(wǎng)絡實現(xiàn),原生支持容器的跨主機通信。同時,還支持通過libnetwork的
plugin機制擴展各種第三方實現(xiàn),從而以不同的方式實現(xiàn)跨主機通信。就目前社區(qū)比較流行的方案來說,跨主機通信的基本實現(xiàn)方案有以下幾種:

  • 1、基于隧道的overlay網(wǎng)絡:按隧道類型來說,不同的公司或者組織有不同的實現(xiàn)方案。docker原生的overlay網(wǎng)絡就是基于vxlan隧道實現(xiàn)的。ovn則需要通過geneve或者stt隧道來實現(xiàn)的。flannel
    最新版本也開始默認基于vxlan實現(xiàn)overlay網(wǎng)絡。
  • 2、基于包封裝的overlay網(wǎng)絡:基于UDP封裝等數(shù)據(jù)包包裝方式,在docker集群上實現(xiàn)跨主機網(wǎng)絡。典型實現(xiàn)方案有weave、flannel的早期版本。
  • 3、基于三層實現(xiàn)SDN網(wǎng)絡:基于三層協(xié)議和路由,直接在三層上實現(xiàn)跨主機網(wǎng)絡,并且通過iptables實現(xiàn)網(wǎng)絡的安全隔離。典型的方案為Project Calico。同時對不支持三層路由的環(huán)境,Project Calico還提供了基于IPIP封裝的跨主機網(wǎng)絡實現(xiàn)。

1、創(chuàng)建主機使用特定范圍內的ip

Docker 會嘗試尋找沒有被主機使用的ip段,盡管它適用于大多數(shù)情況下,但是它不是萬能的,有時候我們還是需要對ip進一步規(guī)劃。
Docker允許你管理docker0橋接或者通過-b選項自定義橋接網(wǎng)卡,需要安裝bridge-utils軟件包。操作流程如下:

  • 1、確保docker的進程是停止的。
  • 2、創(chuàng)建自定義網(wǎng)橋。
  • 3、給網(wǎng)橋分配特定的ip。
  • 4、以-b的方式指定網(wǎng)橋。

具體操作過程如下(比如創(chuàng)建容器的時候,指定ip為192.168.5.1/24網(wǎng)段的):

[root@localhost ~]# service docker stop
[root@localhost ~]# ip link set dev docker0 down
[root@localhost ~]# brctl delbr docker0
[root@localhost ~]# brctl addbr bridge0
[root@localhost ~]# ip addr add 192.168.5.1/24 dev bridge0      //注意,這個192.168.5.1就是所建容器的網(wǎng)關地址。通過docker inspect container_id能查看到
[root@localhost ~]# ip link set dev bridge0 up
[root@localhost ~]# ip addr show bridge0
[root@localhost ~]# vim /etc/sysconfig/docker      //即將虛擬的橋接口由默認的docker0改為bridge0
將
OPTIONS='--selinux-enabled --log-driver=journald'
改為
OPTIONS='--selinux-enabled --log-driver=journald -b=bridge0'    //即添加-b=bridge0
  
[root@localhost ~]# service docker restart

可以利用pipework為容器指定一個固定的ip,操作方法非常簡單,如下:

[root@node1 ~]# brctl addbr br0
[root@node1 ~]# ip link set dev br0 up
[root@node1 ~]# ip addr add 192.168.114.1/24 dev br0                        //這個ip相當于br0網(wǎng)橋的網(wǎng)關ip,可以隨意設定。
[root@node1 ~]# docker run -ti -d --net=none --name=my-test1 docker.io/nginx /bin/bash
[root@node1 ~]# pipework br0 -i eth0 my-test1 192.168.114.100/24@192.168.114.1
 
[root@node1 ~]# docker exec -ti my-test1 /bin/bash
root@cf370a090f63:/# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
    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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
57: eth0@if58: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether b2:c1:8d:92:33:e2 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.114.100/24 brd 192.168.114.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::b0c1:8dff:fe92:33e2/64 scope link
       valid_lft forever preferred_lft forever
 
 
再啟動一個容器
[root@node1 ~]# docker run -ti -d --net=none --name=my-test2 docker.io/nginx /bin/bash
[root@node1 ~]# pipework br0 -i eth0 my-test12 192.168.114.200/24@192.168.114.1
[root@node1 ~]# pipework br0 -i eth0 my-test2 192.168.114.200/24@192.168.114.1

這樣,my-test1容器和my-test2容器在同一個宿主機上,所以它們固定后的ip是可以相互ping通的,如果是在不同的宿主機上,則就無法ping通!

所以說:這樣使用pipework指定固定ip的容器,在同一個宿主機下的容器間的ip是可以相互ping通的,但是跨主機的容器通過這種方式固定ip后就不能ping通了。

2.2.2 跨主機容器通信1

pipework等網(wǎng)絡工具的安裝之前有介紹,此處略去。

查看Docker宿主機上的橋接網(wǎng)絡

# brctl工具依賴bridge-utils軟件包
[root@localhost wwwroot]# brctl show                        
bridge name         bridge id               STP enabled         interfaces
docker0             8000.0242a50841cb       no                  veth20851a5
                                                                veth3a6c445
                                                                veth4517766
                                                                veth754cbe0
                                                                vethc04b11d

有兩種方式做法:

  • 1、可以選擇刪除docker0,直接把docker的橋接指定為br0;
  • 2、可以選擇保留使用默認docker0的配置,這樣單主機容器之間的通信可以通過docker0;跨主機不同容器之間通過pipework將容器的網(wǎng)卡橋接到br0上,這樣跨主機容器之間就可以通信了。

如果保留了docker0,則容器啟動時不加--net=none參數(shù),那么本機容器啟動后就是默認的docker0自動分配的ip(默認是172.17.1.0/24網(wǎng)段),它們之間是可以通信的;

跨宿主機的容器創(chuàng)建時要加--net=none參數(shù),待容器啟動后通過pipework給容器指定ip,這樣跨宿主機的容器ip是在同一網(wǎng)段內的同網(wǎng)段地址,因此可以通信。

一般來說:最好在創(chuàng)建容器的時候加上--net=none,防止自動分配的IP在局域網(wǎng)中有沖突。若是容器創(chuàng)建后自動獲取ip,下次容器啟動會ip有變化,可能會和物理網(wǎng)段中的ip沖突。

下面實例說明,我未操作,這里先借鑒。

宿主機信息
ip:192.168.1.23          (網(wǎng)卡設備為eth0)
gateway:192.168.1.1
netmask:255.255.255.0

1、刪除虛擬橋接卡docker0的配置

[root@localhost ~]# service docker stop
[root@localhost ~]# ip link set dev docker0 down
[root@localhost ~]# brctl delbr docker0
[root@localhost ~]# brctl addbr br0
[root@localhost ~]# ip link set dev br0 up
# 刪除宿主機網(wǎng)卡的IP(如果是使用這個地址進行的遠程連接,這一步操作后就會斷掉;如果是使用外網(wǎng)地址連接的話,就不會斷開)      
[root@localhost ~]# ip addr del 192.168.1.23/24 dev eth0
# 將宿主主機的ip設置到br0       
[root@localhost ~]# ip addr add 192.168.1.23/24 dev br0 
# 將宿主機網(wǎng)卡掛到br0上       
[root@localhost ~]# brctl addif br0 eth0 
# 刪除默認的原路由,其實就是eth0上使用的原路由192.168.1.1(這步小心,注意刪除后要保證機器能遠程連接上,最好是通過外網(wǎng)ip遠程連的。別刪除路由后,遠程連接不上,中斷了)                       
[root@localhost ~]# ip route del default       
# 為br0設置路由                
[root@localhost ~]# ip route add default via 192.168.1.1 dev br0  
# 即將虛擬的橋接口由默認的docker0改為bridge0,即添加-b=br0
[root@localhost ~]# vim /etc/sysconfig/docker                 
將
OPTIONS='--selinux-enabled --log-driver=journald'
改為
OPTIONS='--selinux-enabled --log-driver=journald -b=br0'    
[root@localhost ~]# service docker start

啟動一個手動設置網(wǎng)絡的容器

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
6e64eade06d1        docker.io/centos    "/bin/bash"         10 seconds ago      Up 9 seconds                            my-centos
[root@localhost ~]# docker run -itd --net=none --name=my-test1 docker.io/centos

為my-test1容器設置一個與橋接物理網(wǎng)絡同地址段的ip(如下,"ip@gateway")。默認不指定網(wǎng)卡設備名,則默認添加為eth0。可以通過-i參數(shù)添加網(wǎng)卡設備名。

[root@localhost ~]# pipework br0 -i eth0 my-test1 192.168.1.190/24@192.168.1.1

同理,在其他機器上啟動容器,并類似上面用pipework設置一個同網(wǎng)段類的ip,這樣跨主機的容器就可以相互ping通了!

2、保留默認虛擬橋接卡docker0的配置

[root@localhost ~]# cd /etc/sysconfig/network-scripts/
[root@localhost network-scripts]# cp ifcfg-eth0 ifcfg-eth0.bak
[root@localhost network-scripts]# cp ifcfg-eth0 ifcfg-br0
# 增加BRIDGE=br0,刪除IPADDR,NETMASK,GATEWAY,DNS的設置
[root@localhost network-scripts]# vim ifcfg-eth0            
......
BRIDGE=br0
# 修改DEVICE為br0,Type為Bridge,把eth0的網(wǎng)絡設置設置到這里來(里面應該有ip,網(wǎng)關,子網(wǎng)掩碼或DNS設置)
[root@localhost network-scripts]# vim ifcfg-br0 
......
TYPE=Bridge
DEVICE=br0
 
[root@localhost network-scripts]# service network restart    
[root@localhost network-scripts]# service docker restart

開啟一個容器并指定網(wǎng)絡模式為none(這樣,創(chuàng)建的容器就不會通過docker0自動分配ip了,而是根據(jù)pipework工具自定ip指定)。

[root@localhost network-scripts]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/centos    latest              67591570dd29        3 months ago        191.8 MB
[root@localhost network-scripts]# docker run -itd --net=none --name=my-centos docker.io/centos /bin/bash
6e64eade06d1eb20be3bd22ece2f79174cd033b59182933f7bbbb502bef9cb0f

接著給容器配置網(wǎng)絡。

[root@localhost network-scripts]# pipework br0 -i eth0 my-centos 192.168.1.150/24@192.168.1.1
[root@localhost network-scripts]# docker attach 6e64eade06d1
[root@6e64eade06d1 /]# ifconfig eth0                 //若沒有ifconfig命令,可以yum安裝net-tools工具
eth0      Link encap:Ethernet  HWaddr 86:b6:6b:e8:2e:4d
          inet addr:192.168.1.150  Bcast:0.0.0.0  Mask:255.255.255.0
          inet6 addr: fe80::84b6:6bff:fee8:2e4d/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:9 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:648 (648.0 B)  TX bytes:690 (690.0 B)

[root@6e64eade06d1 /]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.1.1     0.0.0.0         UG    0      0        0 eth0
192.168.115.0   0.0.0.0         255.255.255.0   U     0      0        0 eth0

另外pipework不能添加靜態(tài)路由,如果有需求則可以在run的時候加上--privileged=true 權限在容器中手動添加,但這種方法安全性有缺陷。
除此之外,可以通過ip netns(--help參考幫助)添加靜態(tài)路由,以避免創(chuàng)建容器使用--privileged=true選項造成一些不必要的安全問題:

如下獲取指定容器的pid。

[root@localhost network-scripts]# docker inspect --format="{{ .State.Pid }}" 6e64eade06d1
7852
[root@localhost network-scripts]# ln -s /proc/7852/ns/net /var/run/netns/7852
[root@localhost network-scripts]# ip netns exec 7852 ip route add 192.168.0.0/16 dev eth0 via 192.168.1.1
[root@localhost network-scripts]# ip netns exec 7852 ip route
192.168.0.0/16 via 192.168.1.1 dev eth0

同理,在其它宿主機進行相應的配置,新建容器并使用pipework添加虛擬網(wǎng)卡橋接到br0,如此創(chuàng)建的容器間就可以相互通信了。

2.2.3 跨主機容器通信2

除了上面使用的pipework工具還,還可以使用虛擬交換機(Open vSwitch)進行docker容器間的網(wǎng)絡通信,廢話不多說,下面說下Open vSwitch的使用。

1、在slave1和2上面分別安裝open vswitch

[root@Slave1 ~]# # yum -y install wget openssl-devel kernel-devel
[root@Slave1 ~]# yum groupinstall "Development Tools"
[root@Slave1 ~]# adduser ovswitch
[root@Slave1 ~]# su - ovswitch
[root@Slave1 ~]$ wget http://openvswitch.org/releases/openvswitch-2.3.0.tar.gz
[root@Slave1 ~]$ tar -zxvpf openvswitch-2.3.0.tar.gz
[root@Slave1 ~]$ mkdir -p ~/rpmbuild/SOURCES
[root@Slave1 ~]$ sed 's/openvswitch-kmod, //g' openvswitch-2.3.0/rhel/openvswitch.spec > openvswitch-2.3.0/rhel/openvswitch_no_kmod.spec
[root@Slave1 ~]$ cp openvswitch-2.3.0.tar.gz rpmbuild/SOURCES/
    
[root@Slave1 ~]$ rpmbuild -bb --without check ~/openvswitch-2.3.0/rhel/openvswitch_no_kmod.spec
    
[root@Slave1 ~]$ exit
    
[root@Slave1 ~]# yum localinstall /home/ovswitch/rpmbuild/RPMS/x86_64/openvswitch-2.3.0-1.x86_64.rpm
[root@Slave1 ~]# mkdir /etc/openvswitch
[root@Slave1 ~]# setenforce 0
[root@Slave1 ~]# systemctl start openvswitch.service
[root@Slave1 ~]# systemctl  status openvswitch.service -l

2、在slave1和2上建立OVS Bridge并配置路由

# 在slave1宿主機上設置docker容器內網(wǎng)ip網(wǎng)段172.17.1.0/24
[root@Slave1 ~]# vim /proc/sys/net/ipv4/ip_forward
1
[root@Slave1 ~]# ovs-vsctl add-br obr0
[root@Slave1 ~]# ovs-vsctl add-port obr0 gre0 -- set Interface gre0 type=gre options:remote_ip=192.168.115.5
    
[root@Slave1 ~]# brctl addbr kbr0
[root@Slave1 ~]# brctl addif kbr0 obr0
[root@Slave1 ~]# ip link set dev docker0 down
[root@Slave1 ~]# ip link del dev docker0
    
[root@Slave1 ~]# vim /etc/sysconfig/network-scripts/ifcfg-kbr0
ONBOOT=yes
BOOTPROTO=static
IPADDR=172.17.1.1
NETMASK=255.255.255.0
GATEWAY=172.17.1.0
USERCTL=no
TYPE=Bridge
IPV6INIT=no
    
[root@Slave1 ~]# vim /etc/sysconfig/network-scripts/route-ens32
172.17.2.0/24 via 192.168.115.6 dev ens32
  
[root@Slave1 ~]# systemctl  restart network.service


# 在slave2宿主機上設置docker容器內網(wǎng)ip網(wǎng)段172.17.2.0/24
[root@Slave2 ~]# vim /proc/sys/net/ipv4/ip_forward
1
[root@Slave2 ~]# ovs-vsctl add-br obr0
[root@Slave2 ~]# ovs-vsctl add-port obr0 gre0 -- set Interface gre0 type=gre options:remote_ip=192.168.115.6
   
[root@Slave2 ~]# brctl addbr kbr0
[root@Slave2 ~]# brctl addif kbr0 obr0
[root@Slave2 ~]# ip link set dev docker0 down
[root@Slave2 ~]# ip link del dev docker0
   
[root@Slave2 ~] vim /etc/sysconfig/network-scripts/ifcfg-kbr0
ONBOOT=yes
BOOTPROTO=static
IPADDR=172.17.2.1
NETMASK=255.255.255.0
GATEWAY=172.17.2.0
USERCTL=no
TYPE=Bridge
IPV6INIT=no
   
[root@Slave2 ~]# vim /etc/sysconfig/network-scripts/route-ens32
172.17.1.0/24 via 192.168.115.5 dev ens32
   
[root@Slave2 ~]# systemctl  restart network.service

3、啟動容器測試

slave1和2上修改docker啟動的虛擬網(wǎng)卡綁定為kbr0,重啟docker進程

a、在Server1宿主機上啟動容器,然具體操作過程如下后登陸容器內查看ip,就會發(fā)現(xiàn)ip是上面設定額172.17.1.0/24網(wǎng)段的。

[root@Slave1 ~]# docker run -idt --name my-server1 daocloud.io/library/centos/bin/bash

b、在Server2宿主機上啟動容器,然后登陸容器內查看ip,就會發(fā)現(xiàn)ip是上面設定額172.17.2.0/24網(wǎng)段的。

[root@Slave2 ~]#docker run -idt --name my-server1 daocloud.io/library/centos /bin/bash

然后在上面啟動的容內互ping對方容器,發(fā)現(xiàn)是可以ping通的。

2.3 工具介紹

2.3.1 ip 命令

ip 是 iproute2 工具包里面的一個命令行工具,用于配置網(wǎng)絡接口以及路由表。

iproute2 正在逐步取代舊的 net-tools(ifconfig),所以是時候學習下 iproute2 的使用方法啦。

參考地址:ip 命令用法歸納

2.3.2 pipework

pipework是Docker公司工程師Jerome Petazzoni在Github上發(fā)布的名為pipework的工具。號稱是容器網(wǎng)絡的SDN解決方案,可以在復雜的場景下將容器連接起來。它既支持普通的LXC容器,也支持Docker容器。

1、需求場景

在使用Docker的過程中,有時候我們會有將Docker容器配置到和主機同一網(wǎng)段的需求。要實現(xiàn)這個需求,我們只要將Docker容器和主機的網(wǎng)卡橋接起來,再給Docker容器配上IP就可以了。

2、安裝pipework

之前 1.2.3 小節(jié)已作介紹。

3、使用pipework

[root@localhost lnmp]# pipework
Syntax:
pipework <hostinterface> [-i containerinterface] [-l localinterfacename] [-a addressfamily] <guest> <ipaddr>/<subnet>[@default_gateway] [macaddr][@vlan]
pipework <hostinterface> [-i containerinterface] [-l localinterfacename] <guest> dhcp [macaddr][@vlan]
pipework route <guest> <route_command>
pipework rule <guest> <rule_command>
pipework tc <guest> <tc_command>
pipework --wait [-i containerinterface]

參考地址:pipework使用介紹

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,327評論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,996評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,316評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,406評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,128評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,524評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,576評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,759評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 49,310評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,065評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,249評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,821評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,479評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,909評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,140評論 1 290
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,984評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,228評論 2 375

推薦閱讀更多精彩內容

  • 轉載自 http://blog.opskumu.com/docker.html 一、Docker 簡介 Docke...
    極客圈閱讀 10,520評論 0 120
  • 概述 自從docker容器出現(xiàn)以來,容器的網(wǎng)絡通信就一直是大家關注的焦點,也是生產環(huán)境的迫切需求。而容器的網(wǎng)絡通信...
    糙老爺們兒吃什么櫻桃閱讀 3,639評論 1 5
  • 五、Docker 端口映射 無論如何,這些 ip 是基于本地系統(tǒng)的并且容器的端口非本地主機是訪問不到的。此外,除了...
    R_X閱讀 1,776評論 0 7
  • 本文是篇翻譯。原文:https://docs.docker.com/engine/userguide/networ...
    周立_itmuch閱讀 908評論 0 4
  • Docker簡介1 什么是Docker2 為什么使用Docker3 Docker的安裝與啟動及常用命令4 Dock...
    lucus_guo閱讀 375評論 0 0